Leave GC collection to the user of the D library?
Vladimir Panteleev
thecybershadow.lists at gmail.com
Sun May 9 13:51:26 UTC 2021
On Sunday, 9 May 2021 at 03:25:06 UTC, Ali Çehreli wrote:
> That workaround seemed to be sufficient to load the library
> successfully. Unfortunately, that was not enough to weed out
> all issues related to libraries because this library itself
> loads other D libraries. All of this caused sporadic issues.
> (My brain is too fried to even remember what was a cause, what
> was a usable workaround, etc. Sometimes I wasted days chasing a
> solution while using a test, which had nothing to do with the
> solution. I would change the code, test, no go; repeat, no go.
> It turns out, my test was unrelated. Argh!)
In my experience, calling D from C/C++ works fine as long as 1)
the D runtime is allowed to initialize, and 2) all threads which
execute D code are registered with the D runtime.
If C/C++ code is allowed to hold the only reference to an object
in the D GC heap, then the second rule needs to be extended to
all threads which may hold a reference to said objects, but it
may be practical to copy D objects at the C/D barrier either to
caller-owned memory, or malloc-allocated memory that the caller
can free by calling the standard C `free` function.
> So, we came up with a drastic solution: Since all this code
> works just fine in a pure D environment, make the library as
> thin as possible; the library starts a daemon that is written
> in D with all the functionality. The library merely dispatches
> the requests to that daemon.
>
> The library starts the daemon with pipeProcess(); pipes are
> used for dispatching requests and shared memory is used for
> large data. This idea "worked like a charm." Phew!
>
> However, dispatching of the requests to the daemon is performed
> by a single library thread in a blocked manner: When a request
> is written to the pipe, the response is read back (blocked) and
> the result is returned to the user of the library function.
If the threads don't need to share state, you could just as well
spawn one subprocess per thread, and let it do its own data
processing.
Another approach would be to listen on a UNIX socket instead of
using a pipe, which allows using `accept` to open new
communication channels on-demand.
> I feel so hopeless that in the past, I even thought about and
> experimented with banning the user from starting threads on
> their own. Rather, they would call my library on a posix
> compatible thread API and create their threads through me,
> which happens to be a D thread, so no thread would be a
> "foreign thread" and everything would work just fine. I haven't
> deployed this crazy idea (yet).
Perhaps it would be simpler to just write the library part in C /
C++ / -betterC D. std.mmfile has many lines, but the work it has
to do is actually quite simple. The same is true about
std.socket. This will completely avoid your headache with getting
the D runtime / GC to play well with the host process's threading
model.
More information about the Digitalmars-d
mailing list