Boost logo

Boost :

From: Jason Hise (chaos_at_[hidden])
Date: 2005-10-05 23:44:20


I am trying to decide on the best interface for the multiton to provide.

Some background:
The singleton interface consists of three smart pointer types:
singleton_ptr, const_singleton_ptr, and singleton_ref. Instances of
these always automagically refer to the singleton instance. With regard
to multi threading, when an operation is performed through a
singleton_ptr, an exclusive lock is obtained for the duration of the
operation. A const_singleton_ptr behaves similarly, but it acquired a
shared lock instead, and only const members of the singleton instance
can be accessed. A singleton_ref is considered to be a dereferenced
singleton_ptr, so it owns an exclusive lock on the instance for its
entire lifetime. It is implicitly convertible to a raw reference to
Type, and as such is ideal to use as a proxy to the instance which locks
it for the duration of a function call. Ex:

void foo ( Type & );

void bar ( )
{
    // pass the singleton to foo and simultaneously lock the operation
    foo ( singleton_ref < Type > ( ) );
}

Ideally, I would like the multiton to provide a similar interface. I
would picture doing this by providing a multiton_ptr,
const_multiton_ptr, and multiton_ref, which all take a key to the
instance as a constructor param.

Question 1) Should multiton_ptrs be copy constructible or assignable?
What about multiton_refs? Keep in mind that a multiton_ref owns a lock
directly, and thus would need to switch locks if redirected to a
different instance.

Question 2) Should the multiton_ptr and const_multiton_ptr also function
as iterators? If so, should dereferencing them result in a pointer to a
pair < const Key &, Type & >, or just a regular pointer to Type? Also,
since the container itself is not exposed, how should I provide access
to 'begin' and 'end'? Is it sufficient to provide a multiton_ptr
constructor which takes an enum, and have that enum define the values
begin and end?

Question 3) Although each singleton instance in a multiton has its own
mutex (assuming a multi threaded policy), operations which can change
the state of the multiton container itself also need to be locked with a
separate mutex. Thus far, the only operation of this nature that I can
see is when a pointer to an instance with a previously unused key is
created. However, if client code is using a multiton_ptr as an iterator
in a loop, that whole loop needs to be locked with the same mutex as
well, lest another thread incidentally create a new instance while the
loop is in progress. Should multiton_ptr provide public nested read and
write lock types to give client code this access, or should it provide
some sort of for_each algorithm instead, which does the locking
automatically?

Question 4) Should the container used by the multiton become an
additional optional policy? A regular map just won't cut it if the
multiton needs its instances to exist in shared memory.

A few more notes:

* The singleton and multiton no longer have any inheritance
requirements. Hence, even singleton_ptr < int > is valid, along with
any other type one can think of.

* An uncreatable base is provided which does use CRTP. If used,
uncreatable must also be provided with the factory to use internally.
Use of this is completely optional, and makes it completely and
absolutely impossible for client code to create singleton instances, no
matter how hard it tries to hack around it. (If there is interest in
the semantics of this, I will post a more complete description).

If anyone feels my design is partially or completely off and has better
ideas please let me know.

-Jason


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk