From: Darryl Green (darryl.green_at_[hidden])
Date: 2004-10-29 22:53:20
Beman Dawes <bdawes <at> acm.org> writes:
> But a dependency on any thread library is likely to throw cold water on my
> use. Here are the likely scenarios:
> * Light-duty uses in light-duty non-multithreaded programs, where
> introducing a threading dependency seems far too heavy-weight for the apps.
There really isn't one in this case - see below.
> * Heavy-duty industrial uses. I'm not adverse personally to a threading
> library dependency for these apps (which are sold as libraries); , but I'd
> have to get permission from managers who will be very concerned about use
> of a threading library clashing with customer's use of other threading
> libraries. Whether these concerns are valid or not is almost beside the
> point; it will be a hassle.
The library actually supports overriding the types used for logging including
the threading primitives used, which (unless you use the ts_appender) is only
a simple mutex and corresponding scoped lock class. So you should be able to
keep those managers happy by using/wrapping other mutex/lock classes.
> ... it would be nice if there was a basic subset
> of features that could be used without threading concerns.
There is. Much of this can be addressed by better docs, but there is still some
level of flux in how the internals (including the types exposed to allow
alternative implementations to be assembled) fit together, so detailed docs on
the architecture might take a while to arrive. In the meantime:
The lib can be broken down into:
1) The logger itself. Each log has a collection of appenders and modifiers and
an enabled state.
2) A manager that maintains collections of loggers, appenders, modifiers,
enabled state and provides methods for changing the logging settings.
3) A collection of appender and modifier functions.
Each logger has a mutex to protect its state.
The log manager uses a mutex to serialise updates.
It still needs to be resolved how the actual writing (calling of modifiers and
appenders) should occur in a multithreaded environment. I think it should be
done with no lock held by the logger (or the manager). In that case the
appender and modifier functions need to be threadsafe (reentrant) so stateful
functors may need to use some form of locking. Note that that isn't how the lib
is at present - the log manager lock is held during writing.
In all the above, in a single threaded build, a null mutex type is used.
There is also the case of appenders, such as the ts_appender, which internally
use boost.thread, and that can only possibly run in a multithreaded environment.
FYI, the manager is a concept, which curently has 1 implementation. The concept
probably needs a bit of refinement (and docs), but the key point is that
alternate managers can be used if needed. Other types, including the "string"
and "stream" types can also be replaced. It should be possible to build at
least the following logging systems with the library:
1) The lib as presented so far.
2) A very simple logging facility, with an essentially null manager - just
providing an interface to manually bolt together loggers and
appenders/mutators. One form of this might be a logging facility that can only
have its settings changed (eg read from a file) by an app restart, in which
case even in a multithreaded app most locking can be eliminated.
3) Something quite radically different such as a log where the "stream" is
something into which structured log information can be assembled, and
the "string" carries that information to appenders that use that structured
information (format it for textual output, write it to a database table...).
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk