[Formal review] Singleton library

The formal review of Singleton library written by Jason Hise starts today, May 5th, and lasts 10 days. The library is available at http://boost-sandbox.sourceforge.net/vault/index.php?&direction=0&order=&directory=Singleton The singleton documentation can be browsed online at http://www.ezequal.com/chaos/docs/html/singleton/ Singleton is feature rich library: - ensuring single instance of a class and global access point to this instance - with policies specifying: - when the instance gets created (manually, immediatelly, when first used, ...) - how is the instance created (by new, malloc, in static memory, ...) - when the instance gets destroyed (never, by priority, after another singleton, ...) Parametrized singleton called Multiton is provided City::pointer p1("Chicago"); City::pointer p2("Brussels"); will create two different "singletons" of the same type. Another feature is ability to register resources (like shared pointer) who will get destroyed in controlled order, when the application exits. Not yet implemented features are: - MT safety - self-destroying singleton with timeout - bjam compatible tests The library is known to work with several newer compilers, VC7.1 among them. Help with other compilers is welcomed. When submitting reviews, please state explicitly whether or not you believe that the library should be accepted into Boost. For more information on the Boost formal review process, please see http://www.boost.org/more/formal_review_process.htm. /Pavel

* What is your evaluation of the design? Excellent. Certainly the best Singleton library I've seen. The ability to change the memory model (dynamic/static) easily is an especially nice feature. * What is your evaluation of the implementation? I didn't have a deep look. * What is your evaluation of the documentation? Good. * What is your evaluation of the potential usefulness of the library? As we've all used singletons before, this is potentially very useful. However, I cannot see any wide-spread use for the multiton library. While an interesting idea, the mutiton would be better implemented as a map<string,object> for runtime or just shared variables at compile-time. These options are more flexible from the get-go. * Did you try to use the library? With what compiler? Did you have any problems? Nope, didn't try it. * How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? I did an In-depth study of the documentation and interfaces. * Are you knowledgeable about the problem domain? Yes, for several large code-bases I architect, singletons are integral to the design. * Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion. I do think it should be accepted, but without the multiton part. David J. Sankel

"David Sankel" wrote: Thanks for your review, first.
However, I cannot see any wide-spread use for the multiton library. While an interesting idea, the mutiton would be better implemented as a map<string,object> for runtime or just shared variables at compile-time. These options are more flexible from the get-go.
Purpose of multiton is to hide such infrastructure from the user. Above mentioned techniques are still available for specific needs. /Pavel

David Sankel wrote:
* What is your evaluation of the design?
Excellent. Certainly the best Singleton library I've seen. The ability to change the memory model (dynamic/static) easily is an especially nice feature.
Thank you :)
As we've all used singletons before, this is potentially very useful. However, I cannot see any wide-spread use for the multiton library. While an interesting idea, the mutiton would be better implemented as a map<string,object> for runtime or just shared variables at compile-time. These options are more flexible from the get-go.
I actually tend to agree. IMO, a singleton should exist to provide access to and manage the lifetime of some global resource, but should not be a global resource itself. If the resource being managed is instead a member variable, client code can much more easily add a new managed instances if the need becomes apparent. It can do so by either by adding another resource instance to the existing singleton and providing an accessor function for it, or by deriving a new singleton from the existing one and applying CRTP to the base. // the following code creates two distinct singletons which manage separate resources template < typename Derived > class Base : basic_singleton < Derived > { private: Resource r; public: Resource & get_res ( ) { return r; } }; typedef Base < Base > SingletonBase; class DerivedA : public Base < DerivedA > { }; int main ( ) { // these are the two managed resources Resource & res1 = SingletonBase::pointer ( )->get_res ( ); Resource & res2 = DerivedA::pointer ( )->get_res ( ); return 0; } The multiton might prove useful in situations when the programmer makes the mistake of not separating the concerns of resource management and resource functionality, and wants to quickly introduce another singleton instance. However, it is probably not a good long term solution, as a single typo in the key (I'm assuming a string is used for the multiton key) could lead to difficult-to-debug runtime errors. Specifically, a new singleton instance would be created which would be completely unrelated to the singleton that client code was intending to access. Of course, if anyone is currently finding the multiton useful I'd like to hear from you. -Jason

Pavel Vozenilek wrote:
The library is known to work with several newer compilers, VC7.1 among them. Help with other compilers is welcomed.
I've tried it with bcc32 5.6.4 and just #include <boost/singleton.hpp> leads to these errors. If anyone has any ideas on this then I'd be happy to try them out. Cheers Russell [C++ Error] dependency_lifetime.hpp(119): E2402 Illegal base class type: formal type 'leaky_lifetime_ex<CreationFlags,Creator,Lock>::lifetime<Type>' resolves to 'leaky_lifetime_ex<1,create_using_new,unlocked>::lifetime<Type>' [C++ Error] dependency_lifetime.hpp(61): E2402 Illegal base class type: formal type 'typename leaky_lifetime_ex<CreationFlags,Creator,Lock>::lifetime<Type>::pointer' resolves to 'typename leaky_lifetime_ex<1,create_using_new,unlocked>::lifetime<Type>::pointer' [C++ Error] longevity_registry.hpp(45): E2029 'singleton_ex<longevity_registry,dependency_lifetime>' must be a previously defined class or struct [C++ Error] longevity_registry.hpp(80): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(80): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::creation_index' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::creation_index' is not accessible [C++ Error] longevity_registry.hpp(66): E2288 Pointer to structure required on left side of -> or ->*

"Russell Hind" wrote:
The library is known to work with several newer compilers, VC7.1 among them. Help with other compilers is welcomed.
I've tried it with bcc32 5.6.4 and just #include <boost/singleton.hpp> leads to these errors. If anyone has any ideas on this then I'd be happy to try them out.
I didn't try the BCB port yet (lack of time) but I plan to do so. /Pavel

Russell Hind wrote:
Pavel Vozenilek wrote:
The library is known to work with several newer compilers, VC7.1 among them. Help with other compilers is welcomed.
I've tried it with bcc32 5.6.4 and just #include <boost/singleton.hpp> leads to these errors. If anyone has any ideas on this then I'd be happy to try them out.
Cheers
Russell
[C++ Error] dependency_lifetime.hpp(119): E2402 Illegal base class type: formal type 'leaky_lifetime_ex<CreationFlags,Creator,Lock>::lifetime<Type>' resolves to 'leaky_lifetime_ex<1,create_using_new,unlocked>::lifetime<Type>' [C++ Error] dependency_lifetime.hpp(61): E2402 Illegal base class type: formal type 'typename leaky_lifetime_ex<CreationFlags,Creator,Lock>::lifetime<Type>::pointer' resolves to 'typename leaky_lifetime_ex<1,create_using_new,unlocked>::lifetime<Type>::pointer' [C++ Error] longevity_registry.hpp(45): E2029 'singleton_ex<longevity_registry,dependency_lifetime>' must be a previously defined class or struct
The previous line makes me worry that CRTP will not work on your compiler. CRTP is a major foundation for the library, so if it doesn't work it may not be possible to find a work around. Does the following compile? template < typename Type > struct Base { Type * ptr; }; struct Derived : public Base < Derived > { };
[C++ Error] longevity_registry.hpp(80): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(80): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::longevity' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::creation_index' is not accessible [C++ Error] longevity_registry.hpp(81): E2247 'longevity_registry::node::creation_index' is not accessible [C++ Error] longevity_registry.hpp(66): E2288 Pointer to structure required on left side of -> or ->*
These might be the result of some compiler problem with friends inside templated classes. See if this compiles: template < typename Type > class Outer { private: typedef Type some_type; class Inner { typename Outer < Type >::some_type inner; } inner; friend class Inner; }; int main ( ) { Outer < int > test; return 0; } -Jason

Jason Hise wrote:
The previous line makes me worry that CRTP will not work on your compiler. CRTP is a major foundation for the library, so if it doesn't work it may not be possible to find a work around. Does the following compile?
For the most part, Borland can handle CRTP. For example, the iterator library uses CRTP and works, for the most part, on Borland. Borland is very fussy, though, so you shouldn't be surprised if the library doesn't work out of the box. Jonathan

Jason Hise wrote:
The previous line makes me worry that CRTP will not work on your compiler. CRTP is a major foundation for the library, so if it doesn't work it may not be possible to find a work around. Does the following compile?
template < typename Type > struct Base { Type * ptr; };
struct Derived : public Base < Derived > { };
Yes, this compiles fine.
These might be the result of some compiler problem with friends inside templated classes. See if this compiles:
template < typename Type > class Outer { private: typedef Type some_type;
class Inner { typename Outer < Type >::some_type inner; } inner;
friend class Inner; };
int main ( ) { Outer < int > test; return 0; }
This also compiles fine. Thanks Russell

I'm curious as to how singleton behaves with respect to shared libraries. Is this tested? I'd imagine the results are platform-dependent.

Neal Becker wrote:
I'm curious as to how singleton behaves with respect to shared libraries. Is this tested? I'd imagine the results are platform-dependent.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I'm still looking for testers in that department. :) I suspect it depends on whether static variables are destroyed before or after shared libraries are unloaded. -Jason

On 5/5/05, Neal Becker <ndbecker2@gmail.com> wrote:
I'm curious as to how singleton behaves with respect to shared libraries. Is this tested? I'd imagine the results are platform-dependent.
I've tested Singleton library for various aspects, including this. On my test platform (windows, VC7.1) the singleton in shared libraries (dlls) does not work as expected. I've made the following test: I've create two shared libraries and a test program. The first shared library (my_manager.dll) contained the singleton class itself The second (other_lib.dll) contained a class that uses the singleton (from my_manager.dll) The test program was linked with both libraries and also uses the singleton (from my_manager.dll) and test class from other_lib.dll The test shown that the singleton actually creates _twise_ once from test program, and once from other_lib.dll, therefor resulting two independent instances, instead of one instance shared for entire process. I was a very disappointed with those results. I liked a Singleton library design very much, but this aspect makes it nearly useless for my work, because our typically application are split across multiple shared libraries, where many of the have to access some shared resource. Our current implementation is very simplistic (GOF-style), but it least it works across multiple shared libraries. Hope there is a way to work around this problem. -- Best regards, Zigmar P.S. Have anyone done such tests with *nix shared libraries? They are very much different from windows dlls, so I'm curious how does it behaves there...

Pavel Antokolsky aka Zigmar wrote:
On 5/5/05, Neal Becker <ndbecker2@gmail.com> wrote:
I'm curious as to how singleton behaves with respect to shared libraries. Is this tested? I'd imagine the results are platform-dependent.
I've tested on linux/gcc using shared libs with dynamic linking. It seems OK. I have not tested runtime link using dlopen. The test is attached

"Pavel Antokolsky aka Zigmar" wrote:
I've tested Singleton library for various aspects, including this. On my test platform (windows, VC7.1) the singleton in shared libraries (dlls) does not work as expected.
Win32 DLLs would need some support - Windows does not resolve statics when a DLL is loaded. Either explicit registering of Singleton infrastructure from each DLL would be needed or perhaps using shared segment. Considering DLLs is next phase of the development, AFAIK. I am quite suprised it works under Linux. /Pavel

On 5/6/05, Pavel Vozenilek <pavel_vozenilek@hotmail.com> wrote:
Win32 DLLs would need some support - Windows does not resolve statics when a DLL is loaded.
Either explicit registering of Singleton infrastructure from each DLL would be needed or perhaps using shared segment.
AFAIK there is no platform independent way to deal with shared memory, if that what you mean. Regarding the problem, I was thinking of some kind of way to specify the storage type manually. For example something like in this fictional example: --- my_singleton.h class my_singleton : public boost::singleton_ex< my_singleton, static_lifetime, manual_storage > { //... }; --- my_singleton.cpp my_singleton::storage_type storage; I'm not proposing such interface, but the idea is to allow to used to leave the storage object inside the Singleton uninitialized, and allow him to create it manually where he wants to (i.e. in shared memory or inside implementation file). -- Best regards, Zigmar

Pavel Antokolsky aka Zigmar wrote:
On 5/6/05, Pavel Vozenilek <pavel_vozenilek@hotmail.com> wrote:
Win32 DLLs would need some support - Windows does not resolve statics when a DLL is loaded.
Either explicit registering of Singleton infrastructure from each DLL would be needed or perhaps using shared segment.
AFAIK there is no platform independent way to deal with shared memory, if that what you mean. Regarding the problem, I was thinking of some kind of way to specify the storage type manually.
For example something like in this fictional example: --- my_singleton.h class my_singleton : public boost::singleton_ex< my_singleton, static_lifetime, manual_storage > { //... }; --- my_singleton.cpp my_singleton::storage_type storage;
I'm not proposing such interface, but the idea is to allow to used to leave the storage object inside the Singleton uninitialized, and allow him to create it manually where he wants to (i.e. in shared memory or inside implementation file).
Actually, something like this already exists. class MySingleton : public singleton_ex < MySingleton, lifo_lifetime_ex < default_creation, create_using_std_allocator_ex < false, // throw if memory can't be allocated some_shared_memory_allocator < MySingleton > > > > { }; You would have to provide some_shared_memory_allocator, which would take the form of a standard allocator policy. -Jason

"Jason Hise" wrote:
Actually, something like this already exists.
class MySingleton : public singleton_ex < MySingleton, lifo_lifetime_ex < default_creation, create_using_std_allocator_ex < false, // throw if memory can't be allocated some_shared_memory_allocator < MySingleton > > >
{ };
You would have to provide some_shared_memory_allocator, which would take the form of a standard allocator policy.
The problem is about inability of Windows to "merge" static data from different DLLs into one place. This results in more than one lifetime_priority queue in single application, frex. /Pavel

The problem is about inability of Windows to "merge" static data from different DLLs into one place.
This results in more than one lifetime_priority queue in single application, frex. I'm not sure that shared memory is a right approach. Shared memory is usually used to share the part of memory between several different
On 5/6/05, Pavel Vozenilek <pavel_vozenilek@hotmail.com> wrote: processes, not the same process. Therefor shared memory are something that is OS-wide and using it to share something inside single process is a bit overkill, besides, it can possible to run into several troubles, for example, you have to ensure there is not collisions between different processes and shared memory ids. Personally, I more like the idea of giving the user some way to specify an allocator for Singleton library's managing facilities (lifetime_priority?). Some kind of create_using_std_allocator_ex, but not for single singleton, but for library manager. -- Best regards, Zigmar

Pavel Antokolsky aka Zigmar wrote:
On 5/6/05, Pavel Vozenilek <pavel_vozenilek@hotmail.com> wrote:
The problem is about inability of Windows to "merge" static data from different DLLs into one place.
This results in more than one lifetime_priority queue in single application, frex.
I'm not sure that shared memory is a right approach. Shared memory is usually used to share the part of memory between several different processes, not the same process. Therefor shared memory are something that is OS-wide and using it to share something inside single process is a bit overkill, besides, it can possible to run into several troubles, for example, you have to ensure there is not collisions between different processes and shared memory ids.
Personally, I more like the idea of giving the user some way to specify an allocator for Singleton library's managing facilities (lifetime_priority?). Some kind of create_using_std_allocator_ex, but not for single singleton, but for library manager.
What if I were to move the implementation details that require being only defined once to source files, and by default have those source files included by the headers. Then if some macro is specified, I could omit these inclusions and instead link to a separate dll that is a build of these files. Would this solve the problem? -Jason

On 5/7/05, Jason Hise <chaos@ezequal.com> wrote:
What if I were to move the implementation details that require being only defined once to source files, and by default have those source files included by the headers. Then if some macro is specified, I could omit these inclusions and instead link to a separate dll that is a build of these files. Would this solve the problem?
I think it would solve the problem on windows. Although it must be stated clear enough in documentation, otherwise the user may run into a very unpleasant problems when porting from *nix where it worked with header-only implementation to windows - the code will compile and run, but not behave as expected - he will get multiple instances of singletons. Maybe even dll implementation should be even default on Windows - till user have not configured it differently. -- Best regards, Zigmar

Pavel Antokolsky aka Zigmar wrote:
On 5/7/05, Jason Hise <chaos@ezequal.com> wrote:
What if I were to move the implementation details that require being only defined once to source files, and by default have those source files included by the headers. Then if some macro is specified, I could omit these inclusions and instead link to a separate dll that is a build of these files. Would this solve the problem?
I think it would solve the problem on windows. Although it must be stated clear enough in documentation, otherwise the user may run into a very unpleasant problems when porting from *nix where it worked with header-only implementation to windows - the code will compile and run, but not behave as expected - he will get multiple instances of singletons. Maybe even dll implementation should be even default on Windows - till user have not configured it differently.
OK, I will add this to the singleton to-do list. BTW, which macro should I check to see if the target operating system is windows? -Jason

Pavel Vozenilek wrote:
"Jason Hise" wrote:
OK, I will add this to the singleton to-do list. BTW, which macro should I check to see if the target operating system is windows?
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) Really all of them.
That's why BOOST_WINDOWS was created. Just #include boost/config.h and it'll be available to you. boost/config.hpp: #include <boost/config/select_platform_config.hpp> #ifdef BOOST_PLATFORM_CONFIG # include BOOST_PLATFORM_CONFIG #endif boost/config/select_platform_config.hpp: #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) // win32: # define BOOST_PLATFORM_CONFIG "boost/config/platform/win32.hpp" boost/config/platform/win32.hpp: #define BOOST_WINDOWS 1 Rgds, Angus

The problem is about inability of Windows to "merge" static data from different DLLs into one place.
What if I were to move the implementation details that require being only defined once to source files, and by default have those source files included by the headers. Then if some macro is specified, I could omit these inclusions and instead link to a separate dll that is a build of these files. Would this solve the problem?
Hi Jason and everybody. There is a scenario which I think is not solved by this approach, but on the other hand may be not solvable a all (I'm pessimistic today...) Consider a singleton inside a *static* Windows library, which is linked into a dynamic library, *and* into an executable, which also links with the DLL. Something like this: lib (contains a singleton) | \ | \ | dll | / | / exe Now the singleton appears twice, once in the DLL's memory, and once in the exe's memory. This is something I found when writing my own singleton library (like most of us ;-) ). At first I noticed that singletons in a DLL are created twice, so I created a .cpp file and used dllexport/dllimport (just like the solution mentioned in this thread) to insure one instantiation. This worked for the simple DLL case, but not the more complex case I described above. I haven't been able to find any workaround (except for being really careful not to create such situations), and I really hope you can... Actually, I didn't have any time to look at your library (very unfortunate), but it looks like it will probably suffer from the same problem as my own library. I hope I'm wrong... but it worth a check. Hopefully Boost will soon have a singleton library, Yuval

"Pavel Antokolsky aka Zigmar" wrote:
Either explicit registering of Singleton infrastructure from each DLL would be needed or perhaps using shared segment.
AFAIK there is no platform independent way to deal with shared memory, if that what you mean. Regarding the problem, I was thinking of some kind of way to specify the storage type manually.
A library named Shmem is being developed (quite mature, can be found in sandbox). With this or similar library one could allocate small, uniquely named memory block and singleton infrastructures from each DLLs would (behind the curtain) use it. Then there would be no need for separate Win32 interface. /Pavel

Pavel Vozenilek wrote:
A library named Shmem is being developed (quite mature, can be found in sandbox).
With this or similar library one could allocate small, uniquely named memory block and singleton infrastructures from each DLLs would (behind the curtain) use it.
Then there would be no need for separate Win32 interface.
I agree that shared memory is one way to solve this. Note however that this is a problem that is specific to DLLs on windows -- where the meaning of C++ writeable static variables is broken. This is AFAIK not an issue with any other dynamic libraries like .so files in unix/linux. It is important to limit the workaround to the windows environment. I have experienced problems with side-effects of this type of shared memory solution for singelton, where the negative side effect was on Solaris. I.e. they had used the workaround for this windows DLL "bug" in portable code for all platforms. Needless to say, this was very annoying since it was completely unnessesary. In addition it affected the stability of our clients code, I was not happy :-( So if this is the way you plan to fix the problen, make it a conditional compile for windows. By the way, a more general solution to win32 DLL writable static variables problem may be a nice little thing to add to Boost. It would be something that looks as much as possible like a static variable, and expand to it om all platforms except win32. I really dont like the smell of it, but it may be usefull if you have to write portable code. A real solution would be to stop using compiler/platform/tool combinations with this sort of problem; unless it is fixed (dream on). To me it is as simple as to say: the C++ programming language is not supported with DLLs on windows :-(. Windows DLLs a whole set of rules you need to follow to get the bennifits they do provide, some of these does not play well with efforts to create good portable C++ code. ------ regards, Bjørn Roald

Bjørn Roald <bjorn@4roald.org> writes:
Pavel Vozenilek wrote:
A library named Shmem is being developed (quite mature, can be found in sandbox).
With this or similar library one could allocate small, uniquely named memory block and singleton infrastructures from each DLLs would (behind the curtain) use it.
Then there would be no need for separate Win32 interface.
I agree that shared memory is one way to solve this. Note however that this is a problem that is specific to DLLs on windows -- where the meaning of C++ writeable static variables is broken. This is AFAIK not an issue with any other dynamic libraries like .so files in unix/linux. It is important to limit the workaround to the windows environment.
If you are referring to the fact that static variables with the same name can be allocated in multiple DLLs, so that you see different values from each DLL, your information is incorrect and I disagree with your characterization of it as "broken". GCC now supports restricting symbol visibility for ELF platforms. See http://www.nedprod.com/programs/gccvisibility.html As I see it, this model (essentially the Windows model) is actually much less broken than the usual one on Unix where everything forms a big "symbol soup." -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams vrote:
Bjørn Roald <bjorn@4roald.org> writes:
Pavel Vozenilek wrote:
A library named Shmem is being developed (quite mature, can be found in sandbox).
With this or similar library one could allocate small, uniquely named memory block and singleton infrastructures from each DLLs would (behind the curtain) use it.
Then there would be no need for separate Win32 interface.
I agree that shared memory is one way to solve this. Note however that this is a problem that is specific to DLLs on windows -- where the meaning of C++ writeable static variables is broken. This is AFAIK not an issue with any other dynamic libraries like .so files in unix/linux. It is important to limit the workaround to the windows environment.
If you are referring to the fact that static variables with the same name can be allocated in multiple DLLs, so that you see different values from each DLL, your information is incorrect and I disagree with your characterization of it as "broken". GCC now supports restricting symbol visibility for ELF platforms. See
http://www.nedprod.com/programs/gccvisibility.html
As I see it, this model (essentially the Windows model) is actually much less broken than the usual one on Unix where everything forms a big "symbol soup."
You left out the portion of my post where I mentioned that Windows DLLs have benefits, I certainly agree that their ability to provide much better encapsulation than other models is great. That is not what I think is broken. Your information about GCC was new to me and interresting, I will study it in detail when I get more time. Thanks :) The problem I refer to, which I think is the relevant problem for this thread is that static variables are instanciated by the DLL loader or whatever, in a manner where there becomes more than one instance of the same static variable in the same process. This is not consistent with my understanding of the C++ language. If these static variables are constants or initialized consistently and treated as constants, this never becomes a real problem. I however they are writable and are writen to you end up with with more than one value for the same static variable in the same program. In my view this is broken. It has been some years since I did heavy work with Windows, the tools I used was MSVC++ 5.0 + Dincumware's sepearate standard library (not the one bunndled by MS in those days). Dinkumware provided standard libraries that fixed these issues and others providing DLL compliance, something MS never informed their customers that the bundeled versions where not designed to do. If I remember right, the static writable issue was the hardest nut to crack even for Dinkumware gurus. I think this should be fixed since it makes programming more dificult than needed. I know there may be a defendable position taken to argue that this is not broken, since the C++ standard does not say much about what a program is. In addition MS defines something they call context (if I remember right). You can explicitly switch between the context of one DLL to the context of another, thus controlling which static variable instance you are working on. So a DLL based program probably only have only one instance of a static variable per context. This may AFAIK be suficient to claim C++ compliancy. But I considder this to be something almost none of the C++ developers I have ever met is aware of. So if it holds water, I am not realy interested -- I still cosidder it broken. For the singelton library, it may be possible to always switch context to the DLL owning the singelton before the static variable is accessed. I have not had time to study the libray code yet, so I do not know how hard this may be to get right. If this is done properly, use of shared memory may not be needed. ---- regards Bjørn Roald

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Pavel Antokolsky aka Zigmar Sent: Friday, May 06, 2005 7:48 AM To: boost@lists.boost.org Subject: Re: [boost] Re: [Formal review] Singleton library
On 5/5/05, Neal Becker <ndbecker2@gmail.com> wrote:
I'm curious as to how singleton behaves with respect to shared libraries. Is this tested? I'd imagine the results are platform-dependent.
I've tested Singleton library for various aspects, including this. On my test platform (windows, VC7.1) the singleton in shared libraries (dlls) does not work as expected.
I've made the following test: I've create two shared libraries and a test program. The first shared library (my_manager.dll) contained the singleton class itself The second (other_lib.dll) contained a class that uses the singleton (from my_manager.dll) The test program was linked with both libraries and also uses the singleton (from my_manager.dll) and test class from other_lib.dll
The test shown that the singleton actually creates _twise_ once from test program, and once from other_lib.dll, therefor resulting two independent instances, instead of one instance shared for entire process.
I was a very disappointed with those results. I liked a Singleton library design very much, but this aspect makes it nearly useless for my work, because our typically application are split across multiple shared libraries, where many of the have to access some shared resource. Our current implementation is very simplistic (GOF-style), but it least it works across multiple shared libraries.
Hope there is a way to work around this problem.
__declspec(dllexport)/__declspec(dllimport) needs to be specified in order that the variable can be exported from the DLL it is defined in and imported in client DLL's & EXE's. This will give you a per-process singleton, if you want a singleton instance shared by *all* clients of the DLL of which it is defined use #pragma data_seg(".SHARED").

__declspec(dllexport)/__declspec(dllimport) needs to be specified in order that the variable can be exported from the DLL it is defined in and imported in client DLL's & EXE's. This will give you a per-process singleton, if you want a singleton instance shared by *all* clients of the DLL of which it is defined use #pragma data_seg(".SHARED"). Thanks. I already familiar with windows dlls (unfortunately?). I've made all those things you have mentioned (besides "shared") (I can sent you a source code, if you are interested). The problem is, that
On 5/8/05, Terence Wilson <tez@latte.com> wrote: the Singleton library is header-only library, and stores singleton manager(s) in static function variable(s). And when those code inlined into several different dlls,it results independent static variables in different modules (although is same code), which, in its turn, results multiple singleton instances. -- Best regards, Zigmar

I don't vote because I have not (yet) looked at the library itself, but from the review replies so far I'd like to moot that it may be too early to include a singleton library which: - is not MT safe - is not tested with shared libraries - seems not to be tested with many compilers(...several newer compilers...) Regards, Pavel Vozenilek schrieb:
The formal review of Singleton library written by Jason Hise starts today, May 5th, and lasts 10 days.
The library is available at http://boost-sandbox.sourceforge.net/vault/index.php?&direction=0&order=&directory=Singleton
The singleton documentation can be browsed online at http://www.ezequal.com/chaos/docs/html/singleton/
Singleton is feature rich library:
- ensuring single instance of a class and global access point to this instance
- with policies specifying:
- when the instance gets created (manually, immediatelly, when first used, ...)
- how is the instance created (by new, malloc, in static memory, ...)
- when the instance gets destroyed (never, by priority, after another singleton, ...)
Parametrized singleton called Multiton is provided
City::pointer p1("Chicago"); City::pointer p2("Brussels");
will create two different "singletons" of the same type.
Another feature is ability to register resources (like shared pointer) who will get destroyed in controlled order, when the application exits.
Not yet implemented features are: - MT safety - self-destroying singleton with timeout - bjam compatible tests
The library is known to work with several newer compilers, VC7.1 among them. Help with other compilers is welcomed.
When submitting reviews, please state explicitly whether or not you believe that the library should be accepted into Boost.
For more information on the Boost formal review process, please see http://www.boost.org/more/formal_review_process.htm.
/Pavel
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Stefan Strasser

Stefan Strasser wrote:
I don't vote because I have not (yet) looked at the library itself, but from the review replies so far I'd like to moot that it may be too early to include a singleton library which:
- is not MT safe - is not tested with shared libraries - seems not to be tested with many compilers(...several newer compilers...)
The third point is no big deal. A lot of porting often occurs after acceptance. I agree that MT support is crucial, and that shared library support is very important, if i is possible. Rather than reject the library because these problems haven't been addressed, let's try to address them during the review. Jonathan

Gennadiy Rozental wrote:
important, if i is possible. Rather than reject the library because these problems haven't been addressed, let's try to address them during the review.
That's unacceptable IMO. Review period is not a time to address any issues.
Why not let reviewers try? No one is forced to write a review. If these issues can't be resolved, and the review manager -- informed by the opinions of reviews -- concludes they are show-stoppers, the library will be rejected. Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:d5dngv$3dj$1@sea.gmane.org...
Gennadiy Rozental wrote:
important, if i is possible. Rather than reject the library because these problems haven't been addressed, let's try to address them during the review.
That's unacceptable IMO. Review period is not a time to address any issues.
Why not let reviewers try? No one is forced to write a review. If these issues can't be resolved, and the review manager -- informed by the opinions of reviews -- concludes they are show-stoppers, the library will be rejected.
Jonathan
Because review period is quite short and it's very easy to came up with quick solution which wouldn't work in a long run. If issues couldn't be resolved then it's obvious that submission should be rejected. Gennadiy

Gennadiy Rozental wrote:
"Jonathan Turkanis" wrote :
Gennadiy Rozental wrote:
That's unacceptable IMO. Review period is not a time to address any issues.
Why not let reviewers try? No one is forced to write a review. If these issues can't be resolved, and the review manager -- informed by the opinions of reviews -- concludes they are show-stoppers, the library will be rejected.
Jonathan
Because review period is quite short and it's very easy to came up with quick solution which wouldn't work in a long run. If issues couldn't be resolved then it's obvious that submission should be rejected.
We have to be able to trust reviewers to judge what will work in the long run. Ideally, a library will have been widely used for a considerable period before review. Often that's not the case, however, and reviewers must judge the library by its specification and implementation without the benefit of experience. If a reviewer can propose a way to handle shared libraries, e.g., which stands up to the scrutiny of other reviewers and to the sort of experimentation that's possible during a review period, the proposal could still receive as much scrutiny as several Boost libraries prior to acceptence.
Gennadiy
Jonathan

Jonathan Turkanis wrote:
Stefan Strasser wrote:
I don't vote because I have not (yet) looked at the library itself, but from the review replies so far I'd like to moot that it may be too early to include a singleton library which:
- is not MT safe - is not tested with shared libraries - seems not to be tested with many compilers(...several newer compilers...)
The third point is no big deal. A lot of porting often occurs after acceptance.
I agree that MT support is crucial, and that shared library support is very important, if i is possible. Rather than reject the library because these problems haven't been addressed, let's try to address them during the review.
Jonathan
I don't think its fair to say that it is not MT safe... the MT aspects just have not yet been extensively tested. There is a lock policy in place, which is intended to lock the singleton in the lock's constructor, and release the lock in the lock's destructor. A lock is used during creation, destruction, and access of any of the singleton's members via a proxy pointer. The only thing missing is a lock class that actually performs the locking, and I am under the impression that Boost.Threads probably provides something matching this description. -Jason

Jason Hise wrote:
Jonathan Turkanis wrote:
Stefan Strasser wrote:
- is not MT safe
I agree that MT support is crucial, and that shared library support is very important, if i is possible. Rather than reject the library because these problems haven't been addressed, let's try to address them during the review.
Jonathan
I don't think its fair to say that it is not MT safe... the MT aspects just have not yet been extensively tested.
There is a lock policy in place, which is intended to lock the singleton in the lock's constructor, and release the lock in the lock's destructor. A lock is used during creation, destruction, and access of any of the singleton's members via a proxy pointer. The only thing missing is a lock class that actually performs the locking, and I am under the impression
Okay, I haven't looked at it yet. I was basing my statement on the review announcement which says that thread safety is not yet implemented. that
Boost.Threads probably provides something matching this description.
It only takes a few minutes to figure out how to use Boost.Threads. I suggest you implement and test a lock policy using Boost.Threads and make it available to reviewers.
-Jason
Jonathan

Jonathan Turkanis wrote:
It only takes a few minutes to figure out how to use Boost.Threads. I suggest you implement and test a lock policy using Boost.Threads and make it available to reviewers.
Alright, I have completed a sample program, which is attached. The example has been added to the download package as well. Hopefully this alleviates some concerns. Tom Brinkman wrote:
Was the "singleton" library tested on GCC. I'm getting many compiler errors on 3.34.
The newly uploaded package should fix most of those errors, please let me know if any still need to be corrected. -Jason #include <iostream> #include <boost/singleton.hpp> #include <boost/thread/recursive_mutex.hpp> #include <boost/thread/thread.hpp> using namespace boost; using namespace boost::singleton; // singleton to hold the mutex class mutex_holder : public basic_singleton < mutex_holder > { private: // make sure singleton is created before main // (assumes no secondary threads are created until main) static mutex_holder self; // the mutex to lock (must be recursive with // current singleton implementation) recursive_mutex mutex_; public: recursive_mutex & get_mutex ( ) { return mutex_; } }; // our custom locking policy class shared_singleton_lock : recursive_mutex::scoped_lock { public: shared_singleton_lock ( ) : recursive_mutex::scoped_lock ( mutex_holder::pointer ( )->get_mutex ( ) ) { } // the following are needed because locks need to be able to be copied shared_singleton_lock ( const shared_singleton_lock & rhs ) : recursive_mutex::scoped_lock ( mutex_holder::pointer ( )->get_mutex ( ) ) { } shared_singleton_lock & operator = ( const shared_singleton_lock & rhs ) { } }; // singleton which uses the locking policy class shared_singleton : public singleton_ex < shared_singleton, lifo_lifetime_ex < instant_creation, create_statically, shared_singleton_lock > > { private: // depends upon mutex_holder mutex_holder::pointer holder_ptr; int val; protected: shared_singleton ( ) : val ( 0 ) { } public: // Put something in here designed to fail if two // threads access the function at the same time void DoSomething ( ) { std::cout << "Entering function, val == " << val << "\n"; val = val + 1; std::cout << "Exiting function, val == " << val << "\n"; } }; void test ( ) { shared_singleton::pointer ptr; // we have 6 threads, so if all goes well // the last thing printed should be 6000 for ( int i = 0; i < 1000; ++i ) { ptr->DoSomething ( ); } } int main ( ) { thread t1 ( &test ); thread t2 ( &test ); thread t3 ( &test ); thread t4 ( &test ); thread t5 ( &test ); thread t6 ( &test ); // must join all threads so that program does not end // while threads are executing ( this would kill the // singleton instances and probably result in a crash ) t1.join ( ); t2.join ( ); t3.join ( ); t4.join ( ); t5.join ( ); t6.join ( ); return 0; }

"Stefan Strasser" wrote:
- seems not to be tested with many compilers(...several newer compilers...)
I should have wrote all details I got from Jason but I was lazy: ----- Jason Hise----- I made sure that the library compiles with VC 7.0, VC 7.1, VC 8.0, and Bloodshed 4.9.9.2. The example cannot be immediately compiled with VC 7.0 as it uses lambda expressions, but if those use cases are commented out it works fine. -------------------------- I played with VC6 and there are problems with linker. I also plan to try BCB6.4 port but only as the last compiler. /Pavel

I'm a little confused about singleton usage. Can a singleton have a constructor? I tried this: using boost::basic_singleton; struct Example : public basic_singleton<Example> { Example() { std::cout << "Hello\n"; } int Cnt() const { return 0; } }; int main() { Example::pointer ptr; std::cout << ptr->Cnt(); } ./Test1 0 It appears constructor wasn't run, because nothing was printed.

"Neal Becker" write:
I'm a little confused about singleton usage. Can a singleton have a constructor?
I tried this:
using boost::basic_singleton;
struct Example : public basic_singleton<Example> { Example() { std::cout << "Hello\n"; } int Cnt() const { return 0; } };
int main() { Example::pointer ptr; std::cout << ptr->Cnt(); }
./Test1 0
It appears constructor wasn't run, because nothing was printed.
I tried it with Intel 7 (plugged in VC6 IDE) and it works for me. What is your compiler? Singleton can have constructors, many of them and with parameters too. One may do: Example::pointer ptr; ... ptr->destroy(); ptr->create(100, "sss", 3.14); ... ptr->destroy(); ptr->do_something(); // default ctor will be used first ... ptr->destroy(); ptr->create(); // default ctor ptr->create(); // ignored here /Pavel

Pavel Vozenilek wrote:
"Neal Becker" write:
I'm a little confused about singleton usage. Can a singleton have a constructor?
I tried this:
using boost::basic_singleton;
struct Example : public basic_singleton<Example> { Example() { std::cout << "Hello\n"; } int Cnt() const { return 0; } };
int main() { Example::pointer ptr; std::cout << ptr->Cnt(); }
./Test1 0
It appears constructor wasn't run, because nothing was printed.
I tried it with Intel 7 (plugged in VC6 IDE) and it works for me. What is your compiler?
I ran it on gcc version 3.4.3 20050227 (Red Hat 3.4.3-22.fc3) (x86_64), latest singelton lib (per announcement), and boost-1.32.0

Neal Becker wrote:
I'm a little confused about singleton usage. Can a singleton have a constructor?
I tried this:
using boost::basic_singleton;
struct Example : public basic_singleton<Example> { Example() { std::cout << "Hello\n"; } int Cnt() const { return 0; } };
int main() { Example::pointer ptr; std::cout << ptr->Cnt(); }
./Test1 0
It appears constructor wasn't run, because nothing was printed.
That's strange, your program works fine for me. The constructor should be being run on the line where you first create the pointer. If the constructor isn't being run, you should be getting some sort of runtime error when you try to dereference the pointer. What compiler are you using? Can you put a breakpoint inside the constructor to verify that it is never reached? Are you using the most recent version of the library? -Jason

I like the effort so far in Singleton, but I am far from convinced that the library should be accepted. Specifically, I think there are still too many open issues and questions about the design, implementation, and portability. Most of these have been covered in other threads of discussion. I am not sure it has enough maturity (which is different from age) for acceptance. Thus, I vote no, though I am more than willing to reconsider upon resubmission.

Pavel, Overall, I do not consider the library ready for acceptance into Boost. My review follows: Jason's Singleton library would fill a clear niche, and the demand for a flexible implementation such as this is obviously high. I think this particular implementation has some novel ideas, particularly "multiton," which I know I've had to implement before, but have never seen anybody codify as a pattern per se. I also think that Jason had a good jumping-off point in starting with Andrei Alexandrescu's Loki::SingletonHolder. However I think Jason's work suffers from a number of problems, both conceptual and concrete. I'll rattle these off in no particular order: 1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations. 2. The auto_reset struct has some conceptual issues. The biggest of these is that the scope of the auto_reset object, if I understand it correctly, can exceed the lifetime of the variable it references. If such an object is strictly necessary, I believe it should own the object it references. Another minor nit: the template should be parametrized not only on the variable type, but also the reset value type. And lastly, the documentation contains implementation details in the interface. 3. The leaky_lifetime class is indicated as "not recommended for general use." I tend to disagree: in production code I've had experience with, it's been very appropriate to manually control the order of destruction of singleton resources, because there are often dependencies. Some of these issues can be mitigated by dependency_lifetime, which is a good contribution. But I think the use of leaky_lifetime shouldn't be explicitly discouraged. I think it would be more appropriate to name the class simply "unmanaged_lifetime". 4. I think multiton is a good idea, but its execution is incomplete. If it's in the library, my feeling is that it should implement the requirements of the standard Pair Associative Container fully. (I'd also suggest calling it singleton_map). 5. The polymorphic_pointer and polymorphic_reference helpers seem sketchy to me somehow. I don't understand their use. I'd like to see use cases in the documentation. 6. The exists(), is_null() and operator bool() methods fall prey to a well known C++ pitfall. Have a look at Bjorn Karlsson's article, "The Safe Bool Idiom": http://www.artima.com/cppsource/safebool.html. 7. I want to reiterate my overwhelming disagreement with both the necessity for, and the approach taken, by the pure virtual enable_singleton_creation method. This has been discussed at length in the thread rooted at http://aspn.activestate.com/ASPN/Mail/Message/2531666. 8. The docs are sorely lacking in detail. For example, the methods in the basic_singleton and singleton_ex interfaces are not enumerated anywhere, and none of the examples I saw show how to get an instance of a singleton. All that I felt was illustrated were various regurgitations of the "curiously recurring template pattern." Personally, this gives me the impression (justified or not) that Jason has been focusing more on the cleverness of his implementation than what it has to offer in terms of genuine novelty or general usefulness. Which brings me to my last point: 9. When implementing a Tree library has been discussed on the Boost mailing list, the biggest point that I feel was made in that discussion was (paraphrasing) "any idiot can implement a tree, but thinking about the discrete concepts that comprise the wide variety of trees, and about the concepts' interoperability with other existing concepts such as standard containers and algorithms, is a much harder task." I feel the same critique applies here. The library does offer a novel concept embodied by "multiton", but my comments about multiton's failure to implement Pair Associative Container and of the library's use of a creator policy rather than standard allocators, are examples of this. I feel that some deeper thought should be given to the concepts: all the rest is fluff. To address the standard questions, briefly: * What is your evaluation of the design? A good basic idea with some excellent, novel contributions, but some design problems (primarily inattention to concepts) * What is your evaluation of the implementation? Problematic (see above) * What is your evaluation of the documentation? Very incomplete. Interfaces are not completely described, some implementation detail remains in the interfaces, and use cases are lacking. * What is your evaluation of the potential usefulness of the library? Potentially very useful. I look forward to seeing some implementation of the singleton pattern make its way into Boost eventually. * Did you try to use the library? With what compiler? Did you have any problems? I did not use it. * How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? Somewhere between a quick reading and an in-depth study. I focused on some areas and skimmed others. * Are you knowledgeable about the problem domain? Yes, reasonably knowledgeable. Just like the rest of us I've implemented enough singletons and "multitons" to know about the basics of design, and the relevant issues in production code. Again, to summarize, I think Jason's work shows promise, but needs a lot of work before I'd consider it acceptable. Regards, dr On 5/4/05, Pavel Vozenilek <pavel_vozenilek@hotmail.com> wrote:
The formal review of Singleton library written by Jason Hise starts today, May 5th, and lasts 10 days.

"Dan Rosen" wrote: Thanks for your review. It almost looked here as if no one cares.
I think this particular implementation has some novel ideas, particularly "multiton," which I know I've had to implement before, but have never seen anybody codify as a pattern per se.
There is Ruby library (in permanent beta) implementing multiton. http://raa.ruby-lang.org/project/multiton/
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Creators allows to use arguments when singleton is (re)created, like: Example::pointer ptr; .... ptr->create(111, "abc"); .... ptr->destroy(); ptr->create(); .... While it would be possible to simulate this feature with copy constructor it would violate common expectations placed on singleton class.
2. The auto_reset struct has some conceptual issues. The biggest of these is that the scope of the auto_reset object, if I understand it correctly, can exceed the lifetime of the variable it references. If such an object is strictly necessary, I believe it should own the object it references. Another minor nit: the template should be parametrized not only on the variable type, but also the reset value type. And lastly, the documentation contains implementation details in the interface.
auto_reset.hpp is simplified version of <boost/state_saver.hpp>. There were discussions on mail-list about this utility. Using <boost/state_saver.hpp> would be prefereble to home grown variant, IMHO. In singleton library auto_reset is used internally w/o dangers you mention. The documentation should be hidden, indeed.
3. The leaky_lifetime class is indicated as "not recommended for general use." I tend to disagree: in production code I've had experience with, it's been very appropriate to manually control the order of destruction of singleton resources, because there are often dependencies. Some of these issues can be mitigated by dependency_lifetime, which is a good contribution. But I think the use of leaky_lifetime shouldn't be explicitly discouraged. I think it would be more appropriate to name the class simply "unmanaged_lifetime".
Dependencies between singletons are best solved by owning other singleton pointer. This is documented at the end of tutorial (basic.htm) but obviously it should be more visible. "unmanaged" sounds as something related to .NET. I had suggested "immortal" but native English speakers are better to think about this.
4. I think multiton is a good idea, but its execution is incomplete. If it's in the library, my feeling is that it should implement the requirements of the standard Pair Associative Container fully. (I'd also suggest calling it singleton_map).
More features to multiton has been planned with so called "iterable_multiton". This one would be more like std::map and in addition, user will be able to iterate through it by creation time for individual objects.
5. The polymorphic_pointer and polymorphic_reference helpers seem sketchy to me somehow. I don't understand their use. I'd like to see use cases in the documentation.
Yes.
6. The exists(), is_null() and operator bool() methods fall prey to a well known C++ pitfall. Have a look at Bjorn Karlsson's article, "The Safe Bool Idiom": http://www.artima.com/cppsource/safebool.html.
Looks so. It would be nice to have a common support for this in Boost, though.
8. The docs are sorely lacking in detail. For example, the methods in the basic_singleton and singleton_ex interfaces are not enumerated anywhere, and none of the examples I saw show how to get an instance of a singleton. All that I felt was illustrated were various regurgitations of the "curiously recurring template pattern."
Expansion of the documentation and more examples is planned. While having complete and perfect documentation at this point would be ideal there are real world constraints. I watched the documentation go steadily better and have reason to think it will do so in the future. /Pavel

On 5/10/05, Pavel Vozenilek <pavel_vozenilek@hotmail.com> wrote:
"Dan Rosen" wrote:
(snip)
6. The exists(), is_null() and operator bool() methods fall prey to a well known C++ pitfall. Have a look at Bjorn Karlsson's article, "The Safe Bool Idiom": http://www.artima.com/cppsource/safebool.html.
Looks so. It would be nice to have a common support for this in Boost, though.
I suggested this as an addition to the operators library sometime ago, and patches to the code/docs/tests were applied, but they were later removed. I'll to summarise why. The first suggestion, which was based on Peters pointer to member function conversion : http://lists.boost.org/MailArchives/boost/msg44416.php (the patches) http://lists.boost.org/MailArchives/boost/msg44529.php But then Daniel Frey found a problem with the implementation for classes with integral conversion operators of their own. The integral conversion operator was a better match and so the safe-bool conversion was never called : http://lists.boost.org/MailArchives/boost/msg44894.php So then we tried an implementation based on using a private integral conversion operator and a public operator bool : http://lists.boost.org/MailArchives/boost/msg45089.php This worked well in itself, but caused problems with the type traits is_convertible (sorry, don't seem to be able to find a link to any of those messages). Finally the whole topic was dropped after a long thread, and the code was removed from the CVS tree. A shame I think though, as there were still several open designs which had possiblities. The end of the discussion is here : http://aspn.activestate.com/ASPN/Mail/Message/boost/1900317 I'd like to see the solution back in boost, we've been using it here for a couple of years now without problems, and we find it very useful. I'd be willing to put more work into it if there is interest. Sam

"Sam Partington" wrote:
6. The exists(), is_null() and operator bool() methods fall prey to a well known C++ pitfall. Have a look at Bjorn Karlsson's article, "The Safe Bool Idiom": http://www.artima.com/cppsource/safebool.html.
Looks so. It would be nice to have a common support for this in Boost, though.
I suggested this as an addition to the operators library sometime ago, and patches to the code/docs/tests were applied, but they were later removed. I'll to summarise why.
The first suggestion, which was based on Peters pointer to member function conversion : http://lists.boost.org/MailArchives/boost/msg44416.php (the patches) http://lists.boost.org/MailArchives/boost/msg44529.php
But then Daniel Frey found a problem with the implementation for classes with integral conversion operators of their own. The integral conversion operator was a better match and so the safe-bool conversion was never called :
http://lists.boost.org/MailArchives/boost/msg44894.php
So then we tried an implementation based on using a private integral conversion operator and a public operator bool :
http://lists.boost.org/MailArchives/boost/msg45089.php
This worked well in itself, but caused problems with the type traits is_convertible (sorry, don't seem to be able to find a link to any of those messages).
Finally the whole topic was dropped after a long thread, and the code was removed from the CVS tree. A shame I think though, as there were still several open designs which had possiblities. The end of the discussion is here :
http://aspn.activestate.com/ASPN/Mail/Message/boost/1900317
I'd like to see the solution back in boost, we've been using it here for a couple of years now without problems, and we find it very useful. I'd be willing to put more work into it if there is interest.
Reads like a story. Small utilities don't always get handled in the best way. Perhaps you may propose your as new library (which just happens not to add new files). It would take long but at least this process has clear resolution at the end. /Pavel

"Dan Rosen" wrote:
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Thinking it again: you are likely right here. Handling of constructor arguments could be separated from allocation. /Pavel

From: "Pavel Vozenilek" <pavel_vozenilek@hotmail.com>
"Dan Rosen" wrote:
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Thinking it again: you are likely right here.
Handling of constructor arguments could be separated from allocation.
I don't know about that, but perhaps an adapter could be provided to make a standard allocator look like a creator? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" wrote:
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Thinking it again: you are likely right here.
Handling of constructor arguments could be separated from allocation.
I don't know about that, but perhaps an adapter could be provided to make a standard allocator look like a creator?
I should be possible w/o adapter. Just expecting std::allocator like parameter in template. /Pavel

From: "Pavel Vozenilek" <pavel_vozenilek@hotmail.com>
"Rob Stewart" wrote:
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Thinking it again: you are likely right here.
Handling of constructor arguments could be separated from allocation.
I don't know about that, but perhaps an adapter could be provided to make a standard allocator look like a creator?
I should be possible w/o adapter. Just expecting std::allocator like parameter in template.
That's only true if you separate the construction functionality from the allocation. If you can't for some reason (I haven't looked to see whether it is possible), an adapter can rely on the allocator for its memory management. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: "Pavel Vozenilek" <pavel_vozenilek@hotmail.com>
"Rob Stewart" wrote:
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Thinking it again: you are likely right here.
Handling of constructor arguments could be separated from allocation.
I don't know about that, but perhaps an adapter could be provided to make a standard allocator look like a creator?
I should be possible w/o adapter. Just expecting std::allocator like parameter in template.
That's only true if you separate the construction functionality from the allocation. If you can't for some reason (I haven't looked to see whether it is possible), an adapter can rely on the allocator for its memory management.
Just to make sure... have you looked at create_using_std_allocator? It is designed to make it easy to use anything that fits the description of a standard allocator, and allows you to specify whether or not failed allocation (returning null) results in a bad_alloc exception being thrown. I personally do not feel that creation and allocation are redundant. Allocation is initialization of memory, and creation is the initialization of an object. Additionally, I feel that it is important that creators be easy for client code to write when necessary. The current interface required for a singleton creator is, IMO, much simpler to meet than the interface for a standard allocator. Being able to write a creator makes it easy to wrap other existing libraries with singletons relatively quickly. -Jason

"Jason Hise" wrote:
1. Creator policy is redundant with the standard Allocator concept [snip]
Additionally, I feel that it is important that creators be easy for client code to write when necessary. The current interface required for a singleton creator is, IMO, much simpler to meet than the interface for a standard allocator. Being able to write a creator makes it easy to wrap other existing libraries with singletons relatively quickly.
We are stuck with std::allocators and there's no realistic hope they will change/disappear. So people will code against them, even when it is suboptimal solution. /Pavel

From: Jason Hise <chaos@ezequal.com>
Rob Stewart wrote:
From: "Pavel Vozenilek" <pavel_vozenilek@hotmail.com>
"Rob Stewart" wrote: [the next two levels of attributions were lost]
1. Creator policy is redundant with the standard Allocator concept, I think. Though the standard Allocator concept has some subtle, tricky semantics, I think it's nevertheless worth using: that would permit interoperability with existing allocator implementations.
Thinking it again: you are likely right here.
Handling of constructor arguments could be separated from allocation.
I don't know about that, but perhaps an adapter could be provided to make a standard allocator look like a creator?
I should be possible w/o adapter. Just expecting std::allocator like parameter in template.
That's only true if you separate the construction functionality from the allocation. If you can't for some reason (I haven't looked to see whether it is possible), an adapter can rely on the allocator for its memory management.
Summary with implied but possibly misunderstood information: OP: Creator policy is redundant with standard allocators. Pavel: Maybe you're right; construction and allocation could be handled separately. Me: An adapter could be used to fit a standard allocator into the creator mold. Pavel: No need for an adapter; change template parameter list. Me: That only works if you separate construction from allocation since allocators don't construct from argument lists.
Just to make sure... have you looked at create_using_std_allocator? It
Nope.
is designed to make it easy to use anything that fits the description of a standard allocator, and allows you to specify whether or not failed allocation (returning null) results in a bad_alloc exception being thrown.
That sounds like just the adapter I was suggesting.
I personally do not feel that creation and allocation are redundant. Allocation is initialization of memory, and creation is the initialization of an object.
I didn't say they were redundant, but that was the original point being made.
Additionally, I feel that it is important that creators be easy for client code to write when necessary. The current interface required for a singleton creator is, IMO, much simpler to meet than the interface for a standard allocator. Being able to write a creator makes it easy to wrap other existing libraries with singletons relatively quickly.
I agree. The simpler interface is superior to that of an allocator for those writing a creator without need for an allocator. However, for those clients with a standard allocator, your create_using_std_allocator adapter gives the best of both worlds. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Does anyone have any additional comments about the singleton? So far the major items on my TODO list include: * Provide a built in policy which actually locks using boost.thread's mutexes * Use declspec for windows builds to make dlls work with singletons naturally * Make the multiton fit the requirements for a pair associative container. * Fix boolean conversion for pointers * A lot more example code in the docs Is there anything else that anyone feels is missing from the singleton library? Even if you don't have anything new to mention, I would appreciate hearing whether or not you think the singleton is useful in its current state. It will help the review manager a great deal in making his decision if more people cast their votes. -Jason

Jason, I think my primary point may have gotten lost in the length of my original post. I want to emphasize that I think you need to focus on the concepts (in the STL sense of the word). At a minimum, I'd like to see a relatively complete description of the semantics for each method in every interface. I'm sure you've seen this already, but the SGI docs: http://www.sgi.com/tech/stl are a good example of what I'm looking for. For a more granularly policy-ized example (akin to Singleton), the Boost Threads docs are also a decent style guide, I think. If you can articulate the concepts you're representing clearly, I think the process of solidifying the library for submission will be much more straightforward and smoother for you. Also, regarding your direct question about the usefulness of Singleton in its present state: for me, the question is "would I download this regardless of whether or not it was in Boost?" I believe it is presently useful, but not as useful as it could be if you got the concepts solid (and, since the interfaces are changing, not yet stable enough either). In my mind, multiton is the primary example of this. If you had that solid, I'd definitely see myself downloading and using Singleton regardless of its acceptance into Boost. Best, dr On 5/12/05, Jason Hise <chaos@ezequal.com> wrote:
Does anyone have any additional comments about the singleton? So far the major items on my TODO list include:
* Provide a built in policy which actually locks using boost.thread's mutexes * Use declspec for windows builds to make dlls work with singletons naturally * Make the multiton fit the requirements for a pair associative container. * Fix boolean conversion for pointers * A lot more example code in the docs
Is there anything else that anyone feels is missing from the singleton library? Even if you don't have anything new to mention, I would appreciate hearing whether or not you think the singleton is useful in its current state. It will help the review manager a great deal in making his decision if more people cast their votes.
-Jason
participants (18)
-
Angus Leeming
-
Bjørn Roald
-
Dan Rosen
-
David Abrahams
-
David Sankel
-
Gennadiy Rozental
-
Jason Hise
-
Jody Hagins
-
Jonathan Turkanis
-
Neal Becker
-
Pavel Antokolsky aka Zigmar
-
Pavel Vozenilek
-
Rob Stewart
-
Russell Hind
-
Sam Partington
-
Stefan Strasser
-
Terence Wilson
-
Yuval Ronen