[...]
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.
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.