On Wed, 23 Sep 2015 12:49:26 GMT, Manuel Frischknecht wrote:

For a personal little project, I'm trying to build a rather simple CMS based on a Git repository rather than a complicated database schema. To avoid potential conflicts caused by concurrent file reads/writes, I thought I could use a fiber-affine counterpart to core.sync.rwmutex.

Since I am not aware of such a module already existing, I thought I'd try to write it myself. You can find the result of my attempt in this gist.
So far, I've done some simple print-based testing using the simple application in the gist (using version RWMutexPrint). Unfortunately, I currently face issue 1250 on my machine (Arch Linux) didn't get around to test the mutex using the HTTPServerOption.distribute option.

DMD 2.068.2 is out since a few days, so it should be working again now.

Since I'm not (yet) too familiar with D and vibe.d I'd be glad if someone who is more adept in the internals of the library could have a glance at the code and point out any potential pitfalls.
Thank you in advance! :)

Since such code is always tricky due to all of the corner cases that exist in low-level multi-threaded code, there are probably things that I haven't considered, but the general approach looks good and sound. The only potential issue that I saw is the use of atomic operations for changing the various counters. Since you already need to lock a mutex, it should be more efficient to simply reuse it for protecting the counters (in the unlock() code, using the mutex would amount to about two atomic ops, but it saves a few more during lock()). Functionally, everything looks correct.

WRT the code itself, it looks like C++ habit that template member functions are written as template(ARGS) { void fn(args) {} }. I'd always prefer the shorter void fn(ARGS)(args) {} syntax if there are no technical reasons against it.

The TaskReadWriteMutexImpl.Mutex class as a non-static nested class already has access to the _state member of TaskReadWriteMutex, so you can either remove its own _state field, or declare it as static class Mutex(...). The latter is probably slightly more efficient, not that it would matter much at that scale*. Along those lines, I'd also declare the classes final, so that virtual calls to lock and unlock can be elided.

Finally, since TaskReadWriteMutexImpl is private, the TaskReadWriteMutex aliases would have no meaningful member documentation in the API reference. Unfortunately, some code duplication will be necessary here for purely "cosmetical" reasons (making them classes and declaring reader and writer in both of them instead of in the base class).

PS: I just registered in this forum and git a server error 500 back. Since I don't know who exactly might be interested in this, I thoght I'd mention it here.

Do you perhaps still remember if there was any more specific error message? Unfortunately I haven't implemented error logging for the forum, yet.

* Thinking about it, another possibility would be to keep them non-static, but convert ReadWriteMutexState to a struct. That saves another GC allocation and access should be as efficient as before (single indirection). The struct should probably get a @disable this(this); postblit constructor to disable accidental copying.