Boost logo

Boost :

From: Rainer Deyke (root_at_[hidden])
Date: 2001-11-13 22:54:00


----- Original Message -----
From: "Gennadiy E. Rozental" <rogeeff_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Tuesday, November 13, 2001 7:42 PM
Subject: [boost] Re: Work in progress list? And how about a singleton?

> --- In boost_at_y..., "Rainer Deyke" <root_at_r...> wrote:
> > ----- Original Message -----
> > From: "Gennadiy E. Rozental" <rogeeff_at_m...>
> > To: <boost_at_y...>
> > Sent: Tuesday, November 13, 2001 1:22 PM
> > Subject: [boost] Re: Work in progress list? And how about a
> singleton?

> In my expirience need for the singleton abstraction is encountered
> rather frequently. So I think I have some original problem that I
> need to find a solution for.

I frequently encounter the need for a global resource. I have yet to
encounter a single situation where a singleton (i.e. a class that only has
one instance) is the best way to implement that resource. I suspect you are
overdesigning.

> > When I need global state that is sensitive to
> > creation order in my program, I tend to do something like this:
> >
> > std::vector<std::string>& get_strings()
> > {
> > static std::vector<std::string> strings;
> > return strings;
> > }
>
> This is simpliest singleton (decision 1.b, 2.b, 3.a, 4.c, 5.a, 6.a,
> 7.a, 8.a ). Another issue is that you allow instantiating of
> singleton class by anybody, which is supposed to be prohibited (this
> is one of the reason to use singleton). By this means you can't
> implement non default constructable singleton and so on. You could
> take a look in my comments in
> http://groups.yahoo.com/group/boost/message/19949

I'm not writing a singleton class here, I'm just creating a shared global
object of an existing class (in this case 'std::vector<std::string>').
Preventing multiple instantiation of 'std::vector<std::string>' would not be
a good idea even if it was possible.

> > > 2. When singleton is created:
> > > a. automatically before main
> > > b. automatically in static memory at the point of first access
> > > d. automatically in dynamic memory at the point of first access
> > > c. mannually by user
> > > and couple more
> >
> > Several issues here.
> >
> > - Sometimes a global resource has a specific lifetime. This is
> easily
> > modeled through a pointer.
> >
> > boost::scoped_ptr<A> a = 0;
> >
> > int main()
> > {
> > a.reset(new A);
> > // something else
> > a.reset();
> > }
> >
> > Sometimes the lifetime of such a global resource is tied to some
> other
> > object, in which something like this would work:
> >
> > class A;
> > A *a = 0;
> > class A {
> > public:
> > A() { assert(!a); a = this; }
> > ~A() { a = 0; }
> > };
> >
> > int main()
> > {
> > A shared_a;
> > // something else
> > }
> >
> > - Sometimes a global resource does not have a specific lifetime,
> it just
> > needs to be there when I need it. In this case any creation time
> other than
> > first point of access doesn't really make sense. I also don't see
> any
> > significant commonality between this type of shared resource and
> the other
> > type, so I would not attempt a single class that handles both.
>
> Well, I see some commonality and trying to use generative power of
> C++ templates to create two different classes from the same source,
> while all differences are factored into some policy/traits classes.

I don't see how these different kinds of global resources can share any
implementation or interface.

> > - If the object is created before 'main', then any exceptions
> thrown during
> > construction cannot be caught.
>
> Why, can't you use function try block?

I could do that if I write a custom class, but in general it's not worth it.

> > > 4. Way the singleton is accessed
> > > a. by pointer
> > > b. by const pointer
> > > c. by reference
> > > d. by const reference
> >
> > By pointer if the pointer could be a null pointer to indicate the
> object is
> > not yet created or already destroyed. By reference otherwise.
>
> By const pointer/reference if you don't want give an access to non
> const members.

A singleton is an implementation tool. I can always wrap another layer
around it enforce access restrictions.

>
> >
> > > e. counting reference
> >
> > I assume this is in support of 5c below?
> >
> > > 5. Way the singleton is destroyed
> > > a. automatically after exit from main
> >
> > This is the only one that makes sense for global resources that are
> created
> > on point of first access.
> >
> > > b. manually by user
> >
> > This is the only one that makes sense if the user manually creates
> it.
>
> No. You can create singleton at point of first access and then
> destroy it when you think you do not need it anymore. And vice versa
> You could create singleton manually and do not want to care about
> when and how it will be destroyed.

Either the lifetime of the global resource requires user management, or it
does not.

> > This seems to be another different type of global resource, not
> necessarily
> > related to the others.
>
> I do not see that much difference. The key features of singleton is
> an ability to provide an acess to a single object of a class that
> can't be instantiated by other means.

There are many uses for shared objects that are created on first access and
destroyed when they are no longer in use. Most of these uses have nothing
to do with singletons, so this functionality is better implemented
independently. For example, this functionality would be useful for a bitmap
cache that keeps all currently used bitmaps in memory so that multiple parts
of the program that use the same bitmap can share the same bitmap object
without keeping unused bitmaps in memory. These bitmap objects would
obviously all be of the same class and therefore wouldn't be singleton,
although the bitmap manager itself might.

> >
> > > 6. How to manage destruction several coworking singletons
> >
> > Inverse order of construction.
>
> Sorry for bad example in other posting. Consider following one, even
> simplier: A need global log object L for creating and destruction. So
> order of creation A, L. Automatic order of destruction L, A. When A
> destructed L already gone.

If 'A' needs 'L' for construction, the constructor of 'A' cannot complete
until 'L' is constructed. There the construction order is L, A, and the
destruction order must be A, L.

> > > 8. Number of times singleton could be instantiated
> > > a. One time
> >
> > This is automatically the case if it is created on point of first
> access and
> > remains in existence until exit from main.
> >
> > > b. Many times - phoenix singleton
> >
> > This is automatically the case if it's lifetime is controlled by
> the user.
>
> No. Possible scenario: you somehow(manually or automatically) create
> singleton then destroy it, somehow create it then destroy it and so
> on. On other hand you may want to prevent singleton from being able
> to recreate. How singleton is created is not relevant.

There two kinds of global resources: those that always exist when you need
the (i.e. created at time of first access) and those that have a definite
user controlled lifetime. Preventing the latter from being created again
after it is destroyed is just plain bad design.

--
Rainer Deyke (root_at_[hidden])
Shareware computer games           -           http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk