What is safe to do in an extern (C) function and how can I test this?

Jaime benjamin.i.mccann at gmail.com
Tue Jan 25 01:31:29 UTC 2022


**The lede**:

Can I, for instance, safely call Fiber.yield in a C callback that 
I know will be run in a Fiber?

The stack will look like:
Thread
|- Fiber in D runtime
| |- Call into a C API (stays on same thread)
| | |- Extern (C) callback (stays on same thread)
| | | |- Fiber.yield <-- Is this OK?

Also, in general, is there a convenient way to know or test if 
particular C callbacks are safe? Or is it just case by case?

**The context I was gonna bury the lede in but thought better of 
it**:

So, I am a big lame novice. Don't worry, I know this already.

I'm trying to use gtk-d, but I don't even know how to use gtk, so 
I'm learning them both at once. Probably not a good idea, I know.

 From what I can tell so far, it seems like the way gtk works is 
you write your whole application in terms of gtk's event loop. I 
really don't want to do that, so -- and I realize this is 
probably an even worse idea, but I don't know the right thing to 
do -- I decided I'd try writing a worker thread class -- "Rope" 
-- and run gtk's event loop in a Rope.

A Rope runs its given task in a new Fiber in a new thread, and 
that thread repeatedly resumes the fiber and terminates when the 
fiber terminates, but, in the meantime, takes some time to act as 
an executor each time the fiber suspends, accepting work in 
std.concurrency messages and running it on the same thread as its 
main fiber. My thought was that this way, I can call gtk-d's API 
from any thread, and still have all the calls happen on the same 
thread that the event loop is running on, as the API requires.

All I needed, then, was some way to make gtk-d suspend the fiber 
it's running on, to give its rope some time to service external 
work. My first thought was to use glib.Timeout.Timeout.add and 
put Fiber.yield in the timeout callback. The potential problem: 
the timeout callback, of course, has to be extern (C).

Now, I could just drop the more general concept of Rope and 
rewrite it specifically for gtk, and drop the whole Fiber part, 
and instead directly put the calls to 
std.concurrency.receiveTimeout in the glib.Timeout.Timeout.add 
callback. Assuming, of course, receiveTimeout would be any safer 
to call from extern (C) than Fiber.yield would. But that's just 
the trouble, I can't guess which would be safer, and even a 
minimal test for this question seems daunting.


More information about the Digitalmars-d-learn mailing list