Re: Finding out about D - 102
Ary Borenszweig Wrote: Steve Teale wrote: OK, so structs are a different beast in D than they are in C++. This results in one of my most common pitfalls. I'll find myself writing: struct A { int a; int b; } A[] nameTooLong = ...; foreach (whatever; thingie) { nameTooLong[whatever.whatever].a = whatever.x*3; nameTooLong[whatever.whatever].b = whatever.y/3; with(nameTooLong[whatever.whatever]) { a = whatever.x*3; b = whatever.y/3; } Ary, Yes I use with quite often, it's when I have two of the beasts where I want to use with at the same time that I have fallen into this. Now that I've rubbed my nose in it I'm sure I won't do it again.
Re: 3 variant questions
Saaa wrote: ... var_arg!(T) will convert _argptr into the type you specify and it will also advance _argptr to the next argument. What would happen if you'd cast it incorrectly if it wasn't a simple pointer ? :D Same as would happen if you incorrectly cast anything. i.e. anything. Segfault if you're lucky. If you're unlucky, random crashes. -- Daniel
Re: Threading
I probably should have phrased my question better with the array, what I was wondering is if it was safe for say two threads to right to the array at the same time as long as I'm sure they're not writing to the same index of the array? You can do anything you want without thread safety, but you run the risk of deadlocks or corrupted memory. That is why the question was whether it was safe. The problem isn't writing to two different elements of an array, the hard part is *ensuring* that you are writing to two different elements of an array. Multithreading code is tough to write correctly, you may want to read a book on it. And sometimes it is extremely easy to ensure you are never writing to the same elements.
Re: Threading
On Tue, 12 May 2009 10:12:48 -0400, Saaa em...@needmail.com wrote: I probably should have phrased my question better with the array, what I was wondering is if it was safe for say two threads to right to the array at the same time as long as I'm sure they're not writing to the same index of the array? You can do anything you want without thread safety, but you run the risk of deadlocks or corrupted memory. That is why the question was whether it was safe. If two threads are writing to two different sections of memory, yes it is always safe :) I think that's one of the fundamental premises of threads running anyways. If you couldn't do this, you couldn't have threads. The problem isn't writing to two different elements of an array, the hard part is *ensuring* that you are writing to two different elements of an array. Multithreading code is tough to write correctly, you may want to read a book on it. And sometimes it is extremely easy to ensure you are never writing to the same elements. If you are doing anything interesting with an array, this is not the case. Might as well not pass the same array to both threads. Maybe the OP doesn't understand that you can slice up an array quite easily. If you want to ensure two threads don't touch the same memory, don't give both threads access to the same memory. That's the easiest way to ensure thread safety. i.e. I want thread 1 to initialize elements 0, 1, and 2, and thread 2 to initialize elements 3, 4, and 5: thread1 = new ProcessingThread(arrayToInit[0..3]); thread2 = new ProcessingThread(arrayToInit[3..6]); thread1.start(); thread2.start(); Should be completely thread safe. -Steve
Re: Threading
I probably should have phrased my question better with the array, what I was wondering is if it was safe for say two threads to right to the array at the same time as long as I'm sure they're not writing to the same index of the array? You can do anything you want without thread safety, but you run the risk of deadlocks or corrupted memory. That is why the question was whether it was safe. If two threads are writing to two different sections of memory, yes it is always safe :) I think that's one of the fundamental premises of threads running anyways. If you couldn't do this, you couldn't have threads. I used to think of an array as one thing, thus making it unsafe to write to it from multiple threads at the same time :) I kind of thought he was asking along this conception. The problem isn't writing to two different elements of an array, the hard part is *ensuring* that you are writing to two different elements of an array. Multithreading code is tough to write correctly, you may want to read a book on it. And sometimes it is extremely easy to ensure you are never writing to the same elements. If you are doing anything interesting with an array, this is not the case. Might as well not pass the same array to both threads. Maybe the OP doesn't understand that you can slice up an array quite easily. If you want to ensure two threads don't touch the same memory, don't give both threads access to the same memory. That's the easiest way to ensure thread safety. i.e. I want thread 1 to initialize elements 0, 1, and 2, and thread 2 to initialize elements 3, 4, and 5: thread1 = new ProcessingThread(arrayToInit[0..3]); thread2 = new ProcessingThread(arrayToInit[3..6]); thread1.start(); thread2.start(); Should be completely thread safe. -Steve Could become more difficult if the distinction would be odd/even elements :P Or creatures on a grid who can only see the cell they stand on :D But yes, slicing is neat!
Re: 3 variant questions
import std.stdarg; assert( _arguments[0] is typeid(int*) ); auto arg = va_arg!(int*)(_argptr); *arg = 10; Probably. -- Daniel Calling the following returns an Access Violation Error after correctly writing the two lines. void main() { int i; get( file, `i`, i); } public void get(in char[][] file, in char[] identifier, ...) { assert( _arguments[0] is typeid(int) ); writefln(`assert done`); auto arg = va_arg!(int*)(_argptr); writefln(`assign done`); *arg = 7; return; }
Re: Threading
Georg Wrede georg.wr...@iki.fi wrote in message news:guc6ep$2im...@digitalmars.com... Saaa wrote: Steven Schveighoffer wrote: i.e. I want thread 1 to initialize elements 0, 1, and 2, and thread 2 to initialize elements 3, 4, and 5: thread1 = new ProcessingThread(arrayToInit[0..3]); thread2 = new ProcessingThread(arrayToInit[3..6]); thread1.start(); thread2.start(); Should be completely thread safe. Could become more difficult if the distinction would be odd/even elements :P Why??? If your threads have no bugs (i.e. the odd thread doesn't read or write the even elements, and vice versa), then this should be easy! Or creatures on a grid who can only see the cell they stand on :D Then the only thing that has to be thread safe is the code that moves a creature from cell to cell. And, of course, it has to guarantee that no two creatures end up in the same cell. I meant slicing would become more difficult.
Re: 3 variant questions
Saaa Wrote: import std.stdarg; assert( _arguments[0] is typeid(int*) ); auto arg = va_arg!(int*)(_argptr); *arg = 10; Probably. -- Daniel Calling the following returns an Access Violation Error after correctly writing the two lines. void main() { int i; get( file, `i`, i); } public void get(in char[][] file, in char[] identifier, ...) { assert( _arguments[0] is typeid(int) ); writefln(`assert done`); auto arg = va_arg!(int*)(_argptr); writefln(`assign done`); *arg = 7; return; } You get an AV because you're passing the argument by value. You need to pass its address instead. Try this: void main() { int i; get(file, i, i); writeln(i); } It will print 7.
Re: 3 variant questions
Dear Saaa, these varargs suck badly and you shouldn't use them. It's so simple to introduce portability errors or heisenbugs, and it's incredibly hard to get it right. You're better off with alternatives. Alternative 1: Typesafe Variadic Functions Useful if the variadic arguments should have only one type. And they're very easy to use. It's documented somewhere on http://www.digitalmars.com/d/1.0/function.html Alternative 2: Tuples http://www.digitalmars.com/d/1.0/template.html#TemplateTupleParameter The variadic arguments can have any types, but such functions can't really be virtual methods or delegates. Why is this extra step necessary and why won't simple casting not work? You should never directly work with _argptr. It's not guaranteed to be a simple pointer. For example, I believe that GCC will sometimes use registers (God only knows WHY). I think it's because GCC tries to keep the usual calling convention, where some arguments are passed as registers. Which is utterly pointless and stupid (ok, maybe it was easier to implement in gdc), and turns using varargs into hell. It would be so simple if _argptr was just an array of pointers to the actual arguments. It'd be so simple it makes me mad.
Who wants to have some fun memory debugging?
Running this program with Tango SVN + DMD 1.045 or Tango 0.98 + DMD 1.041 on WinXP SP3 32-bit results in a memory leak (the program keeps increasing in size at every iteration) leak.d: --- module leak; import tango.stdc.stdio; import tango.core.Memory; struct Data { Data* prev; char[4092] something; } public void main() { Data* data; Data* newData; int i; while(true) { for(i = 0; i 10_000; i++) { newData = new Data; newData.prev = data; data = newData; } data = null; newData = null; i = 0; GC.collect(); printf(Iteration...); fflush(stdout); fgetc(stdin); } } --- Running it through a debugger shows that at the printf, the entire contents of the stack frame of main is zeros and there's no global data referenced by the program.
Re: Who wants to have some fun memory debugging?
Simpler version, sans printf: module leak; import tango.core.Memory; struct Data { Data* prev; char[4092] something; } public void main() { Data* data; Data* newData; int i; while(true) { for(i = 0; i 10_000; i++) { newData = new Data; newData.prev = data; data = newData; } data = null; newData = null; i = 0; GC.collect(); } }
Re: Who wants to have some fun memory debugging?
Robert Fraser wrote: Simpler version, sans printf: module leak; import tango.core.Memory; struct Data { Data* prev; char[4092] something; } public void main() { Data* data; Data* newData; int i; while(true) { for(i = 0; i 10_000; i++) { newData = new Data; newData.prev = data; data = newData; } data = null; newData = null; At this point it's quite possible that you still have a reference to newData in a register. If you want to be sure the collect call below works as intended for this test, try adding: newData = new Data; here. i = 0; GC.collect(); } } Beyond that, you'll just potentially end up with a bunch of false positives, since you have a big static array in the same block as a pointer. But since you aren't actually setting the array contents in this test, that clearly isn't a problem here.