Review Request: Singularity

Hello, This is a request for a formal review of Singularity, for inclusion into Boost. The submission is attached as a compressed zip file, and is also publicly available for download from GitHub at https://github.com/icaretaker/Singularity. The Singularity Design Pattern allows you to restrict any class to a single instance. Unlike the infamous Singleton, Singularity gives you direct control over the lifetime of the object, does not require you to grant global access to the object, nor does it limit you to the default constructor for that object. I would like to thank the Boost community for their invaluable feedback regarding the features and implementation details of Singularity. I have compiled and run Singularity on 4 different compilers: GCC 4.5, MSVC++ 2010, the Texas Instruments CL2000 compiler targeting the 2803x processor, and the Green Hills compiler targeting the Cortex-A8 ARM processor. Thank you, Ben Robinson, Ph.D. P.S. I have also implemented Singularity in C++11 using variadic templates and rvalue references to achieve perfect function forwarding. These source files are located in the /cpp11 subdirectory, but that is not part of the submission, unless Boost is accepting C++11 libraries at this time.

On 08/22/2011 09:33 AM, Ben Robinson wrote:
I would like to thank the Boost community for their invaluable feedback regarding the features and implementation details of Singularity. I have compiled and run Singularity on 4 different compilers: GCC 4.5, MSVC++ 2010, the Texas Instruments CL2000 compiler targeting the 2803x processor, and the Green Hills compiler targeting the Cortex-A8 ARM processor.
If I could give you a few suggestions: replace calls to throw by BOOST_THROW_EXCEPTION to allow compilation with -fno-exceptions Another suggestion would be to add support for compilers that support rvalue references but not variadic templates. Apart from that I'm afraid I don't really see the point of this against struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&); public: static my_singleton& instance() { static my_singleton ins; return ins; } }; which is simple, short, fast to compile, and thread-safe.

Mathias, Thank you for you input. I will certainly use BOOST_THROW_EXCEPTION where possible. However, Singularity provides three distinct advantages over Singleton which I have briefly mentioned in this email, and gone into greater detail in the supporting documentation. Restated differently here, they are: 1) Singleton does not give you control over the lifetime of the object. Your implementation, for example, uses a static instance of the object, which is notorious when there are multiple singletons of this type which depend upon each-other. Controlling initialization and teardown order is famously difficult. Singularity does not suffer from these lifetime issues. 2) Singleton forces global access to the class through the ::instance() member. Sometimes this is what you want, other times it is not. Singularity lets you decide. 3) Singleton encapsulates construction of the object, making it more difficult (not impossible) to pass dependencies into the constructor. Singularity, as a base class, or factory wrapper, exposes all your object's constructors, making Singularity easier to use than Singleton. I hope I have better explained what Singularity brings to the table, above what is arguably, the most well known, and misused design pattern in C++. Thank you, Ben Robinson, Ph.D. On Mon, Aug 22, 2011 at 2:15 PM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> wrote:
On 08/22/2011 09:33 AM, Ben Robinson wrote:
I would like to thank the Boost community for their invaluable feedback
regarding the features and implementation details of Singularity. I have compiled and run Singularity on 4 different compilers: GCC 4.5, MSVC++ 2010, the Texas Instruments CL2000 compiler targeting the 2803x processor, and the Green Hills compiler targeting the Cortex-A8 ARM processor.
If I could give you a few suggestions:
replace calls to throw by BOOST_THROW_EXCEPTION to allow compilation with -fno-exceptions
Another suggestion would be to add support for compilers that support rvalue references but not variadic templates.
Apart from that I'm afraid I don't really see the point of this against
struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&);
public: static my_singleton& instance() { static my_singleton ins; return ins; } };
which is simple, short, fast to compile, and thread-safe.
______________________________**_________________ Unsubscribe & other changes: http://lists.boost.org/** mailman/listinfo.cgi/boost<http://lists.boost.org/mailman/listinfo.cgi/boost>

On 23/08/2011 07:05, Ben Robinson wrote:
1) Singleton does not give you control over the lifetime of the object. Your implementation, for example, uses a static instance of the object, which is notorious when there are multiple singletons of this type which depend upon each-other. Controlling initialization and teardown order is famously difficult. Singularity does not suffer from these lifetime issues.
It's a function-scope static. The object will be constructed when instance is called for the first time, which is good enough to control initialization order.
2) Singleton forces global access to the class through the ::instance() member. Sometimes this is what you want, other times it is not.
It is trivial to change it to be what you want, including calling special constructors. It's five lines and easily changed to suit whatever needs you may have, which is not the case of a library, even with a policy-based design, which is more restrictive.

On Mon, Aug 22, 2011 at 5:15 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&);
public: static my_singleton& instance() { static my_singleton ins; return ins; } };
which is simple, short, fast to compile, and thread-safe.
Thread-safe under which version of the language? Maybe C++11 (?), but otherwise depends on the compiler and/or compiler flags, I think. In particular, there is a race as to which thread is the "first" caller to instace(), and thus a race on the construction of `ins`. Tony

On 23/08/2011 08:53, Gottlob Frege wrote:
On Mon, Aug 22, 2011 at 5:15 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&);
public: static my_singleton& instance() { static my_singleton ins; return ins; } };
which is simple, short, fast to compile, and thread-safe.
Thread-safe under which version of the language?
The only one that knows about threads.

Apart from that I'm afraid I don't really see the point of this against
struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&);
public: static my_singleton& instance() { static my_singleton ins; return ins; } };
which is simple, short, fast to compile, and thread-safe.
Not thread safe on the majority of compilers surely? John.

On 23/08/2011 09:44, John Maddock wrote:
Apart from that I'm afraid I don't really see the point of this against
struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&);
public: static my_singleton& instance() { static my_singleton ins; return ins; } };
which is simple, short, fast to compile, and thread-safe.
Not thread safe on the majority of compilers surely?
Isn't MSVC the only one that doesn't do it. And MSVC11 does it, I believe.

On 23/08/2011 14:00, Mathias Gaunard wrote:
Isn't MSVC the only one that doesn't do it.
Sorry, missing "?" here.
And MSVC11 does it, I believe.
I thought I had read that somewhere, but I can't find the source anymore so maybe I'm just confusing it with something else. Hopefully it will be the case though.

[Mathias Gaunard]
which is simple, short, fast to compile, and thread-safe.
[John Maddock]
Not thread safe on the majority of compilers surely?
[Mathias Gaunard]
Isn't MSVC the only one that doesn't do it? And MSVC11 does it, I believe. I thought I had read that somewhere, but I can't find the source anymore so maybe I'm just confusing it with something else. Hopefully it will be the case though.
You're thinking of C++11 "magic statics" (my term), http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm "Dynamic Initialization and Destruction with Concurrency". Neither VC10 nor GCC 4.6 implement magic statics (see http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-feature... and http://gcc.gnu.org/gcc-4.6/cxx0x_status.html ). I've heard (but don't take my word for it) that GCC currently ensures correctness here by taking a lock, which is far less desirable than the novel magic statics algorithm. VC does not ensure correctness here. We haven't yet revealed VC11's Core Language features, except for the bugfix-level ones that I've mentioned in passing (e.g. lambdas v1.1). Stephan T. Lavavej Visual C++ Libraries Developer

On 08/23/2011 10:26 PM, Stephan T. Lavavej wrote:
[Mathias Gaunard]
which is simple, short, fast to compile, and thread-safe.
[John Maddock]
Not thread safe on the majority of compilers surely?
[Mathias Gaunard]
Isn't MSVC the only one that doesn't do it? And MSVC11 does it, I believe. I thought I had read that somewhere, but I can't find the source anymore so maybe I'm just confusing it with something else. Hopefully it will be the case though.
You're thinking of C++11 "magic statics" (my term), http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm "Dynamic Initialization and Destruction with Concurrency".
I'm just thinking of them being thread-safe. Whether it uses the crazy lockfree algorithm or not is of little relevance to me, and is more a QoI issue. They have been thread-safe in GCC at least since version 4.0. It is mandated by the Itanium C++ ABI that is followed by most compilers.

Mathias, I think this discussion is getting a little off track. There is a lot of literature on creating a thread-safe Singleton that manages the lifetime of your object according to your needs. However, there is no silver bullet for the pattern. Different variants make different tradeoffs depending on the user's needs. The three issues that are inherent to Singleton are: 1) You have little control over when the Singleton is destroyed. Should you have multiple Singleton which depend on each-other, very often you need a very specific teardown order. Singularity gives you this control directly. Singleton does not. There are also creation ordering problems as well depending on the implementation. These problems are well documented, and solutions like the Meyers Singleton and the phoenix Singleton have been developed to address it, but no solution is a silver bullet. 2) The instance() member is global, so you cannot fully encapsulate it inside the classes that need it. Singularity allows you to optionally expose global access to the class, should you desire context independent objects. 3) Singleton restricts you to a single constructor, usually the default one. Singularity allows you to use any/all of the constructors of your object. Singleton is useful. But it does it have quirks/limitations/difficulties. I am providing Singularity to directly address the weakness of Singleton, and provide a better approach for ensuring a single instance of the class. My hope is that the community will recognize that the Singularity design pattern is superior to the Singleton design pattern for many applications, and adopt its use where appropriate. Thank you, Ben Robinson, Ph.D. On Tue, Aug 23, 2011 at 2:34 PM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> wrote:
On 08/23/2011 10:26 PM, Stephan T. Lavavej wrote:
[Mathias Gaunard]
which is simple, short, fast to compile, and thread-safe.
[John Maddock]
Not thread safe on the majority of compilers surely?
[Mathias Gaunard]
Isn't MSVC the only one that doesn't do it? And MSVC11 does it, I believe. I thought I had read that somewhere, but I can't find the source anymore so maybe I'm just confusing it with something else. Hopefully it will be the case though.
You're thinking of C++11 "magic statics" (my term), http://www.open-std.org/jtc1/**sc22/wg21/docs/papers/2008/**n2660.htm<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm>"Dynamic Initialization and Destruction with Concurrency".
I'm just thinking of them being thread-safe. Whether it uses the crazy lockfree algorithm or not is of little relevance to me, and is more a QoI issue.
They have been thread-safe in GCC at least since version 4.0. It is mandated by the Itanium C++ ABI that is followed by most compilers.
______________________________**_________________ Unsubscribe & other changes: http://lists.boost.org/** mailman/listinfo.cgi/boost<http://lists.boost.org/mailman/listinfo.cgi/boost>

On 24/08/2011 04:28, Ben Robinson wrote:
Mathias,
I think this discussion is getting a little off track. There is a lot of literature on creating a thread-safe Singleton that manages the lifetime of your object according to your needs. However, there is no silver bullet for the pattern. Different variants make different tradeoffs depending on the user's needs. The three issues that are inherent to Singleton are:
1) You have little control over when the Singleton is destroyed. Should you have multiple Singleton which depend on each-other, very often you need a very specific teardown order.
It should be the inverse order of the construction order. Any system that requires to explicitly give both construction and destruction order without automatically deducing one from the other is IMO broken. function-level statics already deal with this.
2) The instance() member is global, so you cannot fully encapsulate it inside the classes that need it. Singularity allows you to optionally expose global access to the class, should you desire context independent objects.
The code is two lines of straightforward C++. You're free to encapsulate it the way you want. That's easier than dealing with the idiosyncrasies of a library.
3) Singleton restricts you to a single constructor, usually the default one. Singularity allows you to use any/all of the constructors of your object.
It restricts you to whatever you choose to write your function as.

On 24-Aug-2011, at 9:18 PM, Mathias Gaunard wrote:
On 24/08/2011 04:28, Ben Robinson wrote:
Mathias,
I think this discussion is getting a little off track. There is a lot of literature on creating a thread-safe Singleton that manages the lifetime of your object according to your needs. However, there is no silver bullet for the pattern. Different variants make different tradeoffs depending on the user's needs. The three issues that are inherent to Singleton are:
1) You have little control over when the Singleton is destroyed. Should you have multiple Singleton which depend on each-other, very often you need a very specific teardown order.
It should be the inverse order of the construction order.
Consider dependency between singletons

On 24/08/2011 15:29, Alexey Tkachenko wrote:
On 24-Aug-2011, at 9:18 PM, Mathias Gaunard wrote:
On 24/08/2011 04:28, Ben Robinson wrote:
Mathias,
I think this discussion is getting a little off track. There is a lot of literature on creating a thread-safe Singleton that manages the lifetime of your object according to your needs. However, there is no silver bullet for the pattern. Different variants make different tradeoffs depending on the user's needs. The three issues that are inherent to Singleton are:
1) You have little control over when the Singleton is destroyed. Should you have multiple Singleton which depend on each-other, very often you need a very specific teardown order.
It should be the inverse order of the construction order.
Consider dependency between singletons
Your point being? Construct your singletons in the order required by your dependency, then let destruction happen in the inverse order. function-level statics are constructed *on the first call of the function*, not in an unspecified order like class-level statics or global variables.

Mathias Gaunard wrote:
On 24/08/2011 15:29, Alexey Tkachenko wrote:
On 24-Aug-2011, at 9:18 PM, Mathias Gaunard wrote:
On 24/08/2011 04:28, Ben Robinson wrote:
1) You have little control over when the Singleton is destroyed. Should you have multiple Singleton which depend on each-other, very often you need a very specific teardown order.
It should be the inverse order of the construction order.
Consider dependency between singletons
Your point being?
Construct your singletons in the order required by your dependency, then let destruction happen in the inverse order.
function-level statics are constructed *on the first call of the function*, not in an unspecified order like class-level statics or global variables.
If an application has a logging Singleton and each of the other Singletons in that application used the logging Singleton in its destructor, but one or more of those other Singletons were created before the logging Singleton, you'd have a problem. This is the destruction order problem which leads to so many different partial solutions, such as allowing the logging Singleton to be implemented as a function local static pointer and left to leak. When you know that a particular Singleton is needed after all others, you might try to create it early, but if there are objects with static storage duration that access any of the Singletons, then you lose control over the initialization order. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2) The instance() member is global, so you cannot fully encapsulate it
inside the classes that need it. Singularity allows you to optionally expose global access to the class, should you desire context independent objects.
The code is two lines of straightforward C++. You're free to encapsulate it the way you want. That's easier than dealing with the idiosyncrasies of a library.
Creating a Singleton instance with the global instance() member and passing
the resulting object into another object for encapulation, does not encapsulate the Singleton. The instance() member is still global, and any other code, can directly access that instance. Therefore, Singleton exposes the instance at global scope, prevent true encapsulation. Sometimes global access is desirable. However, sometimes we use Singleton just to enforce the single instance, and get the global access as baggage. Instance count and accessibility should be orthogonal. Singularity allows you to enforce the single instance, and <optionally> provide global access to the instance, according to the developer's needs. Ben Robinson, Ph.D. ______________________________**_________________
Unsubscribe & other changes: http://lists.boost.org/** mailman/listinfo.cgi/boost<http://lists.boost.org/mailman/listinfo.cgi/boost>

On Aug 23, 2011, at 4:26 PM, Stephan T. Lavavej wrote:
I've heard (but don't take my word for it) that GCC currently ensures correctness here by taking a lock, which is far less desirable than the novel magic statics algorithm.
On Aug 23, 2011, at 5:34 PM, Mathias Gaunard wrote:
I'm just thinking of them being thread-safe. [...] They have been thread-safe in GCC at least since version 4.0. It is mandated by the Itanium C++ ABI that is followed by most compilers.
For what it's worth, only sort of. gcc 4.0 - 4.2 used a single global mutex in the implementation of thread-safe function scoped static variables, and held this mutex locked while executing the initializer. This can deadlock if the initializer for such a variable requires the result from a computation done by another thread, and part of that computation attempts to initialize some other function scoped static variable. [It is an error in the program if it is the same variable that needs to be initialized.] In gcc 4.3 the relevant code (__cxa_guard_acquire) was changed to (1) eliminate the use of a global lock under some configurations (have futexes), (2) avoid holding the global lock while performing the initialization under other configurations (have condition variables), (3) finally, fall back to the old pre-4.3 behavior if neither of those configurations is enabled. Yes, I learned all about this the hard way.

Apart from that I'm afraid I don't really see the point of this against
struct my_singleton { private: my_singleton() {} my_singleton(const my_singleton&);
public: static my_singleton& instance() { static my_singleton ins; return ins; } };
which is simple, short, fast to compile, and thread-safe. AFAIK the "static my_singleton ins;" is not thread-safe (at least, for
23.08.2011 1:15, Mathias Gaunard пишет: the MSVC compilers). http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx -- Best regards, Sergey Cheban

I think there are two things that require review: 1) Change in Singleton idiom (we get used to Singleton pattern); 2) Implementation of this particular library. Regards, Alexey. On 22-Aug-2011, at 3:33 PM, Ben Robinson wrote:
Hello,
This is a request for a formal review of Singularity, for inclusion into Boost. The submission is attached as a compressed zip file, and is also publicly available for download from GitHub at https://github.com/icaretaker/Singularity.
The Singularity Design Pattern allows you to restrict any class to a single instance. Unlike the infamous Singleton, Singularity gives you direct control over the lifetime of the object, does not require you to grant global access to the object, nor does it limit you to the default constructor for that object.
I would like to thank the Boost community for their invaluable feedback regarding the features and implementation details of Singularity. I have compiled and run Singularity on 4 different compilers: GCC 4.5, MSVC++ 2010, the Texas Instruments CL2000 compiler targeting the 2803x processor, and the Green Hills compiler targeting the Cortex-A8 ARM processor.
Thank you,
Ben Robinson, Ph.D.
P.S. I have also implemented Singularity in C++11 using variadic templates and rvalue references to achieve perfect function forwarding. These source files are located in the /cpp11 subdirectory, but that is not part of the submission, unless Boost is accepting C++11 libraries at this time. <icaretaker-Singularity-31482e4.zip>_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Wed, Aug 24, 2011 at 6:34 AM, Alexey Tkachenko <iskaspb@gmail.com> wrote:
I think there are two things that require review: 1) Change in Singleton idiom (we get used to Singleton pattern); 2) Implementation of this particular library.
Regards, Alexey.
Alexey,
I agree. How do we proceed formally reviewing the new idiom/design pattern? And how do we proceed formally reviewing the implementation? I suspect I may need to add a "Justification" section to the documentation, describing all the subtle issues which arise with Singleton, so it is well understood why a simpler paradigm is desirable. As a reminder, the source and documentation are available here: https://github.com/icaretaker/Singularity Thank you, Ben Robinson, Ph.D.

Hi Ben, I have received your request and will add Singularity to the review schedule. Best, Ron On Aug 22, 2011, at 12:33 AM, Ben Robinson wrote:
Hello,
This is a request for a formal review of Singularity, for inclusion into Boost. The submission is attached as a compressed zip file, and is also publicly available for download from GitHub at https://github.com/icaretaker/Singularity.
The Singularity Design Pattern allows you to restrict any class to a single instance. Unlike the infamous Singleton, Singularity gives you direct control over the lifetime of the object, does not require you to grant global access to the object, nor does it limit you to the default constructor for that object.
I would like to thank the Boost community for their invaluable feedback regarding the features and implementation details of Singularity. I have compiled and run Singularity on 4 different compilers: GCC 4.5, MSVC++ 2010, the Texas Instruments CL2000 compiler targeting the 2803x processor, and the Green Hills compiler targeting the Cortex-A8 ARM processor.
Thank you,
Ben Robinson, Ph.D.
P.S. I have also implemented Singularity in C++11 using variadic templates and rvalue references to achieve perfect function forwarding. These source files are located in the /cpp11 subdirectory, but that is not part of the submission, unless Boost is accepting C++11 libraries at this time. <icaretaker-Singularity-31482e4.zip>_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Ron, Thank you kindly. Ben Robinson, Ph.D. On Sat, Aug 27, 2011 at 11:24 AM, Ronald Garcia <rxg@cs.cmu.edu> wrote:
Hi Ben,
I have received your request and will add Singularity to the review schedule.
Best, Ron
On Aug 22, 2011, at 12:33 AM, Ben Robinson wrote:
Hello,
This is a request for a formal review of Singularity, for inclusion into Boost. The submission is attached as a compressed zip file, and is also publicly available for download from GitHub at https://github.com/icaretaker/Singularity.
The Singularity Design Pattern allows you to restrict any class to a single instance. Unlike the infamous Singleton, Singularity gives you direct control over the lifetime of the object, does not require you to grant global access to the object, nor does it limit you to the default constructor for that object.
I would like to thank the Boost community for their invaluable feedback regarding the features and implementation details of Singularity. I have compiled and run Singularity on 4 different compilers: GCC 4.5, MSVC++ 2010, the Texas Instruments CL2000 compiler targeting the 2803x processor, and the Green Hills compiler targeting the Cortex-A8 ARM processor.
Thank you,
Ben Robinson, Ph.D.
P.S. I have also implemented Singularity in C++11 using variadic templates and rvalue references to achieve perfect function forwarding. These source files are located in the /cpp11 subdirectory, but that is not part of the submission, unless Boost is accepting C++11 libraries at this time.
<icaretaker-Singularity-31482e4.zip>_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (10)
-
Alexey Tkachenko
-
Ben Robinson
-
Gottlob Frege
-
John Maddock
-
Kim Barrett
-
Mathias Gaunard
-
Ronald Garcia
-
Sergey Cheban
-
Stephan T. Lavavej
-
Stewart, Robert