
I'm going through the documentation and now have some questions. I would hope that the documentation could be expanded to include answers to these questions. a) reference is made to a "lease" which sounds like a mutex to me. But its not obvious to me how this should be used. How does the compare with the pattern that I am more familiar with class s : singlton mutex m_mutex ... my_function(...){ scoped_lock(m_mutex); ... } OK - I've looked again and I think its clear to me how this is to be used. We need a tutorial here !!!! b) reference is made to boost::restricted which I couldn't find anywhere. Robert Ramey

Robert Ramey wrote:
I'm going through the documentation and now have some questions. I would hope that the documentation could be expanded to include answers to these questions.
a) reference is made to a "lease" which sounds like a mutex to me. But its not obvious to me how this should be used. How does the compare with the pattern that I am more familiar with
class s : singlton mutex m_mutex ...
my_function(...){ scoped_lock(m_mutex); ... }
OK - I've looked again and I think its clear to me how this is to be used.
We need a tutorial here !!!!
b) reference is made to boost::restricted which I couldn't find anywhere.
c) the synopsis specifies static unspecified instance; But the Expression Symatics specifies D::instance->m which seems inconsistent to me. I Rather expect the synopsis to say D:instance.m or D::get_instance().m d) what about access to object which don't require thread locking - for example const members. Do they need locking/leasing also? I would guess not but? e) What does D::instance return ? a reference or pointer to the single instance of D or something else. I would expect the former, but the synopsis contains static "unspecified" instance rather than static T instance as I would expect. f) can "const" static objects be created? g) what happens if same interface used by different DLLS. Is one instance still created? Robert Ramey Robert Ramey

Robert Ramey wrote:
c) the synopsis specifies
static unspecified instance;
But the Expression Symatics specifies D::instance->m which seems inconsistent to me.
Why? 'm' is a member of the derived class. Obviously it's a user-defined thing, so I can't specify what it is.
I Rather expect the synopsis to say
D:instance.m
or
D::get_instance().m
D::instance is a pointer-like proxy. We can't overload operator., we can't expose the object directly (to ensure initialization) and we can't implement automatic locking if we expose the object by returning it. Nice bonus: There seamless interoperability with anything that accepts a smart pointer.
d) what about access to object which don't require thread locking - for example const members. Do they need locking/leasing also? I would guess not but?
As explained in my previous reply 'mutexed_singleton' locks every access (imagine you're iterating a list to get the const result - if that list is not locked it might get modified and the program might e.g. access freed memory) while 'singleton' puts synchronization in the responsibility of the user. If your objects are immutable (all member functions are const and no mutable members are present) you can just use 'singleton' and no locking is done.
e) What does D::instance return ? a reference or pointer to the single instance of D or something else. I would expect the former, but the synopsis contains
static "unspecified" instance
That's right.
rather than
static T instance as I would expect.
No, it's a proxy of unspecified type. Implementation detail: That proxy's operator-> returns T* for 'singleton' and yet another proxy for 'mutexed_singleton'.
f) can "const" static objects be created?
I'm not sure I've tried, yet. What would it be good for (as it doesn't make a difference if the singleton instance is immutable and it would yield inaccessible code if it wasn't)? Maybe it should be possible for completeness...
g) what happens if same interface used by different DLLS. Is one instance still created?
Yes. Thanks for your comments. Regards, Tobias

Tobias Schwinger wrote:
Robert Ramey wrote:
f) can "const" static objects be created?
I'm not sure I've tried, yet.
What would it be good for (as it doesn't make a difference if the singleton instance is immutable and it would yield inaccessible code if it wasn't)?
Say you need to set up a map of string to function pointer (or some silliness like that). After construction, such a thing should be const. Or is that not what you understood from the question? Sohail

OK - it seems to me that you've got everything covered. I'm anxious to try this out. I just have to figure a way to make it optional pending acceptance (or rejection) from boost. The "const" question isn't a big deal for me but I just like to you "const" every chance I get. I number of the static objects in the serialization libary are just to hold pointers to some template instantiations for unknown derived types so they could be "const". I now understand the static "internal type" instance. But it's very confusing when one reads the documentation. There's not explanation that it overloads the -> operator (other than the table entry in requirements. Given this I expect the synopsis to read static "internal type" *instance which one would expect to apply the -> operator to. Then there's the issue of using what looks like a public member variable as an interface. There are going to be complaints about this. I realize that these things could be dismissed as "cosmetic" - they are "cosmetic" - but going along with common customs and patterns makes it easier to grasp. So think about this. Tutorial - include an example of using this as an aditional base class in a multiple inheritance. This would not have occurred to me until it was probably too late but I think it might be very helpful to me now. Is there any way to test the claim that this thing keeps one instance even though the interface is used from mainline or DLLS. With serialization library it sometimes happens that users use a type in the mainline and the go do the same thing in the DLL. This results in two instances being created as the static initializer is compiled into each translation unit as a local function. This results in multiple typeinfo records corresponding to the same type.which could create some problems. I haven't figured out to use bjam to create a DLL in the same directory as the mainline test module so that this proposition can verified. Robert Ramey

----- Mensaje original ----- De: Tobias Schwinger <tschwinger@isonews2.com> Fecha: Sábado, Agosto 25, 2007 1:06 am Asunto: Re: [boost] Threadsafe singleton - questions Para: boost@lists.boost.org
Robert Ramey wrote: [...]
g) what happens if same interface used by different DLLS. Is one instance still created?
Yes.
Are you sure? For instance, in Windows globals aren't merged on DLL loading, so if you've got something like: /*** foo.hpp ***/ template<typename T> struct foo { static T* get() { T t; return &t; } }; /*** main.cpp ***/ #include "foo.hpp" T* t1=foo<T>::get(); /*** dll1.cpp ***/ #include "foo.hpp" T* t2=foo<T>::get(); you'll get different t1 and t2 values. I don't see how you're able to prevent this behavior for the local static data of singleton_manager. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN LOPEZ MU?Z wrote:
----- Mensaje original ----- De: Tobias Schwinger <tschwinger@isonews2.com> Fecha: Sábado, Agosto 25, 2007 1:06 am Asunto: Re: [boost] Threadsafe singleton - questions Para: boost@lists.boost.org
Robert Ramey wrote: [...]
g) what happens if same interface used by different DLLS. Is one instance still created? Yes.
Are you sure? For instance, in Windows globals aren't merged on DLL loading, so if you've got something like:
/*** foo.hpp ***/ template<typename T> struct foo { static T* get() { T t; return &t; } };
/*** main.cpp ***/ #include "foo.hpp"
T* t1=foo<T>::get();
/*** dll1.cpp ***/ #include "foo.hpp"
T* t2=foo<T>::get();
you'll get different t1 and t2 values.
Right.
I don't see how you're able to prevent this behavior for the local static data of singleton_manager.
Not at all: As client Singletons are user classes it's the users responsibility to eventually add declspec stuff for windows. It should probably be mentioned in the docs. Thanks for the heads up. Regards, Tobias

Tobias Schwinger wrote:
JOAQUIN LOPEZ MU?Z wrote:
----- Mensaje original ----- De: Tobias Schwinger <tschwinger@isonews2.com> Fecha: Sábado, Agosto 25, 2007 1:06 am Asunto: Re: [boost] Threadsafe singleton - questions Para: boost@lists.boost.org
Robert Ramey wrote: [...]
g) what happens if same interface used by different DLLS. Is one instance still created? Yes. Are you sure? For instance, in Windows globals aren't merged on DLL loading, so if you've got something like:
Currently, not even symbol merging can keep us from potential breakage. It can even make things worse, at cases (see below). <code>
you'll get different t1 and t2 values.
Right.
...which (after some more thinking about how Singletons should work with across dynamic library boundaries) is in fact a good thing since a dynamic library shouldn't make any assumptions about when it gets unloaded.
I don't see how you're able to prevent this behavior for the local static data of singleton_manager.
The data is initialized (and inserted into the manager's list) by the Singleton itself, while the manager just handles destruction. Still problematic, however.
Not at all: As client Singletons are user classes it's the users responsibility to eventually add declspec stuff for windows.
It should probably be mentioned in the docs. Thanks for the heads up.
Unfortunately, it's not that simple... A Singleton that is exposed in the header will currently get inlined into the client (including the manager) which can cause serious trouble: A Singleton might end up to exist multiple times and a destructor located in already-unloaded code. This situation can even occur if a dynamic library uses a Singleton internally and symbols get merged (unless merging is #pragmaTically disabled, which might not be possible for all ABIs). The good news: The next version will introduce means for full control over what happens in all sorts of shared library scenarios. Thanks again. Regards, Tobias

Robert Ramey wrote:
I'm going through the documentation and now have some questions. I would hope that the documentation could be expanded to include answers to these questions.
a) reference is made to a "lease" which sounds like a mutex to me.
No it is not a mutex. The 'lease' is a syntactic construct of the interface. Its purpose is to optain a proxy for subsequent calls. A 'mutexed_singleton' is locked by the existence of a lease object. Others are not.
But its not obvious to me how this should be used. How does the compare with the pattern that I am more familiar with
class s : singlton mutex m_mutex ...
my_function(...){ scoped_lock(m_mutex); ... }
OK - I've looked again and I think its clear to me how this is to be used.
OK, I'll answer, anyway. It depends on what you want to do: If your singleton holds some data structure (e.g. a linked list) and you want it to be thread-safe just use 'mutexed_singleton', put a member (e.g. a std::list) inside it and you don't need to care about anything else (concurrent access is mutually exclusive). If your use case is more complicated (e.g. you have a reader/writer problem or several data structures are contained that aren't touched by all member functions) you might want to do things yourself (e.g. using 'read_write_mutex' or several mutexes, respectively). In this case use 'singleton' and synchronize access to the singleton body yourself. This is also the right choice if the Singleton is immutable (such as extended type info might be). Note that the initialization is still thread-safe. The 'thread_specific_singleton' is a different kind of beast in this regard, since it doesn't need much synchronization - every thread gets its own instance.
We need a tutorial here !!!!
Yep, especially since you're not the first one who asks.
b) reference is made to boost::restricted which I couldn't find anywhere.
That's a bit strange since it's even documented redundantly as an unspecified type. It ensures that client code can't accidentally create non-singleton instances of the class. Regards, Tobias
participants (4)
-
"JOAQUIN LOPEZ MU?Z"
-
Robert Ramey
-
Sohail Somani
-
Tobias Schwinger