Trace clients process trace event information, pass it on to another client, or both. Only one client can receive event messages directly from the trace manager. If you need multiple clients with different behavior, see the discussion of filters in Section 6.8.
The Execution Tracing package provides one predefined client RWTraceOstreamClient. To instantiate the client, use code similar to this:
#include <rw/trace/trace.h> . . . RWTraceOstreamClient myTraceClient(cerr);
The RWTraceOstreamClient sends output to any ostream specified to its constructor, such as cerr in the above example. This code comes from the example in Section .
After instantiation, connect the client to the trace manager using the client's connectToManager() member function:
myTraceClient.connectToManager();
To connect the client to another filter, use the client's connect() member function and pass it the filter as an argument:
RWTraceMultiClientFilter myMultiFilter; myTraceClient.connect( myMultiFilter );
See Section 6.8 for the discussion of filters.
If you need a client to do something more exotic than send trace output to an ostream, you need to define your own trace client class. For example, you could send the trace data out over a socket or perhaps over a serial line for remote debugging. The example in this section simply adds a timestamp to each trace message before sending it to an ostream.
NOTE: Do not embed trace macros in the client's trace event processing code. To prevent infinite recursion, the trace manager ignores any trace messages generated by a client.
Figure 31 shows the trace client classes. Like other Threads.h++ packages, the Execution Tracing package uses the handle-body idiom. For example, an RWTraceOstreamClient object is a handle to an RWTraceOstreamClientImp instance, which actually processes the trace messages. RWTraceOstreamClient and RWTraceOstreamClientImp together form a complete client.
To create your own trace client, you must supply a new implementation derived from the body class RWTraceEventClientImp. If your client's body class has any new public member functions (in addition to those inherited from RWTraceEventClientImp), you also need to create a new handle class that forwards those calls to your body. The handle must be derived from RWTraceEventClient.
The RWTraceEventClientImp::doTrace() function, which actually processes the trace events, is declared pure-virtual, so a derived body class must provide an implementation of this function. If you do not create your own derived handle class, the body class must also supply a static make() function. The function constructs a body and returns a handle to it, similar to Example 54.
static RWTraceOstreamClient make(RW_SL_IO_STD(ostream)&
ostr = RW_SL_IO_STD(cerr)) { return new TimeStampClientImp(ostr); }
NOTE: The returned handle's type is actually the parent class of your derived handle.
The above code is from examples\thr0200osfam\trace\example4.cpp, which shows how to create a client both ways, with or without a derived handle.
Example 55 provides an implementation for the pure-virtual function doTrace() in a class derived from RWTraceEventClientImp. The code is taken from examples\thr0200osfam\trace\example4.cpp. In this example, the class derives from RWTraceOstreamClientImp, which already has most of the necessary behavior. Only the doTrace() function is modified to provide timestamping.
#include <rw/rwtime.h> . . . // Override our parent's doTrace member. void TimeStampClientImp::doTrace(RWTraceEvent& ev) { RWTime now; RWCString time( now.asString("%H:%M:%S")); { // Acquire a lock so we can output safely. RWGUARD(getMutex()); getOstream() << time << "|" << ev.getFileName() << "|" << ev.getLineNumber() << "|" << ev.getResourceId() << "|"; // If an object generated this event, output its address. if (ev.getThisPtr()) getOstream() << ev.getThisPtr() << "|"; getOstream() << ev.getSeverity() << "> " << ev.getMessage() << endl; } } };
In Example 56 the derived client shown in Example 55 is given the ability to record which thread produced the trace events. The code is taken from one of the Threads package examples, examples\thr0200osfam\thread\trace.cpp.
#include <rw/trace/trace.h> #include <rw/rwtime.h> // for RWTime #include <rw/sync/RWThreadId.h> // for rwThreadId() ... class TimeStampClientImp : public RWTraceOstreamClientImp { public: // The static make function constructs a body, and returns a
// handle to it. Note: the returned handle's type is actually
// the parent class of our handle. static RWTraceOstreamClient make(RW_SL_IO_STD(ostream)&
ostr = RW_SL_IO_STD(cerr)) { return new TimeStampClientImp(ostr); } protected: // Default constructor. TimeStampClientImp(void) { } // A constructor that takes an ostream. TimeStampClientImp(RW_SL_IO_STD(ostream)& ostr) : RWTraceOstreamClientImp(ostr) { } // Override our parent's doTrace member. virtual void doTrace(const RWTraceEvent& ev) { RWTime now; RWCString time( now.asString("%H:%M:%S")); unsigned threadID = rwThreadHash( rwThreadId() ); { // Acquire a lock so we can output safely. RWGUARD(getMutex()); getOstream() << time << "|" << "TID:" << threadID << "|" << ev.getFileName() << ":" << ev.getLineNumber() << "|" << ev.getResourceId() << "|"; // If an object generated this event, output its address. if (ev.getThisPtr()) getOstream() << ev.getThisPtr() << "|"; getOstream() << ev.getSeverity() << "> " << ev.getMessage() << RW_SL_IO_STD(endl); } } };
To use your client, assuming you created a derived handle, instantiate the handle and connect it to the trace manager:
MyDerivedClient myTraceClient;
myTraceClient.connectToManager();
or connect it to another filter:
myTraceClient.connect(myMultiFilter);
If you did not create your own derived handle class, you must supply a static make() function (see Section 6.7.2). To use your client, instantiate a body with your client's make() function and pass it to a handle of type RWTraceEventClient. Then connect the client handle to the manager or a filter:
RWTraceEventClient myTraceClient( TimeStampClientImp::make() ); myTraceClient.connectToManager();
©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.