digitalmars.D - new thread with nested function
- bobef (3/3) Apr 06 2005 I don't know if this is a bug so I post it here. If new thread is starte...
- Regan Heath (5/10) Apr 06 2005 Do you exit the parent function after starting the thread?
- bobef (7/17) Apr 07 2005 Yes I exit the parent function. And by 'dead' I mean I do not get compil...
- Ben Hinkle (9/19) Apr 07 2005 Disallowing passing nested functions would be pretty harsh. It would be ...
- Regan Heath (56/67) Apr 07 2005 I suspect that's exactly what is happening.
- Regan Heath (18/70) Apr 07 2005 I forgot to mention. This example was actually my test to see what happe...
- Russ Lewis (3/90) Apr 07 2005 If you allocated the struct on the stack, then it should not be GC'd
- Regan Heath (4/80) Apr 07 2005 So, you think I have found a bug below?
- Russ Lewis (5/95) Apr 07 2005 EEK! Sorry, I mistyped. What I meant to say was that you allocate it
- Regan Heath (4/8) Apr 07 2005 Yep. That's what I thought.
- Sean Kelly (10/15) Apr 07 2005 I would expect your sample code to (probably) output:
- Regan Heath (3/23) Apr 07 2005 You are correct :)
- Sean Kelly (5/18) Apr 07 2005 Right. Any GCed object won't be cleaned up until all references to it a...
- David Medlock (13/45) Apr 07 2005 From reading the issues, it appears the problem is delegates are just a...
- Sean Kelly (3/6) Apr 07 2005 They are. True closures have been discussed but are not currently a par...
- Russ Lewis (10/68) Apr 07 2005 Right. I have been an advocate of being able to copy the stack
I don't know if this is a bug so I post it here. If new thread is started with nested function as delegate it sees it's parents variables and class variables (if parent is class member) but they are all 'dead'...
Apr 06 2005
On Wed, 6 Apr 2005 20:58:28 +0000 (UTC), bobef <bobef_member pathlink.com> wrote:I don't know if this is a bug so I post it here. If new thread is started with nested function as delegate it sees it's parents variables and class variables (if parent is class member) but they are all 'dead'...Do you exit the parent function after starting the thread? What is meant by "dead" exactly? Regan
Apr 06 2005
Yes I exit the parent function. And by 'dead' I mean I do not get compiler errors but memory contained in these vairables is unsusable (corrupted, moved or deallocated or something like that). I suppose parent's variables are released when it gets out of scope or something like that but I think then it should be forbidden to pass nested functions as parameters for threads or something like that... In article <opsoufcrkw23k2f5 nrage.netwin.co.nz>, Regan Heath says...On Wed, 6 Apr 2005 20:58:28 +0000 (UTC), bobef <bobef_member pathlink.com> wrote:I don't know if this is a bug so I post it here. If new thread is started with nested function as delegate it sees it's parents variables and class variables (if parent is class member) but they are all 'dead'...Do you exit the parent function after starting the thread? What is meant by "dead" exactly? Regan
Apr 07 2005
"bobef" <bobef_member pathlink.com> wrote in message news:d33574$1s6j$1 digitaldaemon.com...Yes I exit the parent function. And by 'dead' I mean I do not get compiler errors but memory contained in these vairables is unsusable (corrupted, moved or deallocated or something like that). I suppose parent's variables are released when it gets out of scope or something like that but I think then it should be forbidden to pass nested functions as parameters for threads or something like that...Disallowing passing nested functions would be pretty harsh. It would be like disallowing passing pointers to local variables to functions because the pointers could be held onto and dereferenced after the local variable is no longer valid. If the documentation on threading or nested functions could include a little blurb about the dangers of passing nested functions to threads (or for that matter doing anything that runs a nested function after the stack is gone).
Apr 07 2005
On Thu, 7 Apr 2005 11:23:16 +0000 (UTC), bobef <bobef_member pathlink.com> wrote:Yes I exit the parent function. And by 'dead' I mean I do not get compiler errors but memory contained in these vairables is unsusable (corrupted, moved or deallocated or something like that). I suppose parent's variables are released when it gets out of scope or something like thatI suspect that's exactly what is happening.but I think then it should be forbidden to pass nested functions as parameters for threads or something like that...I'm with Ben on this one. Here is an example highlighting the issue: (windows only, sorry linux guys) import std.c.windows.windows; import std.stdio; import std.thread; import std.stream; struct stest { int a = 5; int run() { writefln("s",a); Sleep(1000); writefln("s",a); Sleep(1000); writefln("s",a); } } class ctest { int a = 6; int run() { writefln("c",a); Sleep(1000); writefln("c",a); Sleep(1000); writefln("c",a); } } void main() { fire(); Sleep(10000); } void fire() { Thread t; ctest b = new ctest(); stest a; t = new Thread(&a.run); t.start(); t = new Thread(&b.run); t.start(); Sleep(1000); } Regan
Apr 07 2005
I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. stored on the stack, not a reference. code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked. Have I overlooked something? Regan On Fri, 08 Apr 2005 00:40:33 +1200, Regan Heath <regan netwin.co.nz> wrote:Here is an example highlighting the issue: (windows only, sorry linux guys) import std.c.windows.windows; import std.stdio; import std.thread; import std.stream; struct stest { int a = 5; int run() { writefln("s",a); Sleep(1000); writefln("s",a); Sleep(1000); writefln("s",a); } } class ctest { int a = 6; int run() { writefln("c",a); Sleep(1000); writefln("c",a); Sleep(1000); writefln("c",a); } } void main() { fire();Sleep(1000); fullCollect();Sleep(10000); } void fire() { Thread t; ctest b = new ctest(); stest a; t = new Thread(&a.run); t.start(); t = new Thread(&b.run); t.start(); Sleep(1000); } Regan
Apr 07 2005
If you allocated the struct on the stack, then it should not be GC'd until the delegate goes away. Regan Heath wrote:I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. stored on the stack, not a reference. code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked. Have I overlooked something? Regan On Fri, 08 Apr 2005 00:40:33 +1200, Regan Heath <regan netwin.co.nz> wrote:Here is an example highlighting the issue: (windows only, sorry linux guys) import std.c.windows.windows; import std.stdio; import std.thread; import std.stream; struct stest { int a = 5; int run() { writefln("s",a); Sleep(1000); writefln("s",a); Sleep(1000); writefln("s",a); } } class ctest { int a = 6; int run() { writefln("c",a); Sleep(1000); writefln("c",a); Sleep(1000); writefln("c",a); } } void main() { fire();Sleep(1000); fullCollect();Sleep(10000); } void fire() { Thread t; ctest b = new ctest(); stest a; t = new Thread(&a.run); t.start(); t = new Thread(&b.run); t.start(); Sleep(1000); } Regan
Apr 07 2005
On Thu, 07 Apr 2005 09:52:28 -0700, Russ Lewis <spamhole-2001-07-16 deming-os.org> wrote:If you allocated the struct on the stack, then it should not be GC'd until the delegate goes away.So, you think I have found a bug below? ReganRegan Heath wrote:I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. type stored on the stack, not a reference. (see code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked. Have I overlooked something? Regan On Fri, 08 Apr 2005 00:40:33 +1200, Regan Heath <regan netwin.co.nz> wrote:Here is an example highlighting the issue: (windows only, sorry linux guys) import std.c.windows.windows; import std.stdio; import std.thread; import std.stream; struct stest { int a = 5; int run() { writefln("s",a); Sleep(1000); writefln("s",a); Sleep(1000); writefln("s",a); } } class ctest { int a = 6; int run() { writefln("c",a); Sleep(1000); writefln("c",a); Sleep(1000); writefln("c",a); } } void main() { fire();Sleep(1000); fullCollect();Sleep(10000); } void fire() { Thread t; ctest b = new ctest(); stest a; t = new Thread(&a.run); t.start(); t = new Thread(&b.run); t.start(); Sleep(1000); } Regan
Apr 07 2005
EEK! Sorry, I mistyped. What I meant to say was that you allocate it on the *HEAP*, then it should not be GC'd until the delegate goes away. Structs on the stack definitely *do* become invalid the moment that you return from the function. Regan Heath wrote:On Thu, 07 Apr 2005 09:52:28 -0700, Russ Lewis <spamhole-2001-07-16 deming-os.org> wrote:If you allocated the struct on the stack, then it should not be GC'd until the delegate goes away.So, you think I have found a bug below? ReganRegan Heath wrote:I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. type stored on the stack, not a reference. (see code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked. Have I overlooked something? Regan On Fri, 08 Apr 2005 00:40:33 +1200, Regan Heath <regan netwin.co.nz> wrote:Here is an example highlighting the issue: (windows only, sorry linux guys) import std.c.windows.windows; import std.stdio; import std.thread; import std.stream; struct stest { int a = 5; int run() { writefln("s",a); Sleep(1000); writefln("s",a); Sleep(1000); writefln("s",a); } } class ctest { int a = 6; int run() { writefln("c",a); Sleep(1000); writefln("c",a); Sleep(1000); writefln("c",a); } } void main() { fire();Sleep(1000); fullCollect();Sleep(10000); } void fire() { Thread t; ctest b = new ctest(); stest a; t = new Thread(&a.run); t.start(); t = new Thread(&b.run); t.start(); Sleep(1000); } Regan
Apr 07 2005
On Thu, 07 Apr 2005 16:03:28 -0700, Russ Lewis <spamhole-2001-07-16 deming-os.org> wrote:EEK! Sorry, I mistyped. What I meant to say was that you allocate it on the *HEAP*, then it should not be GC'd until the delegate goes away. Structs on the stack definitely *do* become invalid the moment that you return from the function.Yep. That's what I thought. Regan
Apr 07 2005
In article <opsovvsbcn23k2f5 nrage.netwin.co.nz>, Regan Heath says...On Thu, 07 Apr 2005 09:52:28 -0700, Russ Lewis <spamhole-2001-07-16 deming-os.org> wrote:I would expect your sample code to (probably) output: 5 6 At this point the app may print something and it may just explode, as I expect 'a' would have gone out of scope. Best case would be for it to print 6 twice more and either 5, 0, or something random for the other two lines. But none of this is guaranteed, since nothing says the new threads will actually start in the 1 second before fire() exits. SeanIf you allocated the struct on the stack, then it should not be GC'd until the delegate goes away.So, you think I have found a bug below?
Apr 07 2005
On Thu, 7 Apr 2005 23:14:17 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:In article <opsovvsbcn23k2f5 nrage.netwin.co.nz>, Regan Heath says...You are correct :) ReganOn Thu, 07 Apr 2005 09:52:28 -0700, Russ Lewis <spamhole-2001-07-16 deming-os.org> wrote:I would expect your sample code to (probably) output: 5 6 At this point the app may print something and it may just explode, as I expect 'a' would have gone out of scope. Best case would be for it to print 6 twice more and either 5, 0, or something random for the other two lines. But none of this is guaranteed, since nothing says the new threads will actually start in the 1 second before fire() exits.If you allocated the struct on the stack, then it should not be GC'd until the delegate goes away.So, you think I have found a bug below?
Apr 07 2005
In article <opsou4v7p323k2f5 nrage.netwin.co.nz>, Regan Heath says...I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. stored on the stack, not a reference.Right.code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked.Right. Any GCed object won't be cleaned up until all references to it are gone. The thread these references are held in is not an issue. Sean
Apr 07 2005
From reading the issues, it appears the problem is delegates are just a way of referencing local variables where the function was called rather than true closures. For those interested, true closures allow a function to 'capture' values at the time the function is created(not declared), and the values it takes along with it are called upvalues. A nice example of this is Paul Grahams challenge to create an accumulator: http://store.yahoo.com/paulgraham/accgen.html Which is possible with classes and templates, but it fairly messy. Lua properly handles upvalues, its design is quite interesting: http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/sblp2005.pdf -David Sean Kelly wrote:In article <opsou4v7p323k2f5 nrage.netwin.co.nz>, Regan Heath says...I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. stored on the stack, not a reference.Right.code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked.Right. Any GCed object won't be cleaned up until all references to it are gone. The thread these references are held in is not an issue. Sean
Apr 07 2005
In article <d34eoo$t6m$1 digitaldaemon.com>, David Medlock says...From reading the issues, it appears the problem is delegates are just a way of referencing local variables where the function was called rather than true closures.They are. True closures have been discussed but are not currently a part of D. Sean
Apr 07 2005
Right. I have been an advocate of being able to copy the stack variables onto the heap, so that you can create (something like?) true closures. It hasn't gotten in, yet. I was just thinking today about a complexity that I hadn't considered before, though. What happens if a function has out or inout parameters? If we're trying to create something where the function can do use (copies of) the local variables after the function has returned, then how do we handle these types of parameters? For now, I'm using structs, but as you said, it's ugly. David Medlock wrote:From reading the issues, it appears the problem is delegates are just a way of referencing local variables where the function was called rather than true closures. For those interested, true closures allow a function to 'capture' values at the time the function is created(not declared), and the values it takes along with it are called upvalues. A nice example of this is Paul Grahams challenge to create an accumulator: http://store.yahoo.com/paulgraham/accgen.html Which is possible with classes and templates, but it fairly messy. Lua properly handles upvalues, its design is quite interesting: http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/sblp2005.pdf -David Sean Kelly wrote:In article <opsou4v7p323k2f5 nrage.netwin.co.nz>, Regan Heath says...I forgot to mention. This example was actually my test to see what happens with structs vs classes. What I was trying to answer was: 1. does passing a struct delegate to a thread stop the struct from being free'd. 2. does passing a class delegate to a thread stop the class from being free'd. type stored on the stack, not a reference.Right.(see code below). It appears passing a class delegate, prevents the class from being free'd, which is good, I wondered whether the delegate pointer would do that, or if it had been overlooked.Right. Any GCed object won't be cleaned up until all references to it are gone. The thread these references are held in is not an issue. Sean
Apr 07 2005