Am 26.09.2015 um 16:26 schrieb Manuel Frischknecht:

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

It looks like a logical extension to the current functionality and the
code looks good, too, so this definitely would be a very welcome addition!

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.

Actually, I'd even just use a normal Mutex in this case, as the fiber
never yields while it is locked, so the Task part of the functionality
isn't really necessary anyway. It should also be a bit more efficient.

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

Yeah, the shared situation generally still is very unfortunate in many
ways (especially since proper deprecation/upgrade paths to improve it
are often difficult). But did you try to make the two classes template
classes with an empty template parameter list? That should bring back
the attribute inference of the old code (attributes are only inferred
within templated functions and aggregates).

(...)

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.

I reproduced it now, only to discover that this had actually already
been fixed in code quite a while ago ;) The current version of the
forums with the fix included is deployed now. Thanks for the notice!