Re: Enumerating structs?
> Yeah, D feels like that to me too, sometimes. Anyways, for your question - > would using the struct name be good enough? They're easy to get hold of > and usable in switch statements. > > If not, how about this: > > > import std.typetuple; > > struct TypeEnum( T... ) { > static pure nothrow @property > int value( U )( ) { > static assert ( staticIndexOf!( U, T ) != -1 ); > return staticIndexOf!( U, T ); > } > } > > struct A {} > struct B {} > > void main( ) { > alias TypeEnum!(A, B) types; > > assert( types.value!A == 0 ); > assert( types.value!B == 1 ); > } Ha, yes, that looks quite nice! Thanks! /HF
Enumerating structs?
Hello! I have some structs struct A { int a; } struct B { int b, c; } and I'd like to be able to enumerate them (preferrably as integers) based on their names. I've no idea how this would look, but some pseudo code that would use this feature: // pseudo int type = stream.read!int(); switch(type){ case A.enumof: auto data = stream.read!A(); // ... break; case B.enumof: // ... break; // ... The idea here is to enable stuff like static if's etc and to enforce the connection between the struct and the enumeration. Right now I have a separate enums, like so: enum {A_ENUM = 1, B_ENUM = 2}; // ... case A_ENUM: auto data = stream.read!A(); // ... break; //... But this means the idea that struct A has the enumeration "1" is only by convention. So when I, for instance, refactor struct A to "C", all code still compiles. It would be cool if it didn't, somehow. With this small example it's of course not a problem, but for larger more complex code perhaps. A naive idea I had was to let each struct have an enum: struct A{ enum TYPE_ENUM = 1; int a; } That would be refactor-friendly and be a strong connection, but then there's no guarantee two structs don't have the same enum, of course. Another idea was to maybe use mixin to somehow construct the enum declaration: mixin enumByType!(A,B); That could generate code like: enum {A_ENUM = 1, ...} and then couple it with a // ... case typeEnumFor!A(): //... break; // ... but now it's starting to maybe feel a bit overkill? Is there an easier/correct/other way? - I usually end up feeling like this a lot with D, I just realized. It's like, yes, with mixins I can more or less do anything, but where does one stop? You know what I mean? I like it though. Mixin-paralysis : ) /HF
Re: Catching signals with D
On 12/22/11 23:51 , Matej Nanut wrote: Hello everyone, I've been fascinated by D lately and have been using it for all my school assignments (like simple ray casting and simulated annealing). What I can't find anywhere is how to do something like "signal(SIGINT, myhandler)" (I'm in a Linux environment). I need this to stop the annealing process early but still keep the current best result. Is there a better way to interrupt my program? Thanks! Matej P.s. I hope I sent this to the appropriate address. :) Hi! I don't know of any official way, but since D links against the c runtime you can just hook up functions from there, I believe. This works on osx at least: import std.stdio; extern(C) void signal(int sig, void function(int) ); // Our handler, callable by C extern(C) void handle(int sig){ writeln("Signal:",sig); } void main() { enum SIGINT = 2; // OS-specific signal(SIGINT,&handle); writeln("Hello!"); readln(); writeln("End!"); } $ rdmd sig.d Hello! ^CSignal:2 ^CSignal:2 End! $ _ /HF
Re: d2 file input performance
Christian Köstlin Wrote: > after some optimizing i got better, but was still way slower than c++. > so i started some small microbenchmarks regarding fileio: > https://github.com/gizmomogwai/performance in c++, java and d2. > > christian Hello! Thanks for you effort in putting this together! I found this interesting and played around with some of your code examples. My findings differ somewhat from yours, so I thought I'd post them. >From what I can tell, G++ does generate almost twice (~1.9x) as fast code, in >the fread()/File-example, as DMD. Even though the D-code does handle errors >encountered by fread(), that certainly can't explain the dramatic difference >in speed alone. It would be very interesting to see how GDC and LDC perform in these tests!! (I don't have them installed.) Anyway, here are my notes: I concentrated on the G++-fread-example and the DMD-File-example, as they seem comparable enough. However, I did some changes to the benchmark in order to "level" the playing field: 1) Made sure both C++ and D used a 1 kb (fixed-size) buffer 2) Made sure the underlying setvbuf() buffer is the same (64 kb) 3) Made sure the read data has an actual side effect by printing out the accumulated data after each file. (Cheapo CRC) The last point, 3, particularly seemed to make the G++-example considerably slower, perhaps hinting G++ is otherwise doing some clever optimization here. The second point, 2, seemed to have no effect on C++, but it helped somewhat for D. This may hint at C++ doing its own buffering or something. (?) In that case the benchmark is bogus. Anyway, these are the results: (G++ 4.2.1, fread()+crc, osx) G++ 1135 ms (no flags) G++ 399 ms -O1 G++ 368 ms -O2 G++ 368 ms -O3 G++nofx 156 ms -O3 (Disqualified!) (DMD 2.054, rawRead()+crc, osx) DMD 995 ms (no flags) DMD 913 ms -O DMD 888 ms -release DMD 713 ms -release -O -inline DMD 703 ms -release -O DMD 693 ms -release -O -inline -noboundscheck Well, I suppose a possible (and to me plausable) explanation is that G++'s optimizations are a lot more extensive than DMD's. Skipping printing out the CRC-value ("nofx") makes the C++ code more than twice as fast. Note that the code calculating the CRC-value is still in place, the value is just not printed out, and surely, calling printf() 10 times can hardly account for a 200 ms increase. (?) I think it's safe to assume code is simply being ignored here, as it's not having any side effect. My gut feel is DMD is not doing inlining, at least not to the same extent G++ is, as that seems to be especially important since we're making a function call for every single byte here. (Using the -inline flag even seems to make the D code slower. Weird.) But of course I don't really know. Again, GDC and LDC would be interesting to see here. Finally, to this I must add the size of the generated binary: G++ 15 kb DMD 882 kb Yikes. I believe there's nothing (large enough) to hide behind for DMD there. That's it! Kind regards /HF Here's the modifed code: (Original https://github.com/gizmomogwai/performance) // - - - - - - 8< - - - - - - import std.stdio, std.datetime, core.stdc.stdio; struct FileReader { private: File file; enum BUFFER_SIZE = 1024; ubyte[BUFFER_SIZE] readBuf; size_t pos, len; this(string name){ file = File(name, "rb"); //setbuf(file.getFP(), null); // No buffer setvbuf(file.getFP(), null, _IOFBF, BUFFER_SIZE * 64); } bool fillBuffer() { auto tmpBuf = file.rawRead(readBuf); len = tmpBuf.length; pos = 0; return len > 0; } public: int read() { if(pos == len){ if(fillBuffer() == false) return -1; } return readBuf[pos++]; } } size_t readBytes() { size_t count = 0; ulong crc = 0; for (int i=0; i<10; i++) { auto file = FileReader("/tmp/shop_with_ids.pb"); auto data = file.read(); while(data != -1){ count++; crc += data; data = file.read(); } writeln(crc); } return count; } int main(string[] args) { auto sw = StopWatch(AutoStart.no); sw.start(); auto count = readBytes(); sw.stop(); writeln("d2-6-B", count, "", sw.peek().msecs, "using s
Re: Create a foreach-able struct? Multi-dimensional even?
Christophe Wrote: > > Still, is the multi-dimensional part possible? > > Sure, you have to make an opApply that takes several parameters in its > delegate. > An exemple: > > struct TwoDArray(int nx, int ny) > { > int[nx][ny] data; > > int opApply(int delegate(ref int i, ref int j, ref int cell) > { > foreach (i; 0..nx) > foreach (j; 0..ny) > { > int result = dg(i, j, data[i][j]); > if (result != 0) return result; > } >return 0; > } > } > > > // this program prints a multiplication table: > int main() > { > TwoDArray!(10, 10) data; > > foreach(i, j, ref cell; data) > { > cell = i * j; > } > > foreach(i, j, cell; data) > { > writefln("%s * %s = %s", i, j, cell); > } > return 0; > } > Ha! Beautiful, thanks!!
Re: Create a foreach-able struct? Multi-dimensional even?
Heywood Floyd Wrote: > > Hello! > > 1) How do I create a struct that I can foreach over? > > I get the impression opApply has something do to with this, but I can't find > any documentation on it? (And I'm abroad without my TDPL.) > > > 2) Also, is it possible to do something like this? > > MyData!(100,100,100) data; > foreach(x, y, z, ref cell; data){ > cell = x*y*z; > } > > (The idea here is cells are stored in a plain 1-dimensional array behind the > scenes, but iterated as a 3-dimensional array.) > > > Kind regards > /HF Ah, I'm sorry, I found the documentation regarding opApply() now. Typical. (The site-search didn't seem to work there. Ok..) Still, is the multi-dimensional part possible? /HF
Create a foreach-able struct? Multi-dimensional even?
Hello! 1) How do I create a struct that I can foreach over? I get the impression opApply has something do to with this, but I can't find any documentation on it? (And I'm abroad without my TDPL.) 2) Also, is it possible to do something like this? MyData!(100,100,100) data; foreach(x, y, z, ref cell; data){ cell = x*y*z; } (The idea here is cells are stored in a plain 1-dimensional array behind the scenes, but iterated as a 3-dimensional array.) Kind regards /HF
Re: Get address of label?
Thank you bearophile and Simen for your replies! Very helpful! I'll keep looking into it... BR /HF bearophile Wrote: > Simen kjaeraas: > > > Essentially, mark the switch as final, and cover every option. > > Likely, the optimizer does that for you if you cover every option but > > don't mark the switch as final. > > This is true in theory, and I remember Walter liking this optimization. But > in practice I don't know if DMD performs this optimization already, so you > need to take a look at the produced asm to be sure. > > > > This is a little test, D2 code: > > enum E { e1, e2, e3 } > > int foo1(E e) { > switch (e) { > case E.e1: return 1; > case E.e2: return 2; > case E.e3: return 3; > default: assert(0); > } > } > > int foo2(E e) { > switch (e) { > case E.e1: return 1; > case E.e2: return 2; > default: return 3; > } > } > > int foo3(E e) { > final switch (e) { > case E.e1: return 1; > case E.e2: return 2; > case E.e3: return 3; > } > } > void main() {} > > > _D5test4foo1FE5test31EZi > push EAX > test EAX,EAX > je L11 > cmp EAX,1 > je L18 > cmp EAX,2 > je L1F > jmp short L26 > L11:pop ECX > mov EAX,1 > ret > L18:pop ECX > mov EAX,2 > ret > L1F:pop ECX > mov EAX,3 > ret > L26:hlt > > _D5test4foo2FE5test31EZi > push EAX > test EAX,EAX > je LC > cmp EAX,1 > je L13 > jmp short L1A > LC: pop ECX > mov EAX,1 > ret > L13:pop ECX > mov EAX,2 > ret > L1A:pop ECX > mov EAX,3 > ret > > _D5test4foo3FE5test31EZi > push EAX > test EAX,EAX > je L11 > cmp EAX,1 > je L18 > cmp EAX,2 > je L1F > jmp short L26 > L11:pop ECX > mov EAX,1 > ret > L18:pop ECX > mov EAX,2 > ret > L1F:pop ECX > mov EAX,3 > ret > L26:pop EAX > ret > > > > Some C code compiled with GCC 4.5.1: > > typedef enum { e1, e2, e3 } E; > > int foo2(E e) { > switch (e) { > case e1: return 1; > case e2: return 2; > default: return 3; > } > } > > int foo3(E e) { > switch (e) { > case e1: return 1; > case e2: return 2; > case e3: return 3; > } > } > > int foo4(E e) { > static void *array[] = { &&E1, &&E2, &&E3 }; > > goto *array[e]; > > E1: return 1; > E2: return 2; > E3: return 3; > } > > int main() { > return 0; > } > > > _foo2: > movl4(%esp), %edx > movl$3, %eax > cmpl$1, %edx > jbe L5 > rep > ret > .p2align 4,,7 > L5: > movl_CSWTCH.1(,%edx,4), %eax > ret > .p2align 4,,15 > > _foo3: > movl4(%esp), %edx > cmpl$1, %edx > je L11 > movl$1, %eax > jb L6 > cmpl$2, %edx > je L13 > .p2align 4,,3 > rep > ret > .p2align 4,,7 > L11: > movl$2, %eax > L6: > .p2align 4,,3 > rep > ret > .p2align 4,,7 > L13: > movb$3, %al > ret > > _foo4: > movl4(%esp), %eax > jmp *_array.1639(,%eax,4) > .p2align 4,,7 > L15: > movl$1, %eax > ret > .p2align 4,,7 > L17: > movl$2, %eax > ret > .p2align 4,,7 > L18: > movl$3, %eax > ret > > > > > My forays into the inline asm idea proved fruitless, but there may yet be > > ways. > > In D+DMD inline asm kills inlining, so you may use inline asm only if you > need to do lot of computations. > In LDC there are pragma(allow_inline) and asm expressions that some most of > this problem. > > Going back to the OP problem: in D there are no computed gotos, that are > useful if you want to write very fast interpreters and other things. But keep > in mind that DMD supports normal gotos from and in inlined asm (LLVM-LDC > doesn't supports this well), plus naked asm, this gives you some > possibilities. > An option on Linux is to write the interpreter core using GNU C (that has > computed gotos) and then link the core to the D code compiled with DMD/GDC. > > It's strange how something as basic, old and necessary as a switch, to create > a basic but fast interpreter, is so hard to compile well for compilers :-) > > Bye, > bearophile
Re: Get address of label?
Thanks for the answer! Ok, hm, how about this then: auto opTable = [&op_add, &op_cmp, &op_end]; //etc. ubyte[] eval(ubyte[] prog) { int ip = 0, sp = 0; ubyte[4096] stack; next: goto opTable[prog[ip++] & OP_TABLE_MASK]; op_add: stack[sp] += stack[sp-1]; goto next; op_cmp: stack[sp] = stack[sp-1] == stack[sp-2]; goto next; /// and so on... op_end: return stack; } What I'm looking for here is a way of interpreting code without creating branches in the machine code, unless the interpreted code actually does a branch (ie a conditional jump). Seems to me a switch would introduce branching (?) of some sort. I mean, even if switch is implemented as a jump table, it would still do some basic bounds checking, or? I'm also interested in trying to inline the "next"-operation here, ie like string op_next(){ return "goto opTable[prog[ip++] & OP_TABLE_MASK];"; } //... op_add: stack[sp] += stack[sp-1]; mixin(op_next()); ..in order to reduce a jump. Of course I'm just playing around with different strategies for creating a fast interepreter. In C, at least, using a jump table instead of a switch is faster, especially in 32-bit mode (according to some very simple experiments, which may or may not hold water in reality). Any ideas for how to make a jump-table interpreter in D? Is it doable with inline asm perhaps? If at least not for any other reason than to investigate if it's faster. (Or is it a stupid idea to begin with? Is this overkill? : ) cheers! BR /HF PS. How do you export assembler code from the DMD-compiler? Simen kjaeraas Wrote: > Heywood Floyd wrote: > > > Is this possible somehow: > > int op(int r, int i) > > { > > static auto tbl = [&add, &sub, &mul]; > > goto tbl[i % 3]; > >add: > > r++; > > goto end; > > sub: > > r--; > > goto end; > > mul: > > r*=r; > > goto end; > > end: > > return r; > > } > > Absolutely: > > enum ops : int { > add = 0, > sub = 1, > mul = 2; > } > > int op( int r, int i ) { > switch( i % 3 ) { > case add: > r++; > break; > case sub: > r--; > break; > case mul: > r*=r; > break; > } > return r; > } > > -- > Simen
Get address of label?
Is this possible somehow: int op(int r, int i) { static auto tbl = [&add, &sub, &mul]; goto tbl[i % 3]; add: r++; goto end; sub: r--; goto end; mul: r*=r; goto end; end: return r; } Happy holidays! BR /HF
Re: Is libdruntime deprecated in 2.051?
Quick 2.051 D for Xcode fix: Open /Library/Application Support/Developer/Shared/Xcode/Plug-ins/ And do Show contents on the 'D for Xcode.xcplugin"-bundle and then open ./Contents/Resources/dmd2.pblinkspec and change the line CommandLineArgs = { NO = (); "<>" = ("/usr/local/lib/libphobos2.a", "/usr/local/lib/libdruntime.a"); }; to CommandLineArgs = { NO = (); "<>" = ("/usr/local/lib/libphobos2.a"); }; and restart Xcode. (Sorry for the boring post. Just documenting for future reference.) BR /HF Heywood Floyd Wrote: > > Build fails after upgrade to 2.051 with gcc saying > /usr/local/lib/libdruntime.a: No such file or directory > > And indeed, the file is gone! > > This is XCode with D for XCode plugin, so it assumes stuff about the build > tools. Using dmd from the command line works, and running it with '-v' it > seems it only links in phobos2? (and some other minor libs..) I can't find > libdruntime in the Linux-folder either, although the README-file there lists > it? > > Is libdruntime no more? > > (And if that's the case, does anyone know how to fix this is in the D for > XCode plugin?) > > BR > Happy holidays! > /HF
Is libdruntime deprecated in 2.051?
Build fails after upgrade to 2.051 with gcc saying /usr/local/lib/libdruntime.a: No such file or directory And indeed, the file is gone! This is XCode with D for XCode plugin, so it assumes stuff about the build tools. Using dmd from the command line works, and running it with '-v' it seems it only links in phobos2? (and some other minor libs..) I can't find libdruntime in the Linux-folder either, although the README-file there lists it? Is libdruntime no more? (And if that's the case, does anyone know how to fix this is in the D for XCode plugin?) BR Happy holidays! /HF
Re: Strange socket error
Hi! I see. I think my previous answer was a bit naiveI didn't appreciate the full scope of the problem. Sorry for that, but you know, internet is fast, snap snap : ) Ok, for now I'm afraid I don't have any more to add. (An isolated example would of course help greatly!) All I can say is, in my experience, the D sockets library _does_ behave differently on different platforms. Had a server that just died seemingly random on osx, while working fine on Linux. Turned out to be bug in D sockets. So there you go. (The bug is still there btw... *cough*) Hm, also, I realize I'm not sure I quite understand the structure of your app, and where in this structure the bug happends. Is this bug happening when your html/5-client tries to connect to the server? Or are the threads using sockets to communicate between eachother? BR /heywood Bob Cowdery Wrote: > Hi Heywood > > Thankyou for your time. Yes I agree making the call blocking does stop > the exceptions churning. Unfortunately the application stops accepting > data now because after the first incoming transfer from the web socket > client it sees data on the listening socket and promptly blocks on it > and never comes off until I make another connection. I think this is > expected behaviour. I could spawn a thread for each connection which I > would normally do but shouldn't need to as it's really only a few users > and I believe that would only sidestep the real problem. > > There are lots of things here that don't make sense. > > 1. It works for Windows and it should work for Linux (and Mac) unless > Windows is broken and Linux is behaving as it should. > 2. I should only see data on the listen socket when I make a new > connection. What I see is data on the listen socket when I send data on > the connected socket and with non-blocking even when I don't make a > connection or send any data at all. > 2. The really confusing thing is if I stop my USB and DSP threads it > stops behaving like this and sees data on the correct sockets. In other > words it works as it does on Windows so I have to assume this is the > correct behaviour. > 3. I've played around with trying to figure out exactly what it is in > the other threads that causes the behaviour. I got as far as finding > that only the DSP thead is required so that rules out misbehaving USB. > Very oddly there is a loop that is creating some Json data (not very > efficiently) as it's doing a lot of string concatenation. If I comment > out this loop or reduce its iterations the exception slow down to the > point where I just get 2 and then they stop. This points to something > horrible going on. > > I can only hope I've done something stupid that I just happen to be > getting away with on Windows. If it's a bug in the compiler or libraries > I think I'm stuffed as I wouldn't know where to start. > > Regards > bob > > On 23/12/2010 00:20, Heywood Floyd wrote: > > Hi Bob! > > > > > > My guess: You're listener is set to be non-blocking. That means that when > > you call listener.accept() it will return immediately with an > > SocketAcceptException, if there's no connection. And you're basically > > calling listener.accept() over and over again in an infinite loop. > > > > The following example shows it: > > > > import std.concurrency, std.stdio, std.conv, std.socket; > > void main() > > { > > ushort port = ; > > Socket listener = new TcpSocket; > > assert(listener.isAlive); > > listener.blocking = false; > > listener.bind(new InternetAddress(port)); > > listener.listen(10); > > writeln("Listening on port: ", port); > > Socket sn; > > while(true){ > > try > > { > > writeln ("Accepting"); > > sn = listener.accept(); > > writeln("Connection from ", > > sn.remoteAddress().toString(), " established" ); > > assert(sn.isAlive); > > assert(listener.isAlive); > > break; > > } > > catch(Exception e) > > { > > writeln("Error accepting: ", e.toString() ); > > if(sn) > > sn.close(); > > } > > } > > writeln("end"); > > } > > > > Running the example will print > > Error accepting: std.socket.SocketAcceptException: Unable to accept > > socket connection: Resource temporarily
Re: Strange socket error
Hi Bob! My guess: You're listener is set to be non-blocking. That means that when you call listener.accept() it will return immediately with an SocketAcceptException, if there's no connection. And you're basically calling listener.accept() over and over again in an infinite loop. The following example shows it: import std.concurrency, std.stdio, std.conv, std.socket; void main() { ushort port = ; Socket listener = new TcpSocket; assert(listener.isAlive); listener.blocking = false; listener.bind(new InternetAddress(port)); listener.listen(10); writeln("Listening on port: ", port); Socket sn; while(true){ try { writeln ("Accepting"); sn = listener.accept(); writeln("Connection from ", sn.remoteAddress().toString(), " established" ); assert(sn.isAlive); assert(listener.isAlive); break; } catch(Exception e) { writeln("Error accepting: ", e.toString() ); if(sn) sn.close(); } } writeln("end"); } Running the example will print Error accepting: std.socket.SocketAcceptException: Unable to accept socket connection: Resource temporarily unavailable for ever. (Tested on Mac.) When a user connects to 127.0.0.1: (by for instance opening the URL in a browser) socket.accept _does_ return a connection and the program prints "end". I don't know why the program doesn't do this on Windows. As far as I can tell the endless exceptions _is_ the correct behaviour, right? Anyway, if you comment out the the line listener.blocking = false; in 'listener.d', does it work as intended then? In the example above this will cause the listener.accept()-call to actually wait until it gets a connection, and thus not spew out all the exceptions. BR /heywood Bob Cowdery Wrote: > Hi all, > > This is a long shot but I'm out of ideas. I ported an app from Windows > to Linux and after many issues it is working but I'm left with a strange > problem. The app basically reads data streams from a USB device, > processes them and outputs real-time graphical data to a browser. There > is also some control input from the browser. The interface to the > browser is web sockets for which I have written a D web-socket server. > Depending on how much of my application I allow to run I get a stream of > these errors. > > Error accepting: std.socket.SocketAcceptException: Unable to accept > socket connection: Resource temporarily unavailable > > ./DcSdr() [0x80aa2ed] > ./DcSdr() [0x806f52b] > ./DcSdr() [0x804f752] > ./DcSdr() [0x809b422] > ./DcSdr() [0x80ae77e] > /lib/tls/i686/cmov/libpthread.so.0(+0x596e) [0x48496e] > /lib/tls/i686/cmov/libc.so.6(clone+0x5e) [0xc5fa4e] > > This is the web-socket accept. I seem to fall straight through the > accept call even when I am not making any connection attempt. When I do > connect the stream stops and I get one of these outputs each time I send > data from the browser. I should not even be near the accept at that > point as the connection is made. > > The app appears to be unaffected and works as expected. The odd think is > if I shut down part of the app these errors stop. I can't tie it down to > any specific thing but I suspect threading as the number of threads is > reduced by stopping parts of the app. The error also seems to indicate > threads are involved. I did not get this problem on Windows. > > Any ideas would be much appreciated. > > Thanks > bob
Concurrency and transfering "ownership" of data between threads?
Good Evening from Berlin! Have been reading the chapter about concurrency by Andrei. Nice. I have some questions, of varying quality, I'm sure. Let's say that we have some sort of structure of rather complex data. To give us something concrete to talk about, let's say this data is a tree of nodes representing 3-dimensional objects. It could look something like this: (Not complete example, just to give an idea.) // ... class Cube : Node{ float x, y, z, size, mass, elasticity; // ... } // ... tree.add(new Cube("cube1")); tree["cube1"].add(new Cube("cube2")); Let's further say that this structure of data will be subjected to two different activities: 1) We will change properties of some nodes according to some complex lengthy calculations, which may even entail changing the position of nodes in the tree, and 2) we will traverse the tree in a recursive manner and read the properties in order to render a representation of these nodes to screen. These two activities will then be repeated many times, so, let's say we wish to do these two activities in parallel as much as possible! How do we do that? >From what I can tell, one way of doing this would be to actually have two data >structures, one which is the "original" and is used for the calculations, and >one which is just a copy of the data after each calculation. We could then >insert a third activity, which me can call "copy", inbetween the two threads. >Something like this: |== Calculate ===| Copy | |v |= Render | Seems to me this would then allow us to interlock these two activites: ..|== Calculate ===| Copy |== Calculate |.. ..|=== Render ===|v |=== Render |.. (Sorry if the ASCII graphics looks skewed.) So let me just try and set up some kind of rudamentary code for this in layman's D: // import ... void main() { auto tree = new Node(); tree.add(new Cube("cube1")); auto child = spawn(&renderLoop, thisTid); while(true) { calc(tree); auto treeCopy = tree.deepDup(); receiveOnly!bool(); send(child, treeCopy); } } void renderLoop(Tid parent){ { send(parent, true); while(true) { Node tree = receiveOnly!Node(); render(tree); send(parent, true); } } So a couple of thoughts here. - Is this looking ok? What is the "proper" way of going about this? - How do we send over a large chunk of complex data to another thread and sort of let them assume "ownership" of this data? So that the thread receiving the data does not need any locks etc. when working with the data? I suppose we could send over the entire treeCopy as immutable (?) but let's for the sake of argument assume that renderLoop() needs to be able to _write_ in the copy of the tree structure too! (- Sidenote: How do we efficiently copy a tree-structure of data several times per second? Sounds insane to me?) Let's further, for the sake of argument, NOT consider that the GPU will do most of the rendering and that in effect parallelising in this particular case may be marginally beneficial. Let's simply assume we have only one processor here: your normal household dual-core CPU, and a VGA-graphics card from the 80s. For me, in my head, parallelising is very much about designing a flow of data through different processes, and this flow chart will have certain "hot spots" where data must be guarded. You have one process doing something and then "transfering over" some data to the next process that continues the calculations. (With process I simply mean data processing activity, not a "unix process".) |---calc A--->Ocalc C> etc. |---calc B-^ O = transfer point I find it difficult to see how this is done in D. (Of course, I'm not sure this "transfer"-idea makes any practical sense.) I understand immutable makes data read-only, contagiously, and shared makes data heavily guarded. But yes, is there any way we can transfer "ownership" (not sure if that is the right term) of data from one thread to another? So that we can have two threads working on two pieces data, then let them copy it (or not!), and then transfer ownership and have a third thread work on the copied data, without barriers or guards or stuff like that during the time of actual work? Kind regards and sorry for a lengthy sporadic post /Heywood Floyd
Re: atomicOp problem
Interesting! I get the same result, ie an infinite loop, with the CPU at 100% Some things I noticed: - Changing the for-loops to 100 or 10 doesn't help. - Changing the atomicOp from "+=" to just "+" makes it work (although the account doesn't get changed) - Adding a Thread.sleep(1000) in one of the for-loops, before the call to atomic-op, makes it all work with "+=" as well By looking at the code in atomic.d it looks the "+="-operator ends up here: // L#131..: T get, set; do { get = set = atomicLoad!(msync.raw)( val ); mixin( "set " ~ op ~ " mod;" ); } while( !cas( &val, get, set ) ); return set; And I suppose the cas()-function never returns true? I don't know how atomic is supposed to work, so I'm not sure if it's a bug or not. I'm no expert with D, or threading for that matter, so I don't know. (I'm just an expert guesser : ) I guess bug! BR /HF Benjamin Thaut Wrote: > I recently read the book "the D programming language" and wanted to try > out a few of the multithreaded examples pointed out in this book. I > tried to write a version of the bank account example using the atomicOp > from core.atomic. But when I compile it, it never finishes, it just gets > stuck in a endless loop inside atomic.d I think. > Here is the code: > > import std.stdio; > import std.concurrency; > > enum Messages { > GO > } > > shared class Account { > private float amount = 0; > > float getAmount() const { > return amount; > } > > void change(float change){ > atomicOp!"+="(amount,change); > } > } > > shared Account bank = null; > > void otherThread(Tid father){ > send(father,Messages.GO); > for(int i=0;i<1000;i++) > bank.change(-100); > } > > void main(string[] args) > { > bank = new Account(); > spawn(&otherThread,thisTid); > receiveOnly!(Messages)(); > for(int i=0;i<1000;i++) > bank.change(+100); > writefln("Program finished. Amount is %s",bank.getAmount()); > } > > If you could please point out what I did wrong I would be very glad. If > I did not do anything wrong, I don't quite understand whats the exact > problem because the code inside atomic.d looks good (at least at my > level of understanding) > > -- > Kind Regards > Benjamin Thaut
Re: Stripping D symbols?
..got it solved at last.. \o/ Just writing it down here for future reference (since I found nothing when googling etc..) Strip can not manage this by itself. The linker, ld (el-dee) needs to be run with the "-exported_symbols_list"-option and given an empty file. Then the symbols created by dmd are treated as local, or whatever it is, and then strip can successfully strip them out. If CLI is used then a stripped binary can be created like this: (#-lines are treated as comments in the exported symbols file.) # echo "#empty symbols list for d-code stripping" > symlist # dmd -L-exported_symbols_list -Lsymlist myprog # strip myprog If XCode is used (with the D for Xcode plugin) an empty file can be put in the project root and then the "Exported Symbols File"-build property (for Release) can be set to the name of this file. Then, lastly a new Build Phase: Run Script can be added with the code strip build/Release/MyApp.app/Contents/MacOS/MyApp If the target is an OSX-app named MyApp. Hope it helps someone at some point... :) Toodiloo! BR /HF Heywood Floyd Wrote: > > > ..ok, I got bored and installed Ubuntu I tried it, and there it worked fine! > > # strip sym > # nm sym | grep Bunny > nm: sym: no symbols > # _ > > > Great! The program runs fine too. > (And the binary went from a size of 399Kb to 191Kb! Woah! That's more than > half gone!) > > Hm, but how to I go about his now? Seems the OSX-strip is acting funny? Or > could it have something to do with DMD still? Maybe I should ask in some > darwin-forum about strip... > > BR > /HF > > > > > > > Heywood Floyd Wrote: > > > Hello! > > > > I've been trying to strip an executable created with DMD from symbols. Has > > anyone any experience with this? > > > > I can't seem to rid my execs of more or less containing the entire > > class-tree. Example: > > > > // sym.d - - - - > > import std.stdio; > > class Bunny{ > > int x; > > int getX() > > { > > return x; > > } > > } > > void main() > > { > > auto b = new Bunny(); > > writefln("Hello %d", b.getX() ); > > } > > > > // - - - - - (OSX 10.6) > > > > # dmd -release sym > > # strip sym > > # nm sym | grep Bunny > > 28c8 T _D3sym5Bunny4getXMFZi > > # _ > > > > // - - - - - > > > > This was of course a simplified example. I tried putting "private" in front > > of the class, but that didn't change anything. > > > > Any ideas? I'm just lost. Is it the same on Linux? > > > > Or maybe this is one of those "features" that allows D to call functions by > > name or something? I see "T" is a text entry, by reading the man-pages.. > > > > (I suppose it really doesn't matter, but if possible I'd like to not expose > > function and class names in my binaries, for (I think) obvious reasons.) > > > > > > Kind regards > > /HF > > > > > > > > >
Re: Stripping D symbols?
..ok, I got bored and installed Ubuntu I tried it, and there it worked fine! # strip sym # nm sym | grep Bunny nm: sym: no symbols # _ Great! The program runs fine too. (And the binary went from a size of 399Kb to 191Kb! Woah! That's more than half gone!) Hm, but how to I go about his now? Seems the OSX-strip is acting funny? Or could it have something to do with DMD still? Maybe I should ask in some darwin-forum about strip... BR /HF Heywood Floyd Wrote: > Hello! > > I've been trying to strip an executable created with DMD from symbols. Has > anyone any experience with this? > > I can't seem to rid my execs of more or less containing the entire > class-tree. Example: > > // sym.d - - - - > import std.stdio; > class Bunny{ > int x; > int getX() > { > return x; > } > } > void main() > { > auto b = new Bunny(); > writefln("Hello %d", b.getX() ); > } > > // - - - - - (OSX 10.6) > > # dmd -release sym > # strip sym > # nm sym | grep Bunny > 28c8 T _D3sym5Bunny4getXMFZi > # _ > > // - - - - - > > This was of course a simplified example. I tried putting "private" in front > of the class, but that didn't change anything. > > Any ideas? I'm just lost. Is it the same on Linux? > > Or maybe this is one of those "features" that allows D to call functions by > name or something? I see "T" is a text entry, by reading the man-pages.. > > (I suppose it really doesn't matter, but if possible I'd like to not expose > function and class names in my binaries, for (I think) obvious reasons.) > > > Kind regards > /HF > > > >
Stripping D symbols?
Hello! I've been trying to strip an executable created with DMD from symbols. Has anyone any experience with this? I can't seem to rid my execs of more or less containing the entire class-tree. Example: // sym.d - - - - import std.stdio; class Bunny{ int x; int getX() { return x; } } void main() { auto b = new Bunny(); writefln("Hello %d", b.getX() ); } // - - - - - (OSX 10.6) # dmd -release sym # strip sym # nm sym | grep Bunny 28c8 T _D3sym5Bunny4getXMFZi # _ // - - - - - This was of course a simplified example. I tried putting "private" in front of the class, but that didn't change anything. Any ideas? I'm just lost. Is it the same on Linux? Or maybe this is one of those "features" that allows D to call functions by name or something? I see "T" is a text entry, by reading the man-pages.. (I suppose it really doesn't matter, but if possible I'd like to not expose function and class names in my binaries, for (I think) obvious reasons.) Kind regards /HF
Re: Linking D and Obj-C code into a Cocoa app proper? (Mac)
Ok! Thanks for the advice! Great work on the pluginit got me into D :) /FH Michel Fortin Wrote: > On 2010-10-05 10:02:45 -0400, Heywood Floyd said: > > > But, sometimes I get reeeaally weird bugs. I had one bug where if I > > added an empty function to a class in D I got EXC_BAD_ACCES (segfault). > > An empty function! Ie "void f(){}". Remove the function--it works. In > > the debugger, I got the impression maybe the stack has got messed up, > > but I don't know, the debugger just shows assembler code, and I don't > > have the proper skills. > > It's hard to say without further details, but it could be that you're > not recompiling everything that uses the class where you add a > function. Unlike in Objective-C, adding a function to a D class breaks > most compiled code that uses that class (because you're adding an > offset to the virtual function table), so you need to recompile every D > module that uses that class (or a derived class). > > Note that this is totally unrelated to having Objective-C code in the > same program. > > > > This got really frustrating, needless to say, so I started playing > > around with the build settings. I switched from using LLVM 1.5 (for the > > obj-c code) to gcc 4.2. And now it magically seems to work! > > Are you using D for Xcode? By doing that you basically force everything > to be recompiled, which solves problem described above. > > > > [...] > > > > == Question == > > How do you make D code and Obj-C code coexist? That is, I want to write > > a Cocoa-app that is mostly written in D, and with a little "glue"-code > > in Objective-C. How do you set that up? Is it even supposed to be > > possible? > > It is totally possible, and not that hard. Communicating via `extern > (C)` functions should work well. > > > > (And what could the bug above be? I know LLVM does link-time > > optimizations, and even run-time optimizations. Could it be that it > > messes things up?) > > I doubt LLVM optimizations have anything to do with your problem. > Things to keep in mind when mixing Objective-C: > > 1. Apple's Objective-C GC isn't supported by D, so you it's probably > safer to use manual memory management (retain/release) on the > Objective-C site. > > 2. Exceptions are not compatible between the two runtimes. Throwing can > cause unexpected results when it unwinds stack frames in the other > language. > > > -- > Michel Fortin > michel.for...@michelf.com > http://michelf.com/ >
Linking D and Obj-C code into a Cocoa app proper? (Mac)
Good Evenening Ladies and Gentlemen! == Background == So I currently have a bare-bones Cocoa-app. It's just a window with an OpenGL-view. In the view's draw-function I make the gl-view the current OpenGL context and then call "extern (C) render()". Meanwhile, in a D-file I have the implementation for this function. Here I've copied all the function names from opengl.h and declared them in the D-file ("extern (C) glBlabla()" etc) so I can call glBegin etc from my render()-function in D. This is all in XCode and I use Michel Fortin's "D for XCode"-plugin btw. This works great! The window paint triangles and what have you. Pretty! Happiness! But, sometimes I get reeeaally weird bugs. I had one bug where if I added an empty function to a class in D I got EXC_BAD_ACCES (segfault). An empty function! Ie "void f(){}". Remove the function--it works. In the debugger, I got the impression maybe the stack has got messed up, but I don't know, the debugger just shows assembler code, and I don't have the proper skills. This got really frustrating, needless to say, so I started playing around with the build settings. I switched from using LLVM 1.5 (for the obj-c code) to gcc 4.2. And now it magically seems to work! Ok. But as you might understand, the frustration is not quite gone. Adding a function now feels like a spinning a wheel of fortune. It's utterly demoralizing. So I thought about this and realized, I probably should try to find out what it is I'm actually doing here, and hear with some real programmers if there's a "proper" way of doing it. So my question, dear D community: == Question == How do you make D code and Obj-C code coexist? That is, I want to write a Cocoa-app that is mostly written in D, and with a little "glue"-code in Objective-C. How do you set that up? Is it even supposed to be possible? (And what could the bug above be? I know LLVM does link-time optimizations, and even run-time optimizations. Could it be that it messes things up?) BR /HF
Re: std.socket.TcpSocket.flush
Rory Mcguire Wrote: > Hi, > > What is one supposed to use to flush a TcpSocket. > > flush doesn't seem to exist, should I really just use the c function? > > -Rory Was in a similar situation, found this: http://stackoverflow.com/questions/855544/is-there-a-way-to-flush-a-posix-socket I thought a socket needed to be flushed because curl and ab "hanged" when GETting from my server. Turns out I was just not sending the correct HTTP-headers... /HF
Re: string[int[][]] ??
> > string[int[2]] board; > > board[[0,0]] = "Rook"; > board[[0,1]] = "Knight"; > > foreach( pos, val; board) { > writefln( "%s: %s", pos, val); > } > > > Output: > > 2 9903680: Knight > 2 9903696: Rook > Changing the declaration to string[int[]] board; makes it work (for me). BR /HF
Re: Multi dimensional array question.
Mafi Wrote: > > I don't really like it. Of course the order of indices feels better but > it breaks the rule of reading types from right to left. It also > introduces more parenthesis and a new keyword into types (amongst const, > immutable and delegate etc). Consider: >shared array[3](const( array[5] immuttable((SList!(int)*)[]) )) > WTF, that doesn't look good. I would be a real type if your answer was > accepted. > > It was >shared const( immutable(Slist!(int)*[])[5] )[3] > which reads perfectly from right to left. > > What about this: >// int[width,height] as sugar for int[height][width] >int[width,height] arr = ...; >// arr[x,y] as sugar for arr[x][y] >int element = arr[x,y]; >// then this works as expected >int[height] column = arr[x]; Interesting! First of all, I definitely think that how arrays are declared now would have to stay just the way it is, no matter what. I don't think stuff like that is changeable this late in a language. But, seems to me these two methods of declaring arrays could coexist. One is the shorter syntactical "sugar" method, the other is the elaborate, but perhaps clearer method. These kinds of long way/shortcuts are already in the language, I believe. Like how void()() is automatically a template, comes to mind. (Or did that make sense?) Then, I simply can't resist commenting this exceptional beauty. I'm gonna call it theThing: shared const( immutable(Slist!(int)*[])[5] )[3] theThing; Well. I have to confess, to me, it doesn't read perfectly from right to left. I might be reading it wrong, but to me it reads from right to left, and from left to right, at the same time. Is it a shared const array of something, or a shared array of const something? You can't really tell unless you go back and forth, and almost count the parenthesis. For instance, by looking at the declaration above, what type is a theThing[0][1] ::= ?? It's really not easy to say, for me anyway. I'm sure you get better at reading these things. So it might not be fair to say that it's "unclear". It's just my subjective opinion, and that may be biased by my lack of experience in the matter. Now back to the other thing: shared array[3] const array[5] immutable array[] (SList!(int)*) Sure, this is too verbose. I agree. Still, I think it's clearer. Much clearer. Verbose, but clear. Here I couldn't help but making an interesting obvservation: Those storage classes could also be seen as types. What if we allowed the storage classes to have some syntactical sugar too, for arrays? We could have: shared[3] const[5] immutable[] SList!(int)* theThing; That does read from left to right in one go, and to me, it's still clear what's going on, and, it's not verbose. In fact, it's less verbose than the parenthesis-sprinkled version we saw first. Further, it's almost magically easy to read: We have a shared array of 3 const arrays of 5 immutable dynamic arrays of Slist!(int)*. It just reads, like you read text, quite naturally. (I'm not sure this would actually be the same type as the first declaration, erh, but yes. You get my intention.) So again, what type is a theThing[0][1] ::= ?? Well, if we look at the declaration above it's quite easy: We just cut the line after the second array, const[5], and the rest of the line, that's our type. theThing[0][1] ::= immutable[] SList!(int)* Now, to me, that's just plain beautiful. *** And last, the int[x,y] arr; I like it. Simple. Nice. Maybe it becomes weird when we have mixed array types, like int[uint,,5] arr? Well at least the illusion of an intact order is maintained. BR /HF
Re: Multi dimensional array question.
Lars T. Kyllingstad Wrote: > I do agree that, if possible, the language should match how most people > think. But in this case, it is impossible, because of templates. How > would the following example work with T = int[3], if arrays worked the > way you want? > > struct MyArray(T) > { > T[] a; > } > > C doesn't have this issue, because it doesn't have templates. And I'll > have my templates over C-style array declarations any time, thank you. :) > > -Lars Well, I suppose the obvious way is to introduce array as a proper type, and not just as syntactical sugar. For instance, consider: array[11] int myArr; The array "wraps around" a more basic type. It's simply read from left to right. This should feel "right" for most people. Now it's easy extend this to multidimensional arrays. We just allow arrays to wrap arrays: array[3] array[11] int myArr2d; This way it's clear what's happening. It's "true" to what's going on at the compiler level. We have an "outer" array that holds 3 "inner" arrays of 11 ints. And, it's "true" to our high level semanticswhen we later access the elements, the order is kept intact, as we traverse down the array stack: myArr2d[outer][inner] = 9; It's then not too far of a stretch to allow this array-keyword to accept multidimensional declarations, without reversing the order. Here, it's still quite clear what's happening: (At least if we have seen the above.) array[3][11] int myArr2d; myArr2d[0][10] = 9; //ok When we introduce templates, this should still work: struct MyArray(T){ array[3] T a; } // Let's try T == array[11] int array[3] T a; array[3] (array[11] int) a; array[3] array[11] a; array[3][11] a; a[0][10] = 9; //ok This makes a lot more sense, for me anyway. It's closer to what's actually happening, and it doesn't reverse things at a higher level. BR /HF
Re: Is synchronized(mutex) == mutex.lock()?
Steven Schveighoffer Wrote: > On Wed, 14 Jul 2010 23:22:20 -0400, Heywood Floyd > wrote: > > > Hi! > > > > Breakfast toast: Is there any chance a) and b) below are identical in > > what they do? > > > > > > auto mutex = new Mutex(); > > auto cond = new Condition(mutex); > > > > // a) > > synchronized(mutex){ > >cond.wait(); > > } > > > > // b) > > mutex.lock(); > >cond.wait(); > > mutex.unlock(); > > Almost, this is more equivalent: > > { >mutex.lock(); >scope(exit) mutex.unlock(); >cond.wait(); > } > > But yes, the mutex object implements the monitor interface, and replaces > its own monitor object with a pointer to itself. > > For something really nifty, you can tell mutex to be the monitor object of > *any* other object :) Unfortunately, I can't point you at the docs, cause > they dont exist yet, but this will do it: > > class C{} > > auto c = new C; > auto m = new Mutex(c); // now synchronizing on c is the same as locking m > > -Steve Cool, love it! Thanks! /HF
Is synchronized(mutex) == mutex.lock()?
Hi! Breakfast toast: Is there any chance a) and b) below are identical in what they do? auto mutex = new Mutex(); auto cond = new Condition(mutex); // a) synchronized(mutex){ cond.wait(); } // b) mutex.lock(); cond.wait(); mutex.unlock(); I was sprinkling my code with mutex.lock/unlock (for fun) when suddenly I realized that, hey, maybe synchronized would work just as well, and be even more fun? (If that's even possible.) BR /HF
Re: Multi dimensional array question.
Lars T. Kyllingstad Wrote: > > But then arrays would be different from all other types! If you have an > array of 3 Ts, that is written T[3], regardless of what T is. Now > consider these two cases: > >A. T is an int. Then T[3] becomes int[3]. > >B. T is an int[string]. Then T[3] becomes int[string][3]. > > In case A, the first element of the array is accessed like this: > >int[3] a; >int firstA = a[0]; > > Since a is an array of int, firstA is of course an int. > > But then, since b is an array of int[string], we have > >int[string][3] b; >int[string] firstB = b[0]; > > If we again want to access element "foo" of the associative array which > is firstB, we write firstB["foo"]. And so we have the following three > ways to get to that element, which *must* be equivalent because that's > how the language is defined: > >// Using firstB as an intermediate step >int[string] firstB = b[0]; >int x = firstB["foo"]; > >// Drop the intermediate variable firstB >int x = (b[0])["foo"]; > >// Drop the redundant parentheses >int x = b[0]["foo"]; > > So you see, it can't be any other way than the way it is. :) > > -Lars Thank you for the elaborate answer! When you put it like that, it does make sense. But I'm sorry. I refuse. The reason I refuse is those examples are void of any higher semantic meaning. Once we add a semantic meaning, it simply becomes backwards: int[MAX_WIDTH][MAX_HEIGHT] map2d; map2d[x][y] = 9; // Wrong! At least in my head, this is cognitive dissonance. To me, the language acts as if it's low-level semantics outweighs my high-level semantics and I should correct my thinking for that. I refuse! Seems to me it could just as well work as: int[string][3] b; int[3] firstB = b["foo"]; int i = firstB[0]; int j = (b["foo"])[0]; int k = b["foo"][0]; But I feel like I'm the only one feeling this, so I'll just let it go and hope my dear C-style arrays stay in :) BR /HF PS. Never thought I'd find a reason to love C.. DS.
Re: Multi dimensional array question.
bearophile Wrote: > Heywood Floyd: > > This had me crazy. I ended up putting the brackets on the variable, like > > int marr[3][5]; > > then it worked like > > marr[2][4] = 9; > > That's present only for compatibility with C syntax, this means that you can > use it to perform a quicker port of C code to D, but you are supposed to > later convert it to D-style array definitions. > See also: > http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=113185 > > Bye, > bearophile Aha, good to know! Thanks! (So this might go away in the future? Or require a -cstyle compile flag?) *** I have a feeling this "backwards"-array stuff is gonna be one of the things my brain will repel for as long as it can. To me, it seems equal to saying "you declare a function like: void foo(string name, int age){ //... } And then call it by doing foo(90,"Benny") and this makes sense because the arguments are actually pushed on the stack in reverse at runtime, so they arrive in the correct order in the function. And this is especially important with tuples." or something. Ok, I understand this has some deep purpose that I still don't understand, I'm just, yeah. *tear* (Although this is way out of my league: For instance, if a T is an int[3][4], then why can't T[string] be a int[string][3][4], and be accessed with arr["a"][2][3]? Seems just like a matter of taste?) /HF PS. I was not the thread creator. I just used the creator's terminology to "stay on topic". Maybe too on topic : ) Not important really. Sorry for the confusion. DS.
Re: Multi dimensional array question.
This had me crazy. I ended up putting the brackets on the variable, like int marr[3][5]; then it worked like marr[2][4] = 9;
Re: Is the memory address of classinfo the same for all instances of a class?
On Jul 2, 2010, at 15:34 , Steven Schveighoffer wrote: > On Fri, 02 Jul 2010 09:32:39 -0400, Steven Schveighoffer > wrote: > >> On Fri, 02 Jul 2010 09:24:20 -0400, Heywood Floyd wrote: >> >>> >>> Good day! >>> >>> >>> Consider >>> >>> // - - - - >>> class Foo{} >>> auto one = new Foo(); >>> auto two = new Foo(); >>> writefln("one: %x two: %x", &one.classinfo, &two.classinfo); >>> // - - - - >>> >>> For me this results in two identical memory addresses "every time". >>> >>> Can I rely on this? >>> Can I design software based on the assumption that these addresses are >>> always the same? >>> >>> (I'd like to be able to use the memory address as the key in an associative >>> array, for quick by-class >>> lookups.) >> >> Use classinfo.name. The classinfo is the same memory address in the same >> executable/dynamic library. If you open another D dynamic library, the >> classinfo address for the same class may be different, but the name will be >> the same. >> >> Note that comparing classinfo.names will be just as fast as comparing >> classinfo addresses if the names are at the same address (which will be true >> if the classinfo is at the same address) because the string comparison >> function short-circuits if the addresses are the same. > > Duh, just realized, classinfos should use this same method to compare. Just > use the whole class info as the key, don't take the address. > > -Steve Alright thanks! Ok, loading in code dynamically changes the addresses. Good point. Thanks! I looked up the TypeInfo_Class-implementation and it seems to compare class names. So that looks good. Will use the classinfos directly like you suggested. Seems proper. *** Hm, but still, I can't quite let go of this. Even if the string comparer can short-circuit, it still has to go through strings that are _not_ of the same address untill it spots a difference, as they could potentially be equal anyway? I noted that the classinfo.name-strings typically looks like this: classtype.Foo classtype.Bar classtype.Cat classtype.Dog Doesn't this first "classtype."-part introduce overhead when these strings are used as keys in an AA? The string comparer more or less always have to check the first 10 chars, which are equal for all. (I know I'm being picky here. But the whole using memory addresses-thing came from the fear of string comparisons being suboptimal.) /heywood (PS. Feature-request: move the "classtype."-part of classinfo names to the end ; )
Is the memory address of classinfo the same for all instances of a class?
Good day! Consider // - - - - class Foo{} auto one = new Foo(); auto two = new Foo(); writefln("one: %x two: %x", &one.classinfo, &two.classinfo); // - - - - For me this results in two identical memory addresses "every time". Can I rely on this? Can I design software based on the assumption that these addresses are always the same? (I'd like to be able to use the memory address as the key in an associative array, for quick by-class lookups.) BR /heywood
Re: How to call receiveTimout? (std.concurrency)
Thanks! I will! /heywood PS. I like D. On Jun 29, 2010, at 19:37 , Steven Schveighoffer wrote: > On Tue, 29 Jun 2010 13:05:50 -0400, Heywood Floyd wrote: > >> >> >> Ok, thanks! >> >> How does the chain of command/responsibility work here? >> Should I file this to bugzilla? >> >> (I'm not able to fix it myself as I haven't built dmd locally. I'm just not >> quite there yet... : ) >> /heywood > > Simen actually already filed it. See here: > http://d.puremagic.com/issues/show_bug.cgi?id=4406. In the future, just go > to http://d.puremagic.com/issues and you can file the bug directly. It's > good to ask on d.learn if you aren't sure. > > And this bug isn't in dmd, it's in phobos :) They are compiled separately > (in case you are interested in trying your hand at phobos patches). All the > releases come with the complete source code, just cd to the src directory and > type make -f blah.mak where blah is your platform (posix, windows, etc.). > > -Steve
Re: How to call receiveTimout? (std.concurrency)
Ok, thanks! How does the chain of command/responsibility work here? Should I file this to bugzilla? (I'm not able to fix it myself as I haven't built dmd locally. I'm just not quite there yet... : ) /heywood On Jun 29, 2010, at 16:31 , Steven Schveighoffer wrote: > On Tue, 29 Jun 2010 09:53:25 -0400, Simen kjaeraas > wrote: > >> Heywood Floyd wrote: >> >>> ops = ops[1 .. $]; // <=== line 335 >> >> Well, this looks like a bug to me. Should be >> >> Ops = ops[1 .. $]; >> > > Ops is a type, isn't it? Don't you need a variable there? > > I agree it's a bug in the original, but I don't think that's the fix. > > -Steve
How to call receiveTimout? (std.concurrency)
Hello and Good morning! I'm trying to use receiveTimeout: // import std.stdio, std.concurrency; int main(string[] args){ receiveTimeout( 1000L, (int i){writefln("Received: %d",i);} ) ; return 0; } // (I removed all the surrounding code above that spawned threads etc.) Compiler gives me: /Library/Compilers/dmd2/osx/bin/../../src/phobos/std/concurrency.d(335): Error: mismatched tuple lengths, 2 and 1 I can't see what's wrong? Help! A look in concurrency.d shows: // - - 8< - - bool receiveTimeout(T...)( long ms, T ops ) { static enum long TICKS_PER_MILLI = 10_000; return mbox.get( ms * TICKS_PER_MILLI, ops ); } // - - 8< - - final void get(T...)( T ops ) { static assert( T.length ); static if( isImplicitlyConvertible!(T[0], long) ) { alias TypeTuple!(T[1 .. $]) Ops; assert( ops[0] >= 0 ); long period = ops[0]; ops = ops[1 .. $]; // <=== line 335 } // - - 8< - - (DMD v2.047, OSX 10.6.4) BR /soul PS. Sorry if this is a dupe. Mailman doesn't seem to like my emails? Sending this via the web- interface..