Threads Module User's Guide : PART III Foundation Packages : Chapter 6 The Execution Tracing Package : Using Trace Filters : Chaining Multiple Filters
Chaining Multiple Filters
Instead of using only one filter attached directly to the trace manager, you can chain together several filters. To connect them, use the downstream filter’s connect() member function and pass it the upstream filter as an argument, similar to this:
 
myMultiFilter2.connect(myMultiFilter1);
Creating User-defined Filters
Creating a user-defined filter follows the same pattern as creating a user-defined client. You must create a derived body class, where you specify the rules for filtering. If your filter’s body class has any new public members (in addition to those inherited from its base classes), you must also create a corresponding derived handle class. The predefined Trace Level filter was created in the same way that you would create your own filter, so the source code for RWTraceLevelFilter and RWTraceLevelFilterImp is an example.
Creating the Filter’s Body Class
The filter's implementation must derive from RWTraceSingleClientFilterImp, for a single-client filter, or RWTraceMultiClientFilterImp, for a multiple-client filter.
The doTrace() function. You specify the rules for filtering by redefining the doTrace() member function, which is inherited from RWTraceEventClientImp. The RWTraceEventClientImp::doTrace() function is declared pure-virtual, so a derived body class must provide an implementation of this function.
For a single-client filter, check that the event meets your filter’s criteria and forward it to the connected client, using the trace() member function. Example 56 is taken from the source code for RWTraceLevelFilterImp.
Example 56 – Creating a single-client filter
void
RWTraceLevelFilterImp::doTrace(const RWTraceEvent& ev) {
if (getClient() && (level_ >= ev.getSeverity()) )
getClient()->trace(ev);
}
 
For a multi-client filter, iterate over the connected clients and selectively forward the trace events, based on your filter's criteria. Example 57 is taken from the source code for RWTraceMultiClientFilterImp.
Example 57 – Creating a multi-client filter
void
RWTraceMultiClientFilterImp::doTrace(const RWTraceEvent& ev) {
{
RWGUARD(getMutex());
 
for(unsigned i=0; i < clientPs_.length(); i++ )
clientPs_(i)->trace(ev);
}
}
NOTE >> Do not embed trace macros in the filter’s trace event processing code. To prevent infinite recursion, the trace manager ignores any trace events generated by a filter.
The static make() function. If you are using the predefined handle class, your body class must supply a static make() function. (If you are creating a derived handle class, you can skip to “Creating the Filter’s Handle Class”.) The make() function constructs a body and returns a handle to it. This example is taken from the source code for RWTraceLevelFilterImp.
Example 58 – Creating a filter body class to use with the predefined handle class
RWTraceSingleClientFilter
RWTraceLevelFilterImp::make(RWTraceEventSeverity level) {
 
return new RWTraceLevelFilterImp(level);
}
NOTE >> The returned handle's type is actually the parent class of your derived handle.
Creating the Filter’s Handle Class
If your filter’s body class has any new public members (in addition to those inherited from its base classes), you must create a derived handle class that forwards those calls to your body. Derive your handle from RWTraceMultiClientFilter, for a multiple-client filter, or RWTraceSingleClientFilter, for a single-client filter. For an example, see the source code for RWTraceLevelFilter:
Instantiating Your Derived Filter
If you created your own derived handle class, you can instantiate your derived filter like this:
 
MyMultiClientFilter myMultiFilter;
 
If you did not create your own derived handle class, you must explicitly instantiate a body with your body class’s make() function and pass the body to a handle of type RWTraceEventFilter, as shown in this example:
 
RWTraceEventFilter myTraceFilter ( Test2TraceFilterImp::make() );
Use your filter as you would any predefined filter, as discussed in “Using the Predefined Filters”.