A mechanism for recording of textual information pertaining to an error is provided by the OTC_Logger class. Error messages can be logged at a number of priorities, with messages being displayed to the standard error output. If required, error messages can also be saved to a file.
By deriving from the OTC_Logger class you can capture the error messages and optionally save or cause them to be displayed using an alternate mechanism. For example, you may wish to have messages passed on to the UNIX syslog facility.
When messages are passed to the OTC_Logger class, they must have been preformatted. You could preformat messages using the sprintf() function or the ostrstream class. An alternative mechanism, is to use the OTC_LogStream class. This class provides a streams style interface for logging of messages. Messages will automatically be passed to the OTC_Logger class on the completion of each line of output.
If needing to output the name of the code file, and line in the code file from which a message is being generated, the OTCLIB_WARNING() macro is available.
Not all C++ compilers yet provide the exception facility. To make code portable between C++ compilers which do and do not provide the exception facility, raising of exceptions is hidden behind a set of macros and functions. If the C++ compiler supports exceptions, a true exception will be thrown. When a C++ compiler does not implement exceptions, the terminate() and set_terminate() functions are provided. When an exception needs to be raised it is handled as though it were not caught and thus the terminate() function is called to the halt the application.
The macros for raising of exceptions are OTCLIB_EXCEPTION(), OTCLIB_ASSERT() and OTCLIB_ENSURE(). When true exceptions need to be raised, the exception types which are thrown are OTC_Exception, OTCERR_AssertionFailure and OTCERR_PreconditionFailure. In addition to these, the OTCERR_OutOfMemory exception type exists for signalling of an out of memory condition. When the exception facility is not available, information about an exception will be displayed using the OTC_Logger class prior to the terminate() function being called.
When an exception occurs, and the stack unwound, only destructors for objects created on the stack are invoked. If you had created an object using operator new(), and only held a pointer to that object via a stack variable, the object will not be destroyed, resulting in a memory leak. Three different classes are provided to assist in ensuring that objects allocated using operator new() or malloc() are destroyed when an exception occurs. These classes are OTC_Reaper, OTC_VecReaper and OTC_MallocReaper.
Using two supplied macros, OTCLIB_MARKBLOCK() and OTCLIB_TRACER(), debugging information can be tagged with different levels indicating verbosity. How much information is displayed, based on that tag, can be specified when the program is run. The macros also allow debugging code to be conditionally compiled into code without the need for unsightly `#if' preprocessor checks.
When related objects of a specific type are all to be deleted at the same time, it is possible to cluster those objects together into a single block of memory. This ability is provided by the OTC_Cluster and OTC_MCObject classes. Allocation of memory for clustered objects is handled by the OTC_Arena class. The OTC_Arena class may also be used directly to implement other memory allocators as may be the OTC_Heap class. The difference between these two classes being that memory from the OTC_Arena class must all be deleted at the same time. With the OTC_Heap class, selected blocks of memory may be returned to the heap class for reuse.
When creating memory allocators, correct alignment of memory is important. To assist in determining the alignment requirements of the builtin types and pointers the OTC_Alignment class is provided. An alternative to writing specialised memory allocators is to avoid, if possible, the creation of objects unless they are actually accessed by an application. Implementation of this approach to reducing memory use is assisted by the OTC_Ptr and OTC_VecPtr classes.
One scheme for which support is provided for is the technique of reference counting. Through either automatic or manual means, the number of parties interested in a specific object is recorded. When no parties are interested in the object, the object may be deleted. The class underlying this mechanism is OTC_Resource. This class provides a manual mechanism for performing reference counting. The mechanism can be partially automated by using the smart pointer class OTC_CResPtr and OTC_ResPtr.
The OTC_Resource class works through the reference count being embedded within the object of interest. If the class for the object cannot be modified, or you wish to perform reference counting on builtin types or arrays of objects, the classes above cannot be used. For these cases, alternative smart pointer classes are provided which maintain the reference count external to the object. These classes are OTC_CCtrPtr, OTC_CtrPtr, OTC_CCtrVecPtr and OTC_CtrVecPtr. For all of the above classes, the object of interest must have been created on the free store using `operator new()'.
There are two principal classes provided for use in place of C strings. These classes are OTC_String and OTC_Symbol. Both classes provide you with the ability to store character strings containing embedded null characters. Both will also place a null guard byte at the end of the string, in case there is no explicit null terminator. The addition of the null terminator allows the string to be used where C strings would have been used.
In addition to the two main classes, a number of support classes exist. For string type objects where derivation from OTC_String is not a viable option, the OTC_SObject class exists. When used as a base class, this allows your classes to be used nearly everywhere that OTC_String can be passed as argument, but doesn't give access to the string for editing.
Both OTC_String and OTC_Symbol are internally implemented using OTC_RString. This class encapsulates the delayed copy and buffering mechanisms. The OTC_Length and OTC_Capacity classes exist to provide a means of specifying the length and/or capacity of a string at the time of creation. In addition, the OTC_CString class is provided to allows strings to be easily created which only use as much memory as they need. That is, the buffering mechanism is bypassed at the point the string is created.
A final class, OTC_TString, exists to allows the OTC_String class to have an automatic conversion operator for the type `char const*', but still provide a measure of safety for addition of strings using an overloaded `operator+()'. The problem being avoided being that of the lifetime of the string returned by `operator+()' when the result is saved as a pointer of type `char const*'.
For those instances where it would be valid to access this information, a number of classes are provided to make access to the information consistant, and to also assist in manipulating that information. The class provided to assist in manipulating command line options, obtained from any source, is the OTC_Options class. The classes provided for making access to the programs arguments consistant, are the OTC_Program and OUX_Program classes.
A solution often adopted is to write the application in the style of an event driven system. That is, something happening and to which a task should respond, is modelled as an event. The event is put together by a central thread of control, with then event and thread of execution being handed over to the appropriate task. It is now the tasks job to deal with that event and subsequently return the thread of execution back to the executive or dispatcher.
The class which gives over control to each of the tasks when an event for that task arrives is OTC_Dispatcher. To implement simulation type systems, the OTC_Job class is also provided. At a higher level, the OTC_EVAgent and OTC_Event classes are provided for implementing event based systems. The underlying job queue used by the dispatcher is OTC_JobQueue. This class is extended by OUX_JobQueue and OTK_JobQueue to handle real time events within the UNIX operating system. The latter of of these also handles the TK GUI library. The types of events which can be used when using the job queues supporting real time semantics are OTCEV_Action, OTCEV_Alarm, OTCEV_Timeout, OTCEV_IOEvent and OUXEV_Signal.