StateFull vs Stateless Singleton

P

Pallav singh

Hi

what the consideration parameter to choose stateless and statefull
Singleton ?

Thanks
Pallav Singh
 
F

Francesco S. Carta

Hi

what the consideration parameter to choose stateless and statefull
Singleton ?

The mere need of a "stateless singleton" seems to be debatable - since
the things it can achieve can equally be achieved via regular functions
and static member functions - assuming I haven't completely
misunderstood them, any correction from better knowing will be welcome.

In any case, the considerations to make (in general) lie upon the
requirements of the single cases. Have you got any practical example to
consider?
 
Ö

Öö Tiib

Hi

what the consideration parameter to choose stateless and statefull
Singleton ?

Both are sort of java nonsense to achieve non-copyable global state or
global functions that java does not let you have otherwise. Global
state is bad design in all languages. Global functions are fine, but
you do not need singeltons for them in C++.
 
S

sebastian

Hi

what the consideration parameter to choose stateless and statefull
Singleton ?

Thanks
Pallav Singh

Neither - a simple template class eliminates the issue altogether:

<code>

#include <stdexcept>

template < typename Type >
class singleton
{
public:

singleton( void )
{
Type* ptr = static_cast< Type* >( this );
if( self )
{
/*
Or what have you...
*/
throw std::runtime_error
(
"Error: attempt to instantiate multiple instances of a singleton"
);
}
self = ptr;
}

static inline Type& instance( void )
{
return *self;
}

static inline bool exists( void )
{
return self != 0;
}

virtual ~singleton( void )
{
self = 0;
}

private:

singleton( singleton const& );

singleton& operator = ( singleton const& );

static Type* self;
};

template < typename Type >
Type* singleton< Type >::self = 0;

// Example:

#include <iostream>

class foo : public singleton< foo >
{
public:

void bar( void ) const
{
std::cout << "foo::bar( )" << std::endl;
}
};

int main( void )
{
try
{
foo a;
foo::instance( ).bar( );
foo c; // Whoops!
foo::instance( ).bar( );
}
catch( std::exception const& error )
{
std::cerr << error.what( ) << std::endl;
}
}

</code>

The beauty of the design is that it allows the user to decide how to
allocate and initialize the derived class; it's sole purpose is to
make sure that multiple instances aren't created. Best of all, it's
completely generic!

Cheers.
 
Ö

Öö Tiib

Neither - a simple template class eliminates the issue altogether:

<code>

#include <stdexcept>

template < typename Type >
class singleton
{
        public:

        singleton( void )
        {
                Type* ptr = static_cast< Type* >( this );
                if( self )
                {
                /*
                        Or what have you...
                */
                        throw std::runtime_error
                        (
                                "Error: attempt to instantiate multiple instances of a singleton"
                        );
                }
                self = ptr;
        }

        static inline Type& instance( void )
        {
                return *self;
        }

        static inline bool exists( void )
        {
                return self != 0;
        }

        virtual ~singleton( void )
        {
                self = 0;
        }

        private:

        singleton( singleton const& );

        singleton& operator = ( singleton const& );

        static Type* self;

};

template < typename Type >
Type* singleton< Type >::self = 0;

// Example:

#include <iostream>

class foo : public singleton< foo >
{
        public:

        void bar( void ) const
        {
                std::cout << "foo::bar( )" << std::endl;
        }

};

int main( void )
{
        try
        {
                foo a;
                foo::instance( ).bar( );
                foo c; // Whoops!
                foo::instance( ).bar( );
        }
        catch( std::exception const& error )
        {
                std::cerr << error.what( ) << std::endl;
        }

}

</code>

The beauty of the design is that it allows the user to decide how to
allocate and initialize the derived class; it's sole purpose is to
make sure that multiple instances aren't created. Best of all, it's
completely generic!

Cheers.

Looks as beautiful like any other reinvented square wheel. The
requirements seem to be that such code must work:

int main( void )
{
{
foo a;
foo::instance( ).bar( );
}
foo c; // Second singleton and *NO* Whoops
foo::instance( ).bar( );
}

Not sure why someone needs to have global state? Typical example of
singletons is a logger. Huh? So ... OK. What if i need to have
separate logs from different modules? I will then need new class for
each log to have separate singleton logger for each module? Nonsense.

What if i need to have separate logs from different threads? Then that
Logger::instance() should give me "different" singletons based on
thread ID? Huh? Why it can't just be debugging::log() and where it
logs is its internal business, no global state no nothing?

As for your code ... same thing with 10-12 lines instead of 70-80:

#include <iostream>
namespace foo
{
void bar()
{
std::cout << "foo::bar()" << std::endl;
}
}

int main()
{
foo::bar();
}

Things that contain nothing are not worth allocating or initializing.
 
K

Keith H Duggar

Looks as beautiful like any other reinvented square wheel. The
requirements seem to be that such code must work:

...

Not sure why someone needs to have global state? Typical example of
singletons is a logger. Huh? So ... OK. What if i need to have
separate logs from different modules? I will then need new class for
each log to have separate singleton logger for each module? Nonsense.

Yeah, it seems to me that singleton is the single most heavily
abused design pattern. Maybe because its name is "cool sounding"
and because it is easy to implement and because it allows one to
remain lazy maybe those are a trifecta of abuse temptations.

I think the only pattern I've seen nearly as heavily abused (but
at least not reimplemented as often) is shared_ptr where some crap
coder(s) spams every pointer as a shared_ptr because of irrational
fear and/or unwillingness (or inability) to design proper lifetime
management or to eliminate the need for such management entirely.

KHD
 
S

sebastian

Looks as beautiful like any other reinvented square wheel. The
requirements seem to be that such code must work:

 int main( void )
 {
     {
         foo a;
         foo::instance( ).bar( );
     }
     foo c; // Second singleton and *NO* Whoops
     foo::instance( ).bar( );
 }

Not sure why someone needs to have global state? Typical example of
singletons is a logger. Huh? So ... OK. What if i need to have
separate logs from different modules? I will then need new class for
each log to have separate singleton logger for each module? Nonsense.

What if i need to have separate logs from different threads? Then that
Logger::instance() should give me "different" singletons based on
thread ID? Huh? Why it can't just be debugging::log() and where it
logs is its internal business, no global state no nothing?

As for your code ... same thing with 10-12 lines instead of 70-80:

 #include <iostream>
 namespace foo
 {
     void bar()
     {
         std::cout << "foo::bar()" << std::endl;
     }
 }

 int main()
 {
     foo::bar();
 }

Things that contain nothing are not worth allocating or initializing.

So...your point is that you hate the singleton pattern? Got it. I hate
it when people post snarky comments for no apparent reason,
personally. To each his (and her) own, I guess.

Cheers.
 
P

Pallav singh

So...your point is that you hate the singleton pattern? Got it. I hate
it when people post snarky comments for no apparent reason,
personally. To each his (and her) own, I guess.

Cheers.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

Hi

Q How does Polymorphism get implemented in Singleton ?
Q can we modify basic Singleton in such a way that all the class that
Inherit it become Singleton ?

Thanks
Pallav
 
Ö

Öö Tiib

So...your point is that you hate the singleton pattern? Got it. I hate
it when people post snarky comments for no apparent reason,
personally. To each his (and her) own, I guess.

Did i really insult you somewhere? Sorry then. I thought i posted
reasons. I do not dislike something blindly. I have met them more than
anyone deserves, and i have learned all possible and impossible ways
how to deal with them. One-size-fits-all solutions are usually wrong
so don't be insulted if yours is not exception.

Why the problem with singletons is not so apparent? What is the
difference between calling "globalVariable.doSomething()" and
"SingletonClass::instance().doSomething()" (other than some extra
letters to type on second case)? Both are tight coupling with global
state only semantics are different. Sometimes it is not worth to avoid
tight coupling between close classes but singleton is far and global.

The problem is not only tight coupling between distant things but that
such coupling is hidden within code (call site).

One often named purpose of singletons is that these limit the count of
how many instances there may be simultaneously (1 on case of
singleton). That sounds like responsibility of owners of objects to
limit number of simultaneous instances. Oh yes, global state does not
have owners, it is self-owned.

Also why only one instance? Who knows. "Pragmatic" reasons like "There
was only one window/database/display/player/client/user/account/store/
harddrive/configuration when we started with that application, so we
decided to carve it into rock in most hard way to modify." Mono-media.

Finally massive dependency on global state makes it impossible to rely
on unit tests. I can not imagine large project without even larger
amount of unit tests. Global state carries on behind scenes and so
unit tests may pass (or fail) just because of order in what these were
ran.

These are not apparent reasons? Imagine 25 man-years that was put into
C++ project. Result was with half of classes singletons (with
similarly various "solutions" and "purposes" and "pragmatic reasons").
Someone was paying lot of money for these 25 man-years so it was
like ... desirable thing for him. Original global-state-lover
architects did run far away because quite non-ambitious and reasonable
change requests are near-impossible to fulfill. How to explain why
what he has now is so costly to extend or maintain?

So ... nothing personal, sebastian, but yes i dislike singletons. For
good reasons.
 
J

James Kanze

On 4 juuli, 23:58, sebastian <[email protected]> wrote:

[...]
Looks as beautiful like any other reinvented square wheel. The
requirements seem to be that such code must work:
int main( void )
{
{
foo a;
foo::instance( ).bar( );
}
foo c; // Second singleton and *NO* Whoops
foo::instance( ).bar( );
}
Not sure why someone needs to have global state? Typical
example of singletons is a logger. Huh? So ... OK. What if
i need to have separate logs from different modules? I will
then need new class for each log to have separate singleton
logger for each module? Nonsense.

So your log manager is a singleton. Somewhere, there must be
a single bit of code which reads the configuration file for the
log.

Similarly, the configuration manager is a singleton. As is the
code which captures the command line and its options. In
a multithreaded application, the thread manager (which ensures
e.g. a clean shutdown) must be a singleton.
What if i need to have separate logs from different threads?
Then that Logger::instance() should give me "different"
singletons based on thread ID? Huh? Why it can't just be
debugging::log() and where it logs is its internal business,
no global state no nothing?

Huh? What is debugging::log()? (The syntax suggests a static
class member. A class instance function, in sum. So that its
data is a "singleton".)
 
J

James Kanze

On 5 juuli, 05:48, sebastian <[email protected]> wrote:

[...]
Why the problem with singletons is not so apparent? What is
the difference between calling "globalVariable.doSomething()"
and "SingletonClass::instance().doSomething()" (other than
some extra letters to type on second case)? Both are tight
coupling with global state only semantics are different.
Sometimes it is not worth to avoid tight coupling between
close classes but singleton is far and global.
The problem is not only tight coupling between distant things
but that such coupling is hidden within code (call site).
One often named purpose of singletons is that these limit the
count of how many instances there may be simultaneously (1 on
case of singleton). That sounds like responsibility of owners
of objects to limit number of simultaneous instances. Oh yes,
global state does not have owners, it is self-owned.
Also why only one instance? Who knows. "Pragmatic" reasons
like "There was only one
window/database/display/player/client/user/account/store/
harddrive/configuration when we started with that application,
so we decided to carve it into rock in most hard way to
modify." Mono-media.

I think there is some confusion about what is meant by
a singleton. A singleton is a class which can only be
instantiated once, regardless of how it is implemented. In C++,
the most frequently cited idiom handles order of
initialization (and is incredibly verbose), but that's
a secondary aspect.

Secondly, if the fact that a class can only have one instance is
a fundamental invariant of the class, it makes more sense for
the class itself to ensure this than for it to count on the
client not making mistakes.

Finally, the amount of coupling is to a large degree independant
of whether something is a singleton or not. Arguably, there's
even more coupling if you're passing a pointer to Log into every
function in the application. And in my experience, most
singletons are either static members, or are found in an unnamed
namespace.

In the end, the only real arguments against singletons are that
1) they are often abused (but then, so are a lot of other
things), and 2) the usual syntax is excessively verbose (but
that's easy to fix---just use a lighter syntax).
 
Ö

Öö Tiib

On 4 juuli, 23:58, sebastian <[email protected]> wrote:

    [...]


Looks as beautiful like any other reinvented square wheel. The
requirements seem to be that such code must work:
 int main( void )
 {
     {
         foo a;
         foo::instance( ).bar( );
     }
     foo c; // Second singleton and *NO* Whoops
     foo::instance( ).bar( );
 }
Not sure why someone needs to have global state? Typical
example of singletons is a logger. Huh? So ... OK. What if
i need to have separate logs from different modules? I will
then need new class for each log to have separate singleton
logger for each module? Nonsense.

So your log manager is a singleton.  Somewhere, there must be
a single bit of code which reads the configuration file for the
log.

I am not saying there may not be single instances of something. I am
saying that these should not be in some global state, so there is
danger to produce multiple by mistake or copy it and so it has to be
prevented by singleton pattern. Singular state is perfectly normal.
Where it is needed hide it into implementation to keep interface
laconic. That log configuration should be internal property of logging
framework and not some global self-owned state for anyone to ask
instance() for. Not even as private static member. Translation unit
local is perfect. Then it is function debugging::log() that consults
with private log manager (if there exist such) to find out where it
logs and how (if that differs) and not everyone typing nonsense like:

debugging::LogManager::instance().produceLogger().doYourTrick("bla
bla");
Similarly, the configuration manager is a singleton.

Depends what it manages. If "configuration" of dynamically loadable
modules then such thing must be there, but i would call it
"application" object (or its "configuration" member). If these are
module settings then these belong to each module. It is sad that C++
does not contain concept of dynamically loadable modules.
As is the code which captures the command line and its options.  

Command line is passed to main() and so main() passes it to some
singleton? Why it should be a singleton? These are command line
arguments for something that will be further called by main(). Why
there must be a global singleton that holds its options? However that
does not worry me, after all there are very few things that directly
depend on command line and that command line does not likely change
during program run.
In a multithreaded application, the thread manager (which ensures
e.g. a clean shutdown) must be a singleton.

At the moment yes, application (or some framework that it uses) has to
orchestrate shutdown itself. Again, when i do not get rid of single
things then i do not like "ShutDownManager::instance().doIt()". I
prefer to have shutDown() function. If nothing else then faking it for
a unit test is lot cheaper.
Huh?  What is debugging::log()?  (The syntax suggests a static
class member.  A class instance function, in sum.  So that its
data is a "singleton".)

No, i meant a namespace, sorry for not being clear there.
debugging::log() like std::sort(). Actually i suggest to wrap logging
into macro anyway. Some useful information like file/function/
linenumber are impossible to gather in a generic way without macros
involved.
 
Ö

Öö Tiib

In the end, the only real arguments against singletons are that
1) they are often abused (but then, so are a lot of other
things), and 2) the usual syntax is excessively verbose (but
that's easy to fix---just use a lighter syntax).

Yes, exactly. Nothing suggests to use:

SingletonFactory::instance().giveCordStringTyer().tie( cordString );

Use good syntax:

tie( cordString );
 
J

James Kanze

Yes, exactly. Nothing suggests to use:

SingletonFactory::instance().giveCordStringTyer().tie( cordString );
Use good syntax:
tie( cordString );

You reduce coupling somewhat by grouping functions in classes.
(If nothing else, they don't invade global namespace.) Still,
something like:
CommandLine::parse(argc, argv);
is still a lot less verbose than:
CommandLine::instance().parse(argc, argv);

I've recently remodeled most of my singletons to use this
syntax. In some cases, there may be a more classical singleton
behind the scenes (in order to resolve order of initialization
issues, for example), but there's no point in burdening the
client code with such details.

I haven't worked out a way to do this with templates, and
I don't think I'm going to bother. While I don't have the
horror of singletons that some do, there's not something that
I use frequently enough to justify developing a complex template
for them.
 
J

James Kanze

On 4 juuli, 23:58, sebastian <[email protected]> wrote:
[...]
Looks as beautiful like any other reinvented square wheel.
The requirements seem to be that such code must work:
int main( void )
{
{
foo a;
foo::instance( ).bar( );
}
foo c; // Second singleton and *NO* Whoops
foo::instance( ).bar( );
}
Not sure why someone needs to have global state? Typical
example of singletons is a logger. Huh? So ... OK. What if
i need to have separate logs from different modules?
I will then need new class for each log to have separate
singleton logger for each module? Nonsense.
So your log manager is a singleton. Somewhere, there must
be a single bit of code which reads the configuration file
for the log.
I am not saying there may not be single instances of
something. I am saying that these should not be in some global
state,

It's not "global" state:).
so there is danger to produce multiple by mistake or
copy it and so it has to be prevented by singleton pattern.
Singular state is perfectly normal. Where it is needed hide
it into implementation to keep interface laconic. That log
configuration should be internal property of logging framework
and not some global self-owned state for anyone to ask
instance() for. Not even as private static member. Translation
unit local is perfect. Then it is function debugging::log()
that consults with private log manager (if there exist such)
to find out where it logs and how (if that differs) and not
everyone typing nonsense like:
debugging::LogManager::instance().produceLogger().doYourTrick("bla
bla");

Well, logging is a very special case. Independantly of the
singleton argument, you need to keep the invocations as succinct
as possible, and the test whether the given level is active or
not as fast as possible. This suggests macros (which also allow
automatic insertion of __LINE__ and __FILE__), and some sort of
static variables, rather than a test in an instance functions.
I'll usually use something like:

extern LogStream* logOutput[];

#define LOG(n) logOutput[n] != NULL
&& *logOutput[n] << __FILE__ << ":" << __LINE__

And of course, LogStream can't be a singleton. But the code
which initializes logOutput might be, especially if it has to
wait for external events and possibly update the logOutput
table. And in very large applications, there's likely to be
a logOutput[] instance per subsystem, wrapped in a class, with
a constructor which registers it with a central log manager,
which reads the log configuration when instructed to (since you
can't necessarily shut down the application just to change the
configuration of its log). In such cases, log manager is likely
to be very much like a classic singleton (if only to handle
order of initialization issues).
Depends what it manages. If "configuration" of dynamically
loadable modules then such thing must be there, but i would
call it "application" object (or its "configuration" member).
If these are module settings then these belong to each module.
It is sad that C++ does not contain concept of dynamically
loadable modules.
Command line is passed to main() and so main() passes it to
some singleton? Why it should be a singleton?

Because there can't be more than one command line. Options have
to register before main is called (from the constructor of
a static object), so you need something to handle the order of
initialization issues.
These are command line arguments for something that will be
further called by main(). Why there must be a global singleton
that holds its options?

Because no one component is interested in all of the options.
However that does not worry me, after all there are very few
things that directly depend on command line and that command
line does not likely change during program run.

Not once it has been parsed. But Option enroles with the
CommandLine class, so that it can correctly pick up options when
it parses the command line.
At the moment yes, application (or some framework that it
uses) has to orchestrate shutdown itself. Again, when i do not
get rid of single things then i do not like
"ShutDownManager::instance().doIt()". I prefer to have
shutDown() function. If nothing else then faking it for a unit
test is lot cheaper.

The main argument against this solution is that it doesn't work.
The task manager has to know about all of the tasks, so that it
can signal them in case of a shutdown request, then wait until
they've finished.

(Thinking about it, this seems to be a common theme of
singletons. The have to know about all of the instances of
something else: threads, temporary files, etc.)
No, i meant a namespace, sorry for not being clear there.
debugging::log() like std::sort(). Actually i suggest to wrap
logging into macro anyway. Some useful information like
file/function/ linenumber are impossible to gather in
a generic way without macros involved.

Yes. More generally, however, when single instances of data are
involved, I prefer to wrap in a class than in a namespace. Once
I've defined the class, no one else can get at the data.
 
Ö

Öö Tiib

It's not "global" state:).

Ok, about hidden implementation details i do not usually complain.
Whatever is elegant to get interface contract fulfilled. If it is
singleton most fitting there then so be it.

[...]
Well, logging is a very special case.  

Yes, logging is most valuable debugging/issue resolving tool.
Especially when there are difficulties to debug, like with some
embedded systems. I did bring it in because it is typical thing that i
have heard is a "natural singleton". Seems that we agree there,
natural interface for logging in C++ is a macro. Singletons interface
does not pull the weight. Singleton may be again some behind scenes
implementation detail.

What I hate is when singleton is sort of replacement for a global
variable. That is the cheat how that pattern is often abused.
Because there can't be more than one command line.  Options have
to register before main is called (from the constructor of
a static object), so you need something to handle the order of
initialization issues.


Because no one component is interested in all of the options.

OK, may be it is reasonable. However such options may be passed to
component run-time as well? What is the difference if the source is
command line or some user command to change them later, run-time?
Not once it has been parsed.  But Option enroles with the
CommandLine class, so that it can correctly pick up options when
it parses the command line.

Ok, there is just one command line and pretending there may be several
is pointless when there are no other sources of options.
The main argument against this solution is that it doesn't work.
The task manager has to know about all of the tasks, so that it
can signal them in case of a shutdown request, then wait until
they've finished.

To expose something to a function is actually as hard as to expose it
to a class, isn't it? Ok, task manager. I do not still see why there
must be a class for it.

namespace taskmanager {
void shutDown(); // shortest thing to say.
// other operations with task manager.
}

It might be feels like C way of information hiding, but nameless
namespaces are exactly for that ... like i understand the standard.
Sure, it may be a class too.
(Thinking about it, this seems to be a common theme of
singletons.  The have to know about all of the instances of
something else: threads, temporary files, etc.)

Yes. For example factories. I prefer factory functions when there are
limits so creation (or destruction, or reusage) of something should
not be made in usual ways. How a factory function achieves it is
implementation detail. It may use real singletons that are defined in
(nameless namespace in) translation unit that defines such factory
function.

Such design likely removes (or adds flexibility how to handle) the
issues that may be with construction/destruction order of singletons.
Namespace also naturally does not let any usual questions about
classes (like what if i copy or derive from or use as member or
delete) to be asked with straight face.
[...]
Yes.  More generally, however, when single instances of data are
involved, I prefer to wrap in a class than in a namespace.  Once
I've defined the class, no one else can get at the data.

I believe nameless namespace in a translation unit is deepest place
where single instance of data can be hidden with C++. It may be is my
allergic overreaction to widespread abuse of singletons, so i want to
put them as far from global as possible. ;-)
 
J

James Kanze

[...]
OK, may be it is reasonable. However such options may be passed to
component run-time as well? What is the difference if the source is
command line or some user command to change them later, run-time?

If there is some user command to change them later, then they
aren't command line options. Long running programs don't
normally use command line options (other than the specify the
configuration files); they use configuration files, and if the
user can issue commands to modify the configuration on the fly,
they probably rewrite the configuration file as well. Command
line options are for short running programs, which do one thing
and exit (like a compiler). My options are variables at
namespace scope. Preferrably local to the module in which they
are used. The constructor calls a function in CommandLine which
enrols them.

While convenient at some levels, this solution isn't perfect.
You've still got to find all of those options when it comes to
writing the man page or help text. But globally, I've found it
very useful to be able to define an option in the module which
uses it, without having to modify any central code which "knows"
all of the options.
Ok, there is just one command line and pretending there may be
several is pointless when there are no other sources of
options.

Even when much of the configuration may come from
a configuration file, it's useful to access it through a single
co-ordinator. (I have, or maybe only had, code somewhere which
does this. It's a singleton which maintains a list of
configuration sources; when you ask it for a value, it goes
through the list, returning the first it finds. First in the
list is typically a collection of options, registered with the
command line, followed by an object which reads environment
variables, followed by one or more files, followed by an object
which returns the defaults.)
To expose something to a function is actually as hard as to expose it
to a class, isn't it? Ok, task manager. I do not still see why there
must be a class for it.

It needs to be a container, which can contain a variable number
of entries. Thus, a class. You can use std::vector<Thread*> if
you want, but in that case, you may still want to handle order
of initialization issues, in order to allow threads to be
started from the constructor of a static object. (Not usually
a good idea, but there are probably cases where it is
justified.)
namespace taskmanager {
void shutDown(); // shortest thing to say.
// other operations with task manager.
}

And where do you put the data that taskmanager::shutDown needs
to manipulate? Data which is also accessed each time you start
a thread, etc.
It might be feels like C way of information hiding, but
nameless namespaces are exactly for that ... like i understand
the standard. Sure, it may be a class too.

Unnamed namespaces are only accessible from the translation unit
in which they occur. Something like a thread probably has
a couple of different globally accessible functions; if it's in
library code, each will be in a separate file.
Yes. For example factories. I prefer factory functions when
there are limits so creation (or destruction, or reusage) of
something should not be made in usual ways. How a factory
function achieves it is implementation detail. It may use real
singletons that are defined in (nameless namespace in)
translation unit that defines such factory function.

The classical singleton is nothing more than a factory function.
With the twist that it always returns the same instance, rather
than a new one each time.
Such design likely removes (or adds flexibility how to handle) the
issues that may be with construction/destruction order of singletons.
Namespace also naturally does not let any usual questions about
classes (like what if i copy or derive from or use as member or
delete) to be asked with straight face.
[...]
Yes. More generally, however, when single instances of data are
involved, I prefer to wrap in a class than in a namespace. Once
I've defined the class, no one else can get at the data.
I believe nameless namespace in a translation unit is deepest place
where single instance of data can be hidden with C++.

It's too deep, since only the functions in that one translation
unit can get too it. (Actually, it depends, and in cases where
a helper class or helper functions are only needed in a single
function, I'll put them in the unnamed namespace. I'm also
fairly fond of using namespaces named XxxPrivate, defined in
a local header which isn't exported.)
 
J

Jorgen Grahn

Size or number of developers are no excuse: bad habits are bad habits
period.

I agree with you about size and number of people, but with him on "as
simple as possible". I don't often use global state, but I think it's
a valid design in some cases.

(But people who use it should know about the pitfalls -- for example
how often requirements change so what you believed was global no
longer is, and how bloody hard it can be to rewrite code with global
state.)

/Jorgen
 
Ö

Öö Tiib

  [...]
If there is some user command to change them later, then they
aren't command line options.  Long running programs don't
normally use command line options (other than the specify the
configuration files); they use configuration files, and if the
user can issue commands to modify the configuration on the fly,
they probably rewrite the configuration file as well.  Command
line options are for short running programs, which do one thing
and exit (like a compiler).  My options are variables at
namespace scope.  Preferrably local to the module in which they
are used.  The constructor calls a function in CommandLine which
enrols them.

While convenient at some levels, this solution isn't perfect.
You've still got to find all of those options when it comes to
writing the man page or help text.  But globally, I've found it
very useful to be able to define an option in the module which
uses it, without having to modify any central code which "knows"
all of the options.

Ok, i have used a bit different way. Each option is mapped to command
(function or functor). As options are parsed the commands are
executed. That results with command line being parsed, passed around
and forgotten immediately. Same commands can be executed later by
other means for some reason an option has to be changed. At same place
where commands are there may be little help texts and hints if needed.
At simplest case it is static constant array in some nameless
namespace.

Probably it is because i like somewhat extended interface for command
line application ...
If some mandatory option was missing from command line then program
may ask for it (instead of telling it was error).
When no options were given at all it may enter into interactive mode
(instead of telling about typical usage with few lines).
Such twists are not too uncommon and make testing it simpler.
Even when much of the configuration may come from
a configuration file, it's useful to access it through a single
co-ordinator.  (I have, or maybe only had, code somewhere which
does this.  It's a singleton which maintains a list of
configuration sources; when you ask it for a value, it goes
through the list, returning the first it finds.  First in the
list is typically a collection of options, registered with the
command line, followed by an object which reads environment
variables, followed by one or more files, followed by an object
which returns the defaults.)

It is difficult to achieve if there are components written by third
parties. It is bit easier to equip them with an interface how to add
command line commands. If keeping handling configuration files must be
centralized then i prefer to provide a simplest interface:

namespace configuration
{
void read( ModuleID id, vector<char>& bytes );
void write( ModuleID id, vector<char> const& bytes );
}

Simplest interfaces are simplest to extend. I may handle it as ini or
xml file, for me it is set of bytes i preserve in exact form. When all
modules are mine then of course it is cheaper to have some extended
interface so each configurable value can retrieved from common tree
(or its branch).
It needs to be a container, which can contain a variable number
of entries.  Thus, a class.  You can use std::vector<Thread*> if
you want, but in that case, you may still want to handle order
of initialization issues, in order to allow threads to be
started from the constructor of a static object.  (Not usually
a good idea, but there are probably cases where it is
justified.)

There are so many possible ways how to handle and manage concurrency.
I think there are at least 4 major ways plus endless subtypes. Some,
(like OpenMP) make it business of implementation others deal with
threads very closely and explicitly. I do not think that any of them
does start threads from constructors of static objects, but who knows.
And where do you put the data that taskmanager::shutDown needs
to manipulate?  Data which is also accessed each time you start
a thread, etc.

Why not in some personal vector of taskmanager? Everyone has to give
their tasks to taskmanager without knowing how many threads for the
job there is. Is it some other model of concurrency? Yes, some things
may need specific thread. For example OpenGL is AFAIK implemented so
that you can draw to one display from only one thread and no other
thread. However presence of such threads may be also consulted (with
some special function) to taskmanager.
Unnamed namespaces are only accessible from the translation unit
in which they occur.  Something like a thread probably has
a couple of different globally accessible functions; if it's in
library code, each will be in a separate file.

Thread is not like object for me. It is more like running function
(activity). Threads usually communicate with messages or signals.
Basic functionality function of receiving messages and accepting jobs
to do and reporting back about problems may be same for all threads.
On that case also the place from where they get their tasks may be
centralized and be located at same place the function is implemented.

The tasks that thread does may have some other mechanics for canceling
them on half run, for example they may get some signal interface to
attach and observe. That really needs whole separate newsgroup about
how to implement concurrency in C++; there probably are some in
usenet.
The classical singleton is nothing more than a factory function.
With the twist that it always returns the same instance, rather
than a new one each time.

I believe it is bad twist and does not fit too well into C++ where you
may have free functions. Every time i see one it feels like
"std::sorter::instance().sort(from, to)". When it is surely same
object of whose member functions i call then i prefer to not have that
object on table at all. With that object i may anyway do nothing but
call its member functions. So ... plain set of functions is fine.
There may be case when i need to extract an interface from it to pass
into somewhere that expects such interface. Then i prefer to have
function that provides such interface, why should caller know if it is
whole singleton itself or some data member of it? If there are chances
that there may be more instances than one then i see reason for
factory function. However "instance()" is a bad name for a factory
function.
Such design likely removes (or adds flexibility how to handle) the
issues that may be with construction/destruction order of singletons.
Namespace also naturally does not let any usual questions about
classes (like what if i copy or derive from or use as member or
delete) to be asked with straight face.
 [...]
Yes.  More generally, however, when single instances of data are
involved, I prefer to wrap in a class than in a namespace.  Once
I've defined the class, no one else can get at the data.
I believe nameless namespace in a translation unit is deepest place
where single instance of data can be hidden with C++.

It's too deep, since only the functions in that one translation
unit can get too it.  (Actually, it depends, and in cases where
a helper class or helper functions are only needed in a single
function, I'll put them in the unnamed namespace.  I'm also
fairly fond of using namespaces named XxxPrivate, defined in
a local header which isn't exported.)

Usually it is not too deep. Then i win. Often singleton was there
before, hiding it away is expensive and i likely have more packing
issues to handle. Then it won. For now. :D But namespace is seriously
best singleton interface since i can have such separate ("internal"
like in C#) interface in other header, whole namespace does not have
to be declared in one header unlike a class.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top