Thread overview
WinAPI callbacks and GC
Apr 23, 2013
Jack Applegame
Apr 24, 2013
evilrat
Apr 24, 2013
evilrat
Apr 24, 2013
Regan Heath
Apr 24, 2013
evilrat
May 01, 2013
Sean Kelly
May 02, 2013
Regan Heath
May 06, 2013
Sean Kelly
May 07, 2013
Regan Heath
April 23, 2013
I'm writing Ctrl-C handler for console application for Windows:

extern(Windows) {
  int CtrlHandler(uint flag) nothrow {
    auto tmp = new SomeClass; // is it safe?
    ...
    return true;
  }
}

...

SetConsoleCtrlHandler(&CtrlHandler, true);

...

According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow.
April 24, 2013
On Tuesday, 23 April 2013 at 21:21:28 UTC, Jack Applegame wrote:
> I'm writing Ctrl-C handler for console application for Windows:
>
> extern(Windows) {
>   int CtrlHandler(uint flag) nothrow {
>     auto tmp = new SomeClass; // is it safe?
>     ...
>     return true;
>   }
> }
>
> ...
>
> SetConsoleCtrlHandler(&CtrlHandler, true);
>
> ...
>
> According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow.

i guess it call ur callback(enters D code, so GC is in), alloc new instance, and after callback return it should collect it, but there is no such thing like guessing, just try it and see if it works correctly.

also there is an option without using GC at all, use struct instead of class if you don't need polymorphism(for most tasks structs is really enough, they are as powerful as c++ class just without polymorphism and other nasties)

also if you really need class or whole program lifetime memory, you may declare instance in module level with __gshared("__gshared SomeClass tmp;", don't forget to alloc if is class) so gc won't touch it.

also it may be better to read related docs in language reference on this site for more info, since i'm somehow bad with remembering all the details.
April 24, 2013
On Tuesday, 23 April 2013 at 21:21:28 UTC, Jack Applegame wrote:

> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow.

what stops you from calling normal functions in nothrow one? use try-catch inside nothrow. nothrow means that function doesn't throw, not it can call only nothrow.

also if another func is C language func, you may try to add nothrow to it's signature since it's anyway can't throw anything.

-------------------
example:

void doWithThrow()
{
int x = 1;
x++;
}

nothrow void doStuff()
{
try {
doWithThrow();
}
catch ( Exception e )
{
// your handling code here...
}
}

void main()
{
doStuff();
}
-------------------


i hope i don't learn people to do bad or stupid things :(
April 24, 2013
On Tue, 23 Apr 2013 22:21:27 +0100, Jack Applegame <japplegame@gmail.com> wrote:

> I'm writing Ctrl-C handler for console application for Windows:
>
> extern(Windows) {
>    int CtrlHandler(uint flag) nothrow {
>      auto tmp = new SomeClass; // is it safe?
>      ...
>      return true;
>    }
> }
>
> ...
>
> SetConsoleCtrlHandler(&CtrlHandler, true);
>
> ...
>
> According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow.

You are correct in that the issue with this handler is that it's likely called in a thread created by the Win32 runtime which the D GC has no knowledge of.  And, because of this wont get paused when the GC runs a collection, which is an issue because your allocation above might happen during a GC collection, and the GC is likely to have an 'issue' with it.

The issue here is a timing window.  Lets assume the GC is busy performing a collection when the handler runs.

If you wrap the thread_attachThis() in a try/catch block as evilrat has shown this should solve the nothrow issue.  But, the GC is unlikely to then pause your thread - because it's already done the thread pausing and is busy marking and sweeping so your thread will continue to run and allocate during collection.

The other idea is to call GC.disable() to disable automatic collection at the start of the handler, and GC.enable() at the end.  But again, if collection has already started this might not work, might fail horribly, and wont protect you.

Someone needs to check the GC code, and thread_attachThis to see if it can handle the situation you've presented.

Until then, I would perform manual memory allocation.  I am not sure how in D, but you need something like "placement new" to construct a class in a previously allocated block of memory (allocated with malloc or similar).

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
April 24, 2013
On Wednesday, 24 April 2013 at 09:51:29 UTC, Regan Heath wrote:
> Until then, I would perform manual memory allocation.  I am not sure how in D, but you need something like "placement new" to construct a class in a previously allocated block of memory (allocated with malloc or similar).

look at "__gshared", might be useful for when one need to interop things with non D code.

http://dlang.org/attribute.html#gshared
May 01, 2013
On Apr 23, 2013, at 2:21 PM, Jack Applegame <japplegame@gmail.com> wrote:
> 
> According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not no throw.


thread_attachThis should probably just be labeled nothrow.  I don't think there's anything in that function that can throw an Exception.
May 02, 2013
On Wed, 01 May 2013 01:12:39 +0100, Sean Kelly <sean@invisibleduck.org> wrote:

> On Apr 23, 2013, at 2:21 PM, Jack Applegame <japplegame@gmail.com> wrote:
>>
>> According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
>> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not no throw.
>
>
> thread_attachThis should probably just be labeled nothrow.  I don't think there's anything in that function that can throw an Exception.

That makes it callable.. but did you see my post about the various timing issues with using this in a non-GC thread (potentially while the GC is already collecting - or similar).

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 06, 2013
On May 2, 2013, at 6:17 AM, Regan Heath <regan@netmail.co.nz> wrote:

> On Wed, 01 May 2013 01:12:39 +0100, Sean Kelly <sean@invisibleduck.org> wrote:
> 
>> On Apr 23, 2013, at 2:21 PM, Jack Applegame <japplegame@gmail.com> wrote:
>>> 
>>> According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
>>> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not no throw.
>> 
>> 
>> thread_attachThis should probably just be labeled nothrow.  I don't think there's anything in that function that can throw an Exception.
> 
> That makes it callable.. but did you see my post about the various timing issues with using this in a non-GC thread (potentially while the GC is already collecting - or similar).

The GC holds a lock on the global thread list while collecting, so it shouldn't be possible for thread_attachThis to register a thread when this is happening.  In fact, thread_attachThis even temporarily disables the GC, and since this operation is protected by the GC lock, it's blocked there as well.
May 07, 2013
On Tue, 07 May 2013 00:03:58 +0100, Sean Kelly <sean@invisibleduck.org> wrote:

> On May 2, 2013, at 6:17 AM, Regan Heath <regan@netmail.co.nz> wrote:
>
>> On Wed, 01 May 2013 01:12:39 +0100, Sean Kelly <sean@invisibleduck.org> wrote:
>>
>>> On Apr 23, 2013, at 2:21 PM, Jack Applegame <japplegame@gmail.com> wrote:
>>>>
>>>> According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads?
>>>> If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not no throw.
>>>
>>>
>>> thread_attachThis should probably just be labeled nothrow.  I don't think there's anything in that function that can throw an Exception.
>>
>> That makes it callable.. but did you see my post about the various timing issues with using this in a non-GC thread (potentially while the GC is already collecting - or similar).
>
> The GC holds a lock on the global thread list while collecting, so it shouldn't be possible for thread_attachThis to register a thread when this is happening.  In fact, thread_attachThis even temporarily disables the GC, and since this operation is protected by the GC lock, it's blocked there as well.

Excellent.  Might be nice to see some of these details in the docs :p  .. or even just a "will block if collection is in progress".

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/