Re: Finding out about D - 102

2009-05-12 Thread Steve Teale
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

2009-05-12 Thread Daniel Keep


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

2009-05-12 Thread Saaa


 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

2009-05-12 Thread Steven Schveighoffer

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

2009-05-12 Thread Saaa

 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

2009-05-12 Thread Saaa

 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

2009-05-12 Thread Saaa

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

2009-05-12 Thread John C
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

2009-05-12 Thread grauzone
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?

2009-05-12 Thread Robert Fraser
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?

2009-05-12 Thread Robert Fraser

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?

2009-05-12 Thread Sean Kelly

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.