Re: spurious gc allocation
Indeed, disassembly reveals an allocation (with all three compilers = it's the front-end which generates this crap). I guess the compiler incorrectly treats { node.value; } as a delegate and copies the node to GC heap. void foo() { int* node = null; enum mutable = __traits(compiles, {node.value ;}); } void main() { foo(); }
Get variable symbol name that was passed to a paramater?
I have a template function called inspect that takes two variables as arguments, void inspect(T)( string symbol, T value ) { writeln(symbol, = , value); } int y = 100; inspect( y.stringof, y ); writes to console y = 100 I am wondering if there's a way to pass only the variable and have the inspect function determine the variable's symbol name as passed rather than have to pass both the name and value separately? void inspect(T)( T value ) { writeln( ? , = , value); } I've tried a template with alias parameter void inspect(alias value)() { writeln( value.stringof , = , value); } It works except when passing a variable contained inside a struct or class due to a missing this during evaluation, I'm also worried about template bloat. I figure mixins may help, but not if it's same or less convenient to use as the double entry method. Any suggestions, or is it just impossible or not worth trying? --rt
Re: spurious gc allocation
Ellery Newcomer: can anyone confirm? I only see the class instance allocation in the main(). I use two modules, with your code. I compile on Windows 32, using no compilation flags, and I see this asm, with obj2asm: _D1a1C13_InsertAllButMFiZv: pushEAX pushEAX mov [ESP],0 add ESP,8 ret 4 __Dmain: L0: mov EAX,offset FLAT:_D1a1C7__ClassZ pushEAX callnear ptr __d_newclass push1 mov ECX,[EAX] calldword ptr 014h[ECX] xor EAX,EAX add ESP,4 ret _main: L0: mov EAX,offset FLAT:__Dmain pushEAX pushdword ptr 0Ch[ESP] pushdword ptr 0Ch[ESP] callnear ptr __d_run_main add ESP,0Ch ret Bye, bearophile
Re: Get variable symbol name that was passed to a paramater?
On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote: It works except when passing a variable contained inside a struct or class due to a missing this during evaluation, I'm also worried about template bloat. I figure mixins may help, but not if it's same or less convenient to use as the double entry method. Any suggestions, or is it just impossible or not worth trying? I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement.
Re: spurious gc allocation
On 11/09/2013 12:35 AM, lomereiter wrote: Indeed, disassembly reveals an allocation (with all three compilers = it's the front-end which generates this crap). ouch. I guess the compiler incorrectly treats { node.value; } as a delegate and copies the node to GC heap. void foo() { int* node = null; enum mutable = __traits(compiles, {node.value ;}); } void main() { foo(); } oh, I see, it's the delegate doing that. that's helpful. https://d.puremagic.com/issues/show_bug.cgi?id=11483
Re: Question about function templates when parameter is void
On Saturday, 9 November 2013 at 07:11:50 UTC, Uranuz wrote: I have a question. In my code I want to make uniform template function to call JSON RPC methods (that are regular D functions of any type). So I need some way to call this function with no function params and with them in the same manner. There is a concrete example, because this description isn't obvious (I think that) // import std.stdio, std.json, std.conv, std.traits; JSONValue getStdJSON(T)(T dValue) { static if( is( T == void ) ) { JSONValue result; result.type = JSON_Type.NULL; return result; } else { // } } void f() { writeln(Hello!!); } void main() { writeln(getStdJSON(f())); } //-- Compilation output: /d661/f210.d(28): Error: template f210.getStdJSON does not match any function template declaration. Candidates are: /d661/f210.d(6):f210.getStdJSON(T)(T dValue) /d661/f210.d(28): Error: template f210.getStdJSON(T)(T dValue) cannot deduce template function from argument types !()(void) //--- So my question is how can I implement something like this? Problem is that we don't really have value of type void, but I want uniform way to call this function when it has parameter with concrete type and not. It seems odd to call a function as an argument which returns void. Surely you could just move that out and call it alone before the 'getStdJSON' call? Anyway to answer you question, i'd probably overload the 'getStdJSON' function.
Re: VC linker - unresolved external symbols - runtime
On Saturday, 9 November 2013 at 15:30:55 UTC, deed wrote: core.runtime's import path is specified in the sc.ini file, in DFLAGS If I specify the core.runtime file in the build file everything works Why is it so? in short - it looks like phobos.lib not linked, try link it manually. i don't know why...
Re: VC linker - unresolved external symbols - runtime
On Saturday, 9 November 2013 at 16:08:15 UTC, evilrat wrote: On Saturday, 9 November 2013 at 15:59:02 UTC, deed wrote: No, it doesn't work. Do I have to compile my own runtime library and pass it on the command line? (Have just grabbed the 3.064.2.zip file and not run any installer.) The readme file in the runtime directory says it's compiled into phobos64.lib, which I presume is passed successfully, otherwise there would have been more unresolved symbols.. better use installer, or you can try to set correct linker, mspdb dll, and lib paths in sc.ini for your visual c++ and windows sdk. phobos64.lib contains _D4core7runtime7Runtime10initializeFDFC6object9ThrowableZvZb but not _D4core7runtime7Runtime10initializeFZb Does this mean that the phobos64.lib is not aligned with current core.runtime module?
Re: is there a merge for associative arrays
On Tuesday, 5 November 2013 at 17:47:16 UTC, bearophile wrote: TV[TK] mergeAAs(TK, TV)(TV[TK] aas...) { It seems even fit for Phobos. Bye, bearophile I have something I would appreciate feedback/criticism on. My first stab at it worked, but had no support for passing in const/immutable. AA mergeAAs(alias fun = a + b, AA)(AA[] aas...) if(isAssociativeArray!AA) { AA result; ... } Not sure if this is a good way or if there are better idiomatic ways, but here is what I have got. Any suggestions/improvements to make it more idiomatic would be appreciated. Is there already a DeepUnqual equivalent in phobos? Thanks Dan import std.stdio; import std.traits; import std.algorithm; import std.functional; template DeepUnqual(T) { static if(isAssociativeArray!T) { alias Unqual!(Unqual!(ValueType!T)[Unqual!(KeyType!T)]) DeepUnqual; } else static if(isDynamicArray!T) { alias Unqual!(Unqual!(ArrayElementType!T)[]) DeepUnqual; } else static if(isPointer!T) { alias Unqual!(PointerTarget!T) * DeepUnqual; } else { alias Unqual!T DeepUnqual; } } DeepUnqual!AA mergeAAs(alias fun = a + b, AA)(AA[] aas...) if(isAssociativeArray!AA) { DeepUnqual!AA result; if(aas.length) { foreach( aa ; aas ) { foreach( k , v ; aa ) { auto found = k in result; if(found) { *found = binaryFun!fun(*found, v); } else { result[k] = v; } } } } return result; } void main() { alias double[string] AA; AA a = [ foo:1.1, bar:2.2 ]; AA b = [ foo:1.1, bard:2.2 ]; writeln(mergeAAs(a, b)); writeln(mergeAAs!q{a*b}(a, b)); { const AA ca = a.dup; const AA cb = b.dup; writeln(mergeAAs(ca,cb)); } { immutable AA ia = [ foo:1.1, bar:2.2 ]; immutable AA ib = [ foo:1.1, bard:2.2 ]; writeln(mergeAAs(ia,ib)); } }
Re: VC linker - unresolved external symbols - runtime
On Saturday, 9 November 2013 at 16:22:07 UTC, deed wrote: phobos64.lib contains _D4core7runtime7Runtime10initializeFDFC6object9ThrowableZvZb but not _D4core7runtime7Runtime10initializeFZb Does this mean that the phobos64.lib is not aligned with current core.runtime module? i also have this problem on win 8.1 with visual studio 2013. smells like a bug for me. file a bug on tracker. for now i think manually calling rt_init() and rt_term() can be used to avoid it.
Re: Get variable symbol name that was passed to a paramater?
On Saturday, 9 November 2013 at 11:07:08 UTC, Dicebot wrote: On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote: It works except when passing a variable contained inside a struct or class due to a missing this during evaluation, I'm also worried about template bloat. I figure mixins may help, but not if it's same or less convenient to use as the double entry method. Any suggestions, or is it just impossible or not worth trying? I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement. Do you know if there's already a enhancement request posted for this? I'll make one if not.
Re: How to compile and test samples under Windows?
This reminded me to come back to this (I was commenting on stack overflow a few days ago too). Spun up an XP box and now I can reproduce your problem. Strangely, the same exe and dll work on Vista computer still! But at least I can see the problem on XP so maybe I can help figure this out now
Re: How to compile and test samples under Windows?
Aaaand figured it out: actually, the fact it worked on Vista but not on XP was the key clue and I'm ashamed I didn't realize this earlier. This comment hints at it too in dserver.d // Multiple threads not supported yet Anyway, D's thread local storage doesn't quite work right on Windows XP, and does work beautifully on Vista and up. I don't really know why, but that's the way it is. It can cause invalid memory accesses... And the GUIDs and a couple other variables in the sample are thread local! (Back when the sample was written, global variables were truly global, like in C. Since then, that's changed, the variables are now in thread local storage unless you mark them with __gshared, which breaks things...) So here's the fix: add __gshared to a few places. dserver.d, line 119 give or take, there's some globals g_cObj etc: __gshared ULONG g_cObj =0; __gshared ULONG g_cLock=0; __gshared HINSTANCE g_hInst; chello.d, about line 24: __gshared GUID CLSID_Hello = { 0x30421140, 0, 0, [0xC0, 0, 0, 0, 0, 0, 0, 0x46] }; __gshared GUID IID_IHello = { 0x00421140, 0, 0, [0xC0, 0, 0, 0, 0, 0, 0, 0x46] }; (Actually, those could probably be immutable too, but meh just making it work.) Then recompile, remembering the libraries we talked about on stack overflow, and you get a new dll. On my computer, it actually came out 100KB smaller too, cool! Now, chello.exe runs and successfully creates the object. regsvr32.exe still fails though, on XP (works on Vista), I must still be missing something. But this is a lot closer already
Re: How to compile and test samples under Windows?
On Saturday, 9 November 2013 at 23:37:38 UTC, Adam D. Ruppe wrote: regsvr32.exe still fails though, on XP (works on Vista), I must still be missing something. But this is a lot closer already I fixed this by commenting out the call to gc_init in dserver.d's DllMain (thereabouts line 140). I don't know why it would work in dclient but not regsvr, maybe it has to do with threads again. Regardless though, comment that out and it registers. S yeah that's kinda messed up that this stuff doesn't just work, but at least you can make it work now, hopefully. let me know if it works on your computer too.
Re: Get variable symbol name that was passed to a paramater?
can your 'inspect' method handle: * multiple arguments? * expressions? I wrote a function that does both, it's one of those things that are very useful for quick debugging: import util.prettyprint; void main(){ int x=23; double y=2.4; writelnL(x,y,x*y); } //output: file test.d:7 { x=int{23}, y=double{2.4}, x*y=double{55.2}, } - The way it works: void writelnL(string file=__FILE__, Line_t line=__LINE__, T...)(T args){ ... auto argNames=getArgNamesFromFile(file,line); ... } This reads at runtime file/line and caches the information with memoize to avoid re-reading the same file/line multiple times. I had also tried reading the file/line at compile time using import(file)[line] but that resulted in massive compile time slow-downs even when the actual writelnL wasn't used at runtime. Then the code parses the line to extract each argument names using a simplified D grammar. However this still has some runtime penalty (reading a whole file just for 1 line) and is doing more work than necessary, as compiler has access to this info. I've already asked for this in the past (see email: feature request: __ARGS__ for logging (cf __FILE__, __LINE__, __FUNC___): but Jacob pointed out that AST macros would make this un-necessary (like wise with another proposal I made proposal: a new string litteral to embed variables in a string ): I don't think that __ARGS__ is a bad idea, I just think that there are several features in D which could be replaced with a library solution using AST macros (if those were available) So let's either get a roadmap for introducing AST macros (preferred) or let's allow this very simple __ARGS__ in the language. On Sat, Nov 9, 2013 at 11:05 AM, Rob T al...@ucora.com wrote: On Saturday, 9 November 2013 at 11:07:08 UTC, Dicebot wrote: On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote: It works except when passing a variable contained inside a struct or class due to a missing this during evaluation, I'm also worried about template bloat. I figure mixins may help, but not if it's same or less convenient to use as the double entry method. Any suggestions, or is it just impossible or not worth trying? I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement. Do you know if there's already a enhancement request posted for this? I'll make one if not.
Re: Get variable symbol name that was passed to a paramater?
On 11/09/2013 10:12 AM, Rob T wrote: I am wondering if there's a way to pass only the variable and have the inspect function determine the variable's symbol name as passed rather than have to pass both the name and value separately? ... Well, yes, but the following does not scale that well, and it is somewhat fragile, since there is no way to get column information. import std.stdio; import std.string; import std.algorithm; import std.range; import std.conv; template LineCache(string f){ enum LineCache = import(__FILE__).splitLines(); } void inspect(string f=__FILE__,int l=__LINE__,T)( T value ){ enum name=LineCache!__FILE__[l-1].find(inspect).drop(inspect.length).find(().drop(1).until!(a=a==')').to!string.strip; writeln(name ~ = , value); } void main(){ int a; int b=3; inspect(a); inspect(a+2); inspect(a+b); } $ dmd -J. -run tt.d a = 0 a+2 = 2 a+b = 3
Re: Get variable symbol name that was passed to a paramater?
On 11/10/2013 01:51 AM, Timon Gehr wrote: On 11/09/2013 10:12 AM, Rob T wrote: I am wondering if there's a way to pass only the variable and have the inspect function determine the variable's symbol name as passed rather than have to pass both the name and value separately? ... Well, yes, but the following does not scale that well, and it is somewhat fragile, since there is no way to get column information. import std.stdio; import std.string; import std.algorithm; import std.range; import std.conv; template LineCache(string f){ enum LineCache = import(__FILE__).splitLines(); } void inspect(string f=__FILE__,int l=__LINE__,T)( T value ){ enum name=LineCache!__FILE__[l-1].find(inspect).drop(inspect.length).find(().drop(1).until!(a=a==')').to!string.strip; ... Oops. There's a typo. It should read LineCache!f, obviously. writeln(name ~ = , value); } void main(){ int a; int b=3; inspect(a); inspect(a+2); inspect(a+b); } $ dmd -J. -run tt.d a = 0 a+2 = 2 a+b = 3
Shared data concurrency with SDL
Newbie here. I'm playing around with concurrency in D. Being new to both, I have no idea what I'm doing and am seeking your guidance! I'm using the D SDL wrapper (which is just a thin wrapper around the C library). I have the following threads: - the main program thread; the `control coordination` thread - SDL_Mixer has its own thread (which calls a callback I provide) - a thread to handle graphics Questions I'm seeking answers to: 1) I'm doing a lot of casting to/from shared which doesn't feel right. What should be I doing? Some of this seems unavoidable, as in the SDL callback postMixCallback() where I'm bound by the SDL_mixer library to provide a specific type signature. 2) A specific instance of 1). In my main(), I declare GraphicsState to be unshared. GraphicsState just holds on to a bunch of pointers returned by SDL initialization routines (which won't work on shared pointers). Then, in order to communicate with the graphics thread via send(), I cast the address of to a shared pointer. On the other end, I receive this shared pointer then cast to an unshared pointer and dereference. I do this because the pointer values in GraphicsState are passed pretty much exclusively to C functions which won't accept shared types. Seems awkward, no? My code (also at http://pastebin.com/SMC2e9Bx ) // Holds data the graphics thread needs // This is initialized in the main // thread then sent to the graphics thread // Cleanup is done by the main thread after // the graphics thread exits struct GraphicsState { SDL_Window* window; SDL_Renderer* renderer; SDL_Texture* texture; ImageSurface cairoSurface; ubyte* pixels; } // a simple ring buffer struct RingBuffer { ulong pos; short[] buffer; } void main() { // ... GraphicsState graphicsState; gfxInit(graphicsState); shared RingBuffer ringBuffer; ringBuffer.pos = 0; ringBuffer.buffer.length = audioConf.sample_f * audioConf.chunkSize; Mix_SetPostMix(finished, cast(void*)ringBuffer); Tid tid = spawn(doGfx); shared GraphicsState* sharedGfx = cast(shared GraphicsState*)graphicsState; send(tid, sharedGfx, cast(shared(RingBuffer*))ringBuffer); // ... } extern(C) void postMixCallback(void* udata, ubyte *stream, int len) { shared RingBuffer* buffer = cast(shared RingBuffer*)udata; short *samples = cast(short*)stream; // naive copy for (int i = 0; i len / short.sizeof; i += 2) { buffer.buffer[buffer.pos] = *(samples + i); auto nextPos = buffer.pos + 1; if (nextPos == buffer.buffer.length) { nextPos = 0; } buffer.pos = nextPos; } } void doGfx(AudioConf audioConf) { GraphicsState graphicsState; Mix_Chunk* beat; shared RingBuffer* ringBuffer; auto msg = receiveOnly!(shared(GraphicsState*), shared(RingBuffer*)); graphicsState = *(cast(GraphicsState*)msg[0]); ringBuffer = msg[1]; while (true) { // read from ring buffer // render } }