Thank you very much for your feedback! Especially for pointing out the short-hand template notation and the nested class access to parent members - I'll have a closer look at that part of the language documentation :)

I've implemented most of your recommendations (and updated the gist), but faced some questions on the way. Assuming those get resolved, do you think the class would be fit for inclusion into vibe.d? If so, I could file a pull request...

atomicOp vs. interrupt()

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()).

As far as I understand it, Task.interrupt() causes an exception to be thrown at the next yielding instruction of a fiber. I reckoned this could lead to an interruption to occur before the counter is decremented in unlock(), thus resulting in a potential deadlock. Am I mistaken in this regard?
As a possible tradeoff I would see to only use a non-interruptible TaskMutex to guard the counters, which would mean that lock() could only lead to interrupts while performing a wait() operation.

shared
Also, I faced a problem as I took apart the definitions for TaskReadWriteMutex and InterruptibleTaskReadWriteMutex (i.e. deleting the alias statements): It seems that the compiler is no longer able to infer the implication of using them as shared objects - and since shared is transitive and I then basically have to "share all the things", I'm no longer able to properly override the core.sync.mutex.Mutex interface, which has no defined shared methods. Also, constructing a shared TaskMutex seems rather tricky.
For now I got around the problem by stripping the shared attribute off the mutex in app.d, but I'm not sure if that's a particularly good idea. It seems to work as a member of a web interface object, but fails if the mutex is defined globally (presumably because it resides in TLS and appears as a null-reference in other threads).

issue 1280
On Sat, 26 Sep 2015 07:12:49 GMT, Sönke Ludwig wrote:

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

Sadly, the issue still persists on my machine. The Arch package claims it has the newest version (dmd-2.068.2-1) but I still get the same error whenever I uncomment the distribute line in my gist:

λ manuel-laptop rwmutex → dub
Performing "debug" build using dmd for x86_64.
vibe-d 0.7.25: target for configuration "libevent" is up to date.
foo ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
Running ./foo 
Worker thread terminated due to uncaught error: No event driver loaded. Did the vibe.core.core module constructor run?
Worker thread terminated due to uncaught error: No event driver loaded. Did the vibe.core.core module constructor run?
Program exited with code 255

Sadly, the compiler doesn't print out the whole version string. That said, I did some tests using gdc and ldc and haven't seen any strange behavior so far.

λ manuel-laptop rwmutex → dmd --version
DMD64 D Compiler v2.068
Copyright (c) 1999-2015 by Digital Mars written by Walter Bright

Registration error

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

Sadly, I didn't pay too much attention at the time, but it seemed like a very generic internal server error message to me.