Re: Who wants to have some fun memory debugging?

2009-05-12 Thread grauzone

Maybe it's time to put together an instrumented GC...


Wishlist:
- some way to know _when_ a collection happened (or how often)
- logging of allocations (module/linenumber of allocator, size of 
allocation, type of allocation)

- per TypeInfo allocation statistics
- per module allocation statistics


Re: Who wants to have some fun memory debugging?

2009-05-12 Thread Daniel Keep


Sean Kelly wrote:
> ...
> 
> 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.

Debugging it with ddbg under Win XP, I found that at "data = null",
there is what appears to be a pointer to the newest allocation in EDX,
and a pointer to the previous one in ECX.

>> i = 0;

After this line, the ECX reference hasn't been touched.

>> GC.collect();

Disassembling the code, there's nothing that touches ECX before the call
to GC.collect, so it's quite probable that this is why the memory isn't
being freed in a given iteration, but not necessarily why it isn't being
collected at all.

I modified the code to explicitly zero-out ECX just before the call to
GC.collect, and it didn't appear to help.

I then instrumented the code with calls to gc_stats.  Here is the run of
it reporting the stats AFTER each forced collect (output via printf):

GCStats: poolsize, usedsize, freeblocks, freelistsize, pageblocks
GCStats: 81985536, 640, 16, 7552, 
GCStats: 16384, 640, 3200, 7552, 18399
GCStats: 232652800, 640, 2030, 7552, 27384
GCStats: 306315264, 640, 5948, 7552, 34417
GCStats: 360251392, 640, 6954, 7552, 40498
GCStats: 410517504, 640, 5502, 7552, 47360
GCStats: 469958656, 640, 8498, 7552, 53118

The program also got progressively slower as the size of the heap
increased.  Odd thing is that it would pause at a certain heap size for
many seconds at a time, increase in size, pause, increase, pause... it
was like the allocations were getting slower.

What's also weird is that even though the heap usage should be the same
each iteration, it's clearly creating more and more blocks.  It's like
the GC is freeing those blocks, but the allocator isn't using them.

Then I ran it so that it would compute the difference of gc_stats before
and after the collect.  This one is somewhat depressing:

GCStats: poolsize, usedsize, freeblocks, freelistsize, pageblocks
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1
GCStats: 0, 0, 2, 0, -1

It appears to free *two* blocks and consume an extra page during a
collection, but doesn't affect the pool or used size at all.

Maybe it's time to put together an instrumented GC...

  -- Daniel


Re: Who wants to have some fun memory debugging?

2009-05-12 Thread grauzone
Wild guess: there's a false pointer, that keeps one element in the list 
from being collected, and because the list-prev pointers are still 
there, all following elements won't be collected either in consequence.


If I had time, I'd try two experiments:
1. before freeing everything, reset the prev field of each element; if 
this makes the leak go away, my guess would probably be right
2. use the destructor (Data had to be a class) to keep track of how many 
elements are actually freed by the GC (just a thread safe counter, 
that's incremented in the ctor and decremented in the dtor); just to 
find out if this is an internal GC problem, or if you have too many live 
garbage


Re: Who wants to have some fun memory debugging?

2009-05-12 Thread Robert Fraser

Sean Kelly wrote:
At this point it's quite possible that you still have a reference to 
newData in a register.  


That argument works for one iteration, but this fool just keeps on 
growing. Also, this is a pared down test from a much larger program, so 
this is unlikely.


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();
}
}


Nope, didn't do anything. It still swells forever.

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.


The real program is a tree structure that contains class references, so 
is entirely pointers. The root of the tree is then discarded, and a new 
tree created, however the old tree isn't being collected.


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.


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: A couple of questions

2009-05-12 Thread BCS

Hello Sam,


Hello,

For the given example below,

E1:
template Chain(R...) if (allSatisfy!(isInputRange, R))
{
static if (R.length > 1)
alias ChainImpl!(R) Chain;
else
alias R[0] Chain;
}
Q1: What's *if* statement doing right after the template definite?I
can guess what the purpose is but I can not find the answer from the
spec.

E2:
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
}()));
}
Q2:What's the logic inside the enum...{} blocks?


That is an odd construct and not an enum block, breaking it into pieces:

enum bool isInputRange = SomeBoolExp;

SomeBoolExp:  // true if SomeExp is a valid expression
   is(typeof(SomeExp))

SomeExp:  // a function call
   SomeFnExp()

SomeFnExp: // a delegate literal
   {
  R r; // can define a range object
  if (r.empty) {}  // can test for empty
  r.popFront;  // can invoke next
  auto h = r.front; // can get the front of the range
   }



Q3:The *typeof* expression here. is it an anonymous function/delegate
which return a bool value?If not,how come there is a () pairs appeared
right after the enum{}blocks?If yes,shouldn't the () pairs appear
before the last *)* ?
It would be grateful if anybody can help.


see above



Regards,
Sam





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.


A couple of questions

2009-05-12 Thread Sam Hu
Hello,

For the given example below,

E1:
template Chain(R...) if (allSatisfy!(isInputRange, R))
{
static if (R.length > 1)
alias ChainImpl!(R) Chain;
else
alias R[0] Chain;
}
Q1: What's *if* statement doing right after the template definite?I can guess 
what the purpose is but I can not find the answer from the spec.

E2:
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
}()));
}

Q2:What's the logic inside the enum...{} blocks?
Q3:The *typeof* expression here. is it an anonymous function/delegate which 
return a bool value?If not,how come there is a () pairs appeared right after 
the enum{}blocks?If yes,shouldn't the () pairs appear before the last *)* ?

It would be grateful if anybody can help.

Regards,
Sam


invariant

2009-05-12 Thread saotome
Hi all,

i want to declare an invariant interger, for instance "invariant int x = 3;". 
But i've got this error while compiling.

Error: constant 3 is not an lvalue

could someone explain me what's wrong here ? I'm using dmd 2.030



Re: 3 variant questions

2009-05-12 Thread Saaa

> 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
heisenbugs :)
> 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

It doesn't say much about setting/changing the passed arguments.

How do these differ?

int test1( int i ...) { return i;}
int test2( int i ) { return i;}
test1(3);  // returns 3
test2(3);  // returns 3

>
> 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.

Well, I should learn about them templates anyways :)
Templates create the necessary appropriately typed instances of a function
 at compile-time.. seems more usefull as my get function should work with
any type.

>
>>> 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. 




Re: 3 variant questions

2009-05-12 Thread Saaa
>>
>
> 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".

Ah of course, thanks. 




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.


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: Threading

2009-05-12 Thread Saaa

"Georg Wrede"  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 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 Georg Wrede

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.




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: Threading

2009-05-12 Thread Steven Schveighoffer

On Tue, 12 May 2009 10:12:48 -0400, Saaa  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.

>
> 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 05:11:49 -0400, Brok3n Halo   
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.


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.


D2 promises to be a lot better at helping you ensure this.



Also I'm still getting the "Error: Win32 Exception" with my test code  
any idea

why? Attached is the latest version.


Just realized from reading your code, you are using D1 with Phobos, I have  
no idea what bugs there are, or how to use threads there, so I can't  
really help you.


I can tell you that your code ported to Tango runs without throwing an  
exception, code below:


import tango.core.Thread;
import tango.io.Stdout;

int count = 0;

void main(){

Thread testthread;

void testfunc(){
while(count<1000){
++count;
}
}


testthread = new Thread(&testfunc);
testthread.start();


int lastCount = 0;
while(testthread.isRunning){
if(count != lastCount){
Stdout.formatln("{}", count);
lastCount = count;
}
}

}

output:

164
16789
23750
29998
36054
4472263
4482283
4488871
4495320
4501356
4507264
4513158
4518987
4524886
4530722
4536557
4542362
4548221
4554051
4559848
4565753
4571592
4577354
4583152
4588942
4594719
4600579
4606375
4612181
4617981
4623686
4629421


-Steve


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: 3 variant questions

2009-05-12 Thread Saaa

"Daniel Keep"  wrote in message 
news:gubip2$187...@digitalmars.com...
>
>
> Saaa wrote:
>> I just noticed D1 does have std.stdarg.
>> I shouldn't just search on the website :(
>> (where it is missing on the phobos page)
>>
>>> import std.stdarg;
>>>
>>> assert( _arguments[0] is typeid(int*) );
>>> auto arg = va_arg!(int*)(_argptr);
>>> *arg = 10;
>>>
>>> Probably.
>> :D
>>>  -- Daniel
>>
>> So, you make arg point to the same as va_arg.
>
> No, va_arg is a function.
I meant to write _argptr :)

>
>> 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).
ok...
>
> 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

>
>  -- Daniel 




Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
> I just noticed D1 does have std.stdarg.
> I shouldn't just search on the website :(
> (where it is missing on the phobos page)
> 
>> import std.stdarg;
>>
>> assert( _arguments[0] is typeid(int*) );
>> auto arg = va_arg!(int*)(_argptr);
>> *arg = 10;
>>
>> Probably.
> :D
>>  -- Daniel
> 
> So, you make arg point to the same as va_arg.

No, va_arg is a function.

> 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).

var_arg!(T) will convert _argptr into the type you specify and it will
also advance _argptr to the next argument.

  -- Daniel


Re: 3 variant questions

2009-05-12 Thread Saaa

I just noticed D1 does have std.stdarg.
I shouldn't just search on the website :(
(where it is missing on the phobos page)

> import std.stdarg;
>
> assert( _arguments[0] is typeid(int*) );
> auto arg = va_arg!(int*)(_argptr);
> *arg = 10;
>
> Probably.
:D
>
>  -- Daniel

So, you make arg point to the same as va_arg.
Why is this extra step necessary and why won't simple casting not work?




Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
>> Saaa wrote:
>>> ...
>>> Passing variadic arguments as ref I think is what I am asking for :)
>> You can't.  You have to explicitly take the address of the arguments.
>>
>>  -- Daniel
> 
> Like this ?
> *_argptr = 10;
> :D
> 
> I don't know how to tell the compiler I want to write data there.

import std.stdarg;

assert( _arguments[0] is typeid(int*) );
auto arg = va_arg!(int*)(_argptr);
*arg = 10;

Probably.

  -- Daniel


Re: Threading

2009-05-12 Thread Saaa
I have never used threads before, but it sounds safe to me as when the 
thread gets thrown of the core and later gets back nothing referred by the 
register has changed.
Again, I am a newbie :)

"Brok3n Halo"  wrote in message 
news:gubegl$uu...@digitalmars.com...
>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?
>
> Also I'm still getting the "Error: Win32 Exception" with my test code any 
> idea
> why? Attached is the latest version.
> 




Re: 3 variant questions

2009-05-12 Thread Saaa

> Saaa wrote:
>> ...
>> Passing variadic arguments as ref I think is what I am asking for :)
>
> You can't.  You have to explicitly take the address of the arguments.
>
>  -- Daniel

Like this ?
*_argptr = 10;
:D

I don't know how to tell the compiler I want to write data there.




Re: Threading

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

Also I'm still getting the "Error: Win32 Exception" with my test code any idea
why? Attached is the latest version.
begin 644 test.d
M;6]D=6QE('1EPT*"0EI9BAC;W5N="`A/2!L87-T0V]U;G0I>PT*"0D)=W)I=&5F;&XH
M(B5D(b...@8v]u;G0I.PT*"0D);&%S=$-O=6YT(#...@8v]u;G0[#0H)"7T-"@E]
%#0H-"GT`
`
end


Re: 3 variant questions

2009-05-12 Thread Daniel Keep


Saaa wrote:
> ...
> Passing variadic arguments as ref I think is what I am asking for :) 

You can't.  You have to explicitly take the address of the arguments.

  -- Daniel