Re: [boost] Is there interest in an alternative to the Singleton anti-pattern?

I look forward to your feedback on the Singularity Pattern. The unittests in Vault/Singularity/singularity_unittest.cpp are great to study first to see how Singularity is meant to be used.
I have some remarks:
1) class single_threaded - if you remove user defined destructor and constructor, it will become a POD type and compillers will do better optimizations
I completely agree. Done. Thank you.
2) singularity_state, singularity_instance and singularity classes can be combined together if you remove BOOST_PP_REPEAT(BOOST_SINGULARITY_ARGS_MAX, BOOST_PP_DEF_CLASS_TYPE_DEFAULT, _) from singularity and put this templates directly for create functions. If you do so, code like:
singularity<Horizon, single_threaded, int, Event*, Event&>::create(3, &event, event);
will look much better, just like:
singularity<Horizon, single_threaded>::create(3, &event, event);
Then, FRIEND_CLASS_SINGULARITY macro will be much shorter
You suggestion simplifies the interface by implicitly determing the types for the user, rather than requiring them to manually specify them. But in addition, by only generating create(...) overloads that pass by reference or pointer (not by value which the user could have done before), we prevent the undesirable situation where a user would pass an object by value into Singularity which would then pass by value into their constructor. Now, all arguments which are passed by value are accepted by their reference, and then passed either by value, or by reference, into the constructor, whichever is present. A class obviously cannot provide both a value, and a reference constructor for the same type, so there are no ambiguity problems. An excellent suggestion. One detail, I still require the singularity_state and singularity_instance structs, because state should not depend on the threading model, and instance should not depend on the access model (see point 5 below). The only downside is that I must generate 2^(n+1)-1 function overloads if I am to support constructors up to a maximum of n arguments. I am basically permuting receiving the typed arguments by reference or by address. I have implemented Singularity without the BOOST_PP meta generating functions for now up to three arguments. Once the design is finalized, I will once again generate the create() functions based on BOOST_SINGULARITY_ARGS_MAX. 4) May be, it would be much better to derive from singularity. Then
the code will look just like this: Horizon::create(3, &event, event); or like: Horizon< single_threaded >::create(3, &event, event);
5) It would be great, to have a get() function in singularity, that returns reference
One of the selling points of Singularity is that it did not provide global access to an instance. However, I can see situations where this would be desirable, and also providing global access will make transitioning from Singleton much easier. Therefore, I have created an additional policy argument, which has a default value of "local_access", causing get() to
I did not need to implement this suggestion, as implementing #2 also allowed this usage pattern. As such, Singularity is now usable as both a factory, or as a base class. I have unit tests and code comments demonstrating both usage patterns. This makes Singularity now far more usable, and general purpose. throw an exception. However, if you instantiate Singularity with "global_access", you can now access the instance, provided create() has already been called and destroy() has not.
It's just what I saw in a 15 minutes of review. I will make a more deep look a little bit later. Any comments are welcomed.
Best regards. Antony Polukhin
Keep the feedback coming. I was going to post updated source and both AsFactory and AsBaseClass unit tests, to the Vault, but apparently the Vault is now deprecated. You can email me at icaretaker@gmail.com if you would like to see the new code. Here is an example of the new usage pattern: // Usage as a Factory: typedef singularity<Horizon, single_threaded, local_access> HorizonSingularityType; // same as singularity<Horizon> Horizon & horizonA = HorizonSingularityType::create(3, &event, event); HorizonSingularityType::destroy(); // Usage as a Base Class: class Horizon : public singularity<Horizon, multi_threaded, global_access> Horizon & horizonB = Horizon::create(3, &event, event); Horizon::destroy(); Thank you, Ben Robinson, Ph.D.
participants (1)
-
Ben Robinson