singleton report (lifetimes)

Just thought I would release a progress report on the singleton. I have added a new lifetime policy called static_lifetime, which derives from the longevity lifetime and just hides the longevity part from client code, setting it to zero. The result: singletons using the static_lifetime policy are guaranteed to be destroyed in reverse order of creation, if they are created. I am thinking that this should be the default lifetime for the singleton, however I am open to suggestions. Here is a brief summary of each lifetime in the library. If there are any ideas for other lifetimes I would love to hear them. dependency_lifetime - Uses pointers to the singleton as reference counted dependencies. The singleton, if created, is destroyed upon the destruction of the last pointer. A static or global pointer must exist to ensure that the singleton doesn't get destroyed and recreated as the program executes. Singletons can own dependencies to other singletons to ensure proper order of creation and destruction. If a circular reference exists, the singletons owning pointers to each other will never be destroyed. This was my former choice for the default policy. longevity_lifetime - Upon first creation of a singleton using this policy, the singleton instance is registered with a hidden singleton, the longevity_registry. The longevity_registry has a static pointer to itself in its constructor, ensuring it lives at least until main exits. Upon destruction, it destroys the registered singletons in order. Singletons with lower longevities are destroyed first, and singletons with the same longevity are destroyed in reverse order of creation. static_lifetime - Deriving from the longevity_lifetime, this just hides the longevity template parameter and uses zero. As a result, singletons using this policy are destroyed in reverse order of creation, and are destroyed before any longevity based singletons using a longevity greater than one. As the longevity is an unsigned int, this means most of them. This is my current choice for a default. leaky_lifetime - This never destroys the singleton instance. Because of the extensive framework that it provides in terms of member functions and classes, all of the other lifetimes derive from it. This way the other lifetimes can add the specialized destruction behavior without duplicating all the little details, like creation behavior and member functions of the pointer class. The leaky lifetime is used internally by a hidden singleton used in the multiton implementation. This singleton stores multiton instance holders in a map (ideally this should be an assoc_vector if one is ever added to boost). It can never be destroyed because the singletons it stores instance holders to could potentially be destroyed later, or even be recreated by other singletons in the process of being destroyed. Fortunately the map only needs to be destroyed if it needs to free the memory, and this memory which will be automatically cleaned up by the OS anyway. I would like to point out that the method of creation is the same regardless of the lifetime used. An enumerated trait of each lifetime controls when automatic creation can occur. This can be set to create the singleton upon creation of a pointer, upon dereferencing a pointer, both, or neither. If this is set to not automatically create the singleton at all, client code can explicitly call a create member function from any singleton pointer. The leaky_lifetime implements all of these details so that the other lifetimes which derive from it do not have to worry about it. Phoenix re-creation ability works automatically for all of these. To achieve a non-phoenix lifetime, a one_time_creator can be specified which uses a real creator the first time, and a creator designed to fail the second time. Numerous failure creators are provided: null_creator - create simply returns null throw_creator - create throws an exception (which can optionally be specified) assert_creator - causes a boost assertion to fail, and then uses some other failure creator (defaults to throw_creator) if execution gets past the assertion The real creators provided include: create_using_new - client code can customize with a boolean trait whether to make it use no throw new create_using_malloc - client code can make this throw or no throw as well create_statically - uses a static aligned_storage buffer to hold the instance, cannot be used with a multiton create_using_std_allocator - allocates memory with a standard allocator (which can be customized) The one_time_creator can be chained to use a different creator for the first, second, and third creations, ad infinitum. It makes sure to destroy each instance with the internal creator used to create it. I am diligently working on the html documentation, which is going to be quite extensive. It seems like the more documentation I write, the more ideas I get for improving the library. When I get the documentation into a coherent state I will upload it. However, I have made so many changes now that I think an outside perspective would be a good thing before I start setting class and function names in stone. Thus, an up to date stable version has been uploaded to the sandbox. What would be really helpful is if someone could try to write a test program in a multi threaded context. My background in threading is very shaky, and I want to be sure that I am using the locking policy the right way. Is anyone willing to give this a try? -Jason
participants (1)
-
Jason Hise