Logging is thread-safe

quarks::service::Logger now takes a Semaphore during the call to LoggerImpl::send() so that log messages from different tasks don't get mixed together. Class LoggerImpl is much simplified in that all formatting, severity level filtering and synchronization are done elsewhere.

Checking the severity level threshold

Logger().aboveThreshold(severity-level) will return true if messages of level severity-level are being logged. This allows you to skip debug-printout code that's more complex than a simple series of logging calls.

Piecewise assembly of log messages.

Class quarks::service::LogMessage may be used to assemble a log message a piece at a time instead of all in one logging call. The accumulated message is sent when the LogMessage instance being used is destroyed. This may happen at the end of a statement (temporary instance) or at the end of a code block (named instance).

New way to initialize and shut down logging

In a module's main function construct an instance of quarks::service::InitLogging on the stack instead of calling Logging::initLogging() directly. When the function exits then logging will be gracefully shut down. An example of Resource Allocation Is Initialization (RAII).

New package: concurrency

These are tools and data structures used in aid of thread-safe programming. The first class added is CriticalSection, whose constructor takes a given Semaphore and whose destructor gives that semaphore, thereby creating a critical section that lasts as long as the instance does. Another example of RAII.

New package: datastructures

These are non-concurrent data structures. BitSet is a classic powerset defined in an unsigned int (32 bits). BitPq is a priority queue that returns in ascending order the bit positions of all the bits set in a Bitset.

New PDF documentation

A new version of quarks.pdf is attached to the Petacache Documentation page in Confluence.