I want to add a Phobos module with template mixins for common idioms.

Dmitry Olshansky dmitry.olsh at gmail.com
Mon May 20 23:43:58 PDT 2013


21-May-2013 02:02, Idan Arye пишет:
> On Monday, 20 May 2013 at 19:15:34 UTC, Dmitry Olshansky wrote:

>> If you need synchronization and coordination based on what the
>> reference happens to be right now then there are tools far better fit
>> for the job - mutexes, semaphore, condition vars etc.
>
> First and foremost - this is library library code, so it should expose
> as much interface as possible without exposing or breaking the
> implementation.
>

A-ha. That's it and it's totally wrong. Exposing as much interface as 
possible is a disaster. Libraries (esp standard) take great deal of 
deliberation in picking what to expose. Exposing less is a common theme 
in interfaces. "Doing more" is a common theme in wrappers, helpers and 
has a proverbial "kitchen sink" effect.

> Personally, I think `hasInstance()` would be mainly used in the second
> use case you suggested. It would be useful if you have a long running
> loop(for example - a game loop) that needs to interact with the
> singleton instance if it exists, but can't or shouldn't instantiate it.

Message passing, queues, condition variables. Singleton pattern assumes 
you have an object with unknown initialization order and who ever 
touches it first gets to create it.

> As for the first use case, you are right - it is a bad design to
> busy-wait for a singleton to be instantiated somewhere else. I should
> probably add another method that waits for the instance using a condition.

And your are falling into a trap I decidedly put in my example - this is 
a no use case for singletons. Want to wait on smth to happen? - use 
*separate* condition var, event pump etc. Want to check on some external 
state? - same answer.

Though you might provide separate class for waitable singleton that 
incorporates
condition variable. Could be useful sometimes(?) in case there is no 
other logic
to define order of initialization.

BTW Why not just make a template Singleton!T instead of mixin?

>> The last but not least is the fact that LowLock returns TLS reference
>> to a (__g)shared instance make me worry about how the users code now
>> is full of hidden race conditions anyway. This applies to the pattern
>> as presented not only your implementation of it.
>> So the singleton itself would need some synchronization... and for
>> that it really should be marked shared. The alternative is to have a
>> per-thread singleton without any locking.
>
> There is also a thread local version called `ThreadLocalSingleton`. If I
> made a shared version, would that solve those possible hidden race
> conditions?

It would make people do something about it - shared allows only calling 
shared methods of a class and prohibits all basic operations on the 
fields. Points of race become fairly obvious - they need casts and lack 
of locks in the vicinity.

Every time I see __gshared I think "lazy, old and broken" and usually at 
least one of these is true.

> Is there a point in using the TLS Low Lock method for shared
> singletons?

Good question. Yes, it is as it will allow you to have lazy 
initialization from any thread on any multicores w/o always taking a 
lock. If you can't figure out how to make order of initialization 
deterministic (or who creates what and when) then these lazy-init 
singletons are good idea.

I personally despise singletons and the code patterns they introduce. 
IMHO lazy initialization (not to mistake with lazy loading/caching) is 
so rarely *required* that you may as well avoid it, and in D we have 
static this/shared static this.

-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list