queries on druntime

Petar Petar
Thu Dec 14 08:00:44 UTC 2017


On Thursday, 14 December 2017 at 07:04:49 UTC, Arun 
Chandrasekaran wrote:
> Hi,
>
> What are the reasoning behind core.sync.* primitives being 
> classes and not structs?

There are several reasons as far as I know:
1) Structs in D can't have non-trivial constructors - i.e. you 
can't call pthread_mutex_init or InitializeCriticalSection to 
initialize the underlying OS object. If you go with structs, 
every call to lock, tryLock and unlock would have to first check 
if the object has been initialized, and the code would have to 
guard the initialization from data races. Or alternatively, the 
code would be unsafe, just like the pthread_* and Win32 APIs.

2) Structs in D best model values, something that doesn't have an 
identity and could be freely copied around. Yes, you can disable 
post-blit (with @disable `this(this);`) and opAssign, but given 
the fact that any API that uses them will receive the sync object 
by reference (e.g. either `Mutex*` or `ref Mutex`) if they were 
implemented as structs, it would really look better on the API 
level to simply have reference types.

3) Polymorphism. Third-party libraries like vibe-d have custom 
synchronization primitives that inherit those in druntime and 
override their functionality, in vibe-d's case to make them 
compatible with Fibers.

4) Class monitors currently work through the 
object.Object.Monitor interface, which core.sync.mutex.Mutex 
implements.

> This prevents them from being placing on shared memory.

Do you mean shared in the OS sense (mmap with MAP_ANONYMOUS | 
MAP_SHARED and whatever the Win32 analog is), or in the sense of 
the D type qualifier, e.g. shared(Mutex)?

If you mean shared(Mutex), that should already work since I fixed 
it a couple of releases ago. I haven't yet had the time to do the 
work for the rest of core.sync.*, though.

If you mean process shared memory, I agree that there are many 
valid cases where you want to be in control of the memory. I have 
been thinking about extracting the core of the synchronization 
primitives into @system structs, so users can have more control 
over them, though I haven't had the time for that either.

For now you have two options:
A) roll your own struct-based implementations
B) manually emplace the class instances on your piece of void[] 
memory. See 
https://github.com/dlang/druntime/blob/v2.077.1/src/core/sync/mutex.d#L342 for an example.


More information about the Digitalmars-d mailing list