Objective Toolkit : Chapter 16 Utility Classes : Safe Multi-Threaded Trace Output
Safe Multi-Threaded Trace Output
Objective Toolkit now includes support for safe, synchronized logging of trace-type output from within multi-threaded code. Using objects derived and instantiated from the base template class MultiTrace, developers of multithreaded applications can implement synchronized output from multiple threads to a common text file. Features of this class include:
Optional synchronization. The base MultiTrace class is a template that takes as one of its parameters a trait or behavior class into which the synchronization behavior has been factored. Implementations of this trait have been provided for both single and multi-threaded behaviors; so, for example, if you instantiate from base class MultiTrace using trait class SingleThreadLogTraits as a parameter, synchronization is disabled. However, if you instantiate using trait class MultiThreadLogTraits as a parameter, synchronization is enabled. In the header file, we have provided simple typedefs for each of these choices. If some other type of behavior is desired, the user has the option of deriving and using a custom trait class.
Printf-type syntax. Client code invokes methods on the multithreaded logging object using familiar syntax (i.e. format string followed by a variable list).
Optional and configurable tags for log output. Users have the option of specifying tags that appear before and after each piece of log output. A default tag style is provided that includes thread ID and the time (hour:minute:second:millisecond) of the output.
Optional file size threshold. A size (character count) can be specified for the logging object, which represents a count after which file output restarts back at the top. This will be convenient for applications that run unattended, as it will prevent the output file from growing indefinitely.
Optional base64 conversion of binary data. Binary data may be base64 converted into printable text before being written to the output stream.
Optional exception handling. By default, exceptions arising from trace log operations are NOT thrown back to client code. This will probably be the preferred mode for production applications. However, exception handling can be turned on so that exceptions within the logging code are thrown back to the client.
Use of the Multi-Threaded Logging Class
Using the logging class is straightforward.
1. Include these two files:
MultiTrace.h
MultiTraceException.h
2. Declare an instance of the MultiTrace class:
 
multithreadedlogger mt;
This should have file scope. Note that this declaration uses one of the typedefs from MultiTrace.h, which is synonymous with:
 
MultiTrace<MultiThreadLogTraits> mt;
NOTE >> As mentioned above, a non-synchronizing, single-threaded version is provided also, typedefed as singlethreadedlogger.
3. Set the desired properties of the logger, and call initialize():
 
mt.fname=_T(“c:\logfile.txt”);
mt.initialize();
4. In your thread procedure where you desire to log output, invoke an output method:
 
mt.LogWrite(_T(“At this point, the value of x is %i”),x);
By default, this output will be bracketed in the output file by HTML-like tags, which incorporate the thread ID and the time (to the millisecond):
 
<25c 15:24:10.0024> At this point, the value of x is 4 </25C>
The MultiTrace object will perform the file I/O operations in a critical section so that I/O from multiple threads in your application will be properly sequenced in the output stream.
Binary data can be logged as well (converted to text via base64 conversion) through method LogBinary(). Arguments for this method are a pointer to the item and its length. For example, assume oStructure is a data structure in memory. The following code will convert the contents of the structure via base64 conversion and output them to the log file:
 
Mt.LogBinary((void*)&oStructure,sizeof(oStructure));
This will produce output resembling the following:
 
<16c 15:24:09.0703>UAAZAAAAAAAHAAAAAABPABgAUAAZAA==</16c>
When your MultiTrace object falls out of scope, its destructor will be called, which in turn will close the output file and free up any buffers allocated for the purpose of base64 conversion of binary data.
See the MultiThreadLog sample console application (sample\toolkit\MFC\utility) included with the product for an example of the setup and use of the multithreaded logging class.
NOTE >> This class has no dependencies on MFC.