
What is: namespace boost { const class { ??? Mike "Jason Hise" <chaos@ezequal.com> wrote in message news:42E93F43.4040204@ezequal.com...
This message is an in depth description of my current design plan for a new singleton library, which I hope to complete and schedule for review by boost in the coming year. I would appreciate any comments, questions, or suggestions regarding this plan before I begin work on the code. Specifically, I would like to know if there are any important issues that this design fails to address, or difficulties with the interface that would turn away potential users.
(My old singleton library, which was not accepted by boost, is available at http://tinyurl.com/6qvrd. It was rejected primarily because it failed to adequately address concerns related to multi threading and dlls.)
Thus far, my high level design plan looks like this:
The creator_policy defines fundamental pointer, const_pointer, and reference types. These hold references to a creator policy instance which maintains the singleton internally, so that the pointer types can always see and access the state of the single instance. This way, pointers to the singleton instance are not invalidated when the state of the singleton changes. The creator_policy defines create, replace, and destroy methods, as well as methods to generate instances of the various pointer types. Create only creates the instance if it does not already exist, destroy only destroys the instance if it does exist, and replace makes sure any existing instance is destroyed before attempting creation. Thus far, I hope to support the following creators:
--------------------------------------------------------------------------------
in_place_creator creates/destroys inside an aligned_storage POD
interface:
create ( [ctor params] ); replace ( [ctor params] ); destroy ( );
pros: no memory allocation/deallocation ever required constructor params can be easily specified
cons: automatic creation, when it occurs, always uses the default constructor singleton cannot be created as a derived type
useful for simple, user defined singleton classes
--------------------------------------------------------------------------------
source_sink_creator owns fixed source and sink functors, specified with template parameters
interface:
create ( ); replace ( ); destroy ( );
pros: source can return a derived type automatic creation uses source rather than default construction
cons: source and sink cannot be set or changed at runtime constructor arguments cannot be specified by calling code
useful for singleton types provided by untouchable code, which may require calling special functions to get pointers to instances
--------------------------------------------------------------------------------
dynamic_source_sink_creator owns dynamic source and sink functors
interface:
create ( [source[, sink]] ); replace ( [source[, sink]] ); destroy ( [source[, sink]] );
pros: source can return a derived type automatic creation uses source rather than default construction source and sink can optionally be changed at run time source and sink can change functor types when they are set (example: from function pointer to lambda expression)
cons: specifying constructor parameters to pass is non-trivial dynamic memory allocation and virtual functions must be used to store the functors in order to allow for different functor types at runtime, thus creation is more expensive and can potentially fail
useful for a singleton which needs to take the forms of unspecified derived types and is frequently destroyed and created via some type of factory
--------------------------------------------------------------------------------
The lifetime_policy owns and wraps the creator policy, and provides pointer and reference types which wrap those belonging to the creator. It also provides functions to generate instances of the various pointer types, and provides a function to access the creator_policy instance. The unmanaged lifetime simply typedefs the underlying pointer and reference types, and thus results in no overhead. The longevity_lifetime and lifo_lifetime behave similarly, but handle scheduling of automated destruction when any of the pointer generation methods are called. The dependency_lifetime will wrap the internal pointer types to perform reference counting (the reference count itself will be stored in the lifetime_policy instance). The timeout_lifetime will manage a separate thread that releases the instance when it finishes counting down. It will also wrap the internal pointer types to reset the timer when a pointer is dereferenced, and reset and lock the timer while any references exist.
The threading_policy owns and serializes access to the lifetime_policy. It also has a function to get access to the lifetime_policy instance, and provides pointer, const_pointer, and reference types which wrap and forward to the lifetime's corresponding types. For the single_threaded policy, these pointer types are simply typedefs of the lifetime's pointer types, resulting in no overhead, and the function through which the lifetime_policy instance is accessed just returns a raw pointer to it. For the multi_threaded policy, pointer types perform locking before forwarding to lifetime pointer types, and the reference type acts as a lock throughout it's existence. The mutex is stored inside the threading_policy instance. The function which returns a pointer to the lifetime_policy instance returns a smart pointer which serializes access.
A storage_policy determines how instances of the threading_policy are stored (and because these instances contain instances of the other policies, this indirectly controls how all of the policy instances are stored). static_storage stores policy instances directly as global variables, which is fine for singletons that are not required to have a specific lifetime with regard to other singletons. These global variables will be set up in such a way that it will be guaranteed that any automatic destruction takes place before the policy bundle is destroyed. group_storage allows multiple singletons to have their policies stored in a master group. No policies in this group are destroyed until all automated destruction that will be performed by any members of the group has completed. This way, if destructors of some of the singletons in this group trigger re-creation of other singletons in the same group, the policies needed to recreate the singletons are guaranteed to still exist. dll_storage requires linking with singleton.dll, and stores instances in a special exported manager singleton to ensure unique singleton instances across dll boundaries. All policy instances of this type are guaranteed to be destroyed only after all automated destruction has taken place.
A singleton class exists, which takes a singleton type and a name tag as template parameters. The name will have a default type called 'unnamed'. This name parameter enables using multiple singleton instances of the same type. Policies are traits of the name specified, so using the default name 'unnamed' results in using the default policies. Policies can be specified by declaring a name as an undefined struct, and then specializing the desired policy traits for that name.
The singleton class contains three pointer types, which wrap those of the threading policy. These are strong_pointer, lazy_pointer, and weak_pointer. strong_pointer attempts automatic creation of the singleton instance if it does not exist when the pointer is first created, and also attempts automatic creation if needed any time it is dereferenced. lazy_pointer only attempts automatic creation when dereferenced, and weak_pointer will never create the instance automatically. For the lifo_lifetime, a strong_pointer can be used to specify a dependency of some singleton B on some singleton A by having B own a strong_pointer to A. This will ensure that A is created before B and destroyed after B.
Const versions of these three pointer types will also exist. Creation, destruction, and non-const member functions will not be allowed to be called through these const pointer types. A single reference type will exist which will be the result of dereferencing any pointer type via the unary * operator. const_pointers return const qualified references. Pointers only perform temporary locking (if the threading policy supports locking) when a member function is called via the -> operator or when a create or destroy operation is invoked. References lock the singleton throughout their entire lifetime, and thus can be used to make a series of operations on the singleton instance atomic. A reference provides an implicit conversion to a raw reference of the singleton's type (which comes back const if the reference is const). Create and destroy can only be called on non-const references.
Typical code will access a singleton instance by creating one of the above pointer types and calling member functions through it via the -> operator. Ex:
singleton < MyType, SomeName >::lazy_pointer ptr; ptr->DoSomething ( );
--------------------------------------------------------------------------------
I plan to sneak an improved version of the null developed by Scott Meyers in with this code in a header called boost/null.hpp, and use it in the singleton's implementation. It will be defined as follows:
namespace boost { const class { private: void operator & ( ) const;
public: #ifndef BOOST_NO_MEMBER_TEMPLATES
// provide conversion to any pointer type template < typename Class, typename Type > operator Type Class::* ( ) const { return 0; }
template < typename Type > operator Type * ( ) const { return 0; }
#else
//provide conversion to int if member templates are not supported operator int ( ) const { return 0; }
#endif//BOOST_NO_MEMBER_TEMPLATES
} null; }
#undef NULL #define NULL (::boost::null)
--------------------------------------------------------------------------------
Any and all comments or suggestions on this plan are welcomed. Potential problems are much easier to address at design time than after the code is written.
-Jason
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost