// MultThread.cc -- Illustration of using the basic features of // ThreadSafeErrorLogger mechanism with multiple threads. // // This example program is in three logical pieces: // // First we show the user code -- many physicist users could contribute // code of this nature, using errlog in the manner shown. // // Then we show the program run as each thread. // // Then we show the framework code that would support this. // // Look for // <------ *** to see the modifications // and for // <====== to see how the threading is done. // ----------------- // Physicsists' Code // ----------------- #include "MultThread.h" // <------ *** #include "ErrorLogger/ThreadSafeErrorLog.h" // <------ *** void DoPhysics::operator()( Event & event ) { // THIS METHOD IS WHERE ALL THE PHYSICS CALCULATION WOULD GO. errlog( ELsuccess, "An Event" ) << "data = " << event.data << "processed by thread" << threadNumber << endmsg; if ( event.data == 9 ) { errlog( ELerror, "Ninth Event" ) << endmsg; } // I don't like event number 9. int sum = 0; for (int i = 1; i <= event.data; i++) { sum += i*(event.data+i); if (sum > 100) { errlog( ELwarning, "Big Sum" ); errlog << "event " << event.data; errlog << " i = " << i; errlog << " sum = " << sum; errlog << "From thread " << threadNumber << endmsg; break; } } } // DoPhysics::operator()(event) // --------------- // Thread Code // <====== // --------------- #include "ZMutility/iostream" USING( std::cout ) #include pthread_mutex_t mutex_; pthread_mutex_t* mutex; int threadNum; extern "C" {typedef void*(*cprog)(void*);} void * threadProgram (void *v) { int tnum; // Decide a thread number -- there may be a better way than this! { Mutex LOCK; tnum = ++threadNum; } std::ostringstream s; s << "Thread-" << tnum; DoPhysics doPhysics( s.str(), tnum ); int n; for ( n = 1; n < 20; ++n ) { Event event( n ); doPhysics( event ); } return 0; } // --------------- // Framework Code // --------------- #include "MultThread.h" // <------ *** // These are the ErrorLogger classes used by the typical framework: #include "ErrorLogger/ELadministrator.h" #include "ErrorLogger/ELdestControl.h" #include "ErrorLogger/ELoutput.h" #include "ErrorLogger/ELstatistics.h" #include "ZMutility/iostream" USING( std::cout ) Module::Module( const std::string & name ) { errlog.setModule(name); } Module::~Module( ) { } Mutex::Mutex() { // <====== int status = pthread_mutex_lock(mutex); if (status) cout << "pthread_mutex_lock returned status = " <attach(logfileD) ); // tell logger about it logfile.setThreshold ( ELsuccess ); // ignore messages below // ELsucess ELoutput outputD( cout ); // another ELdestination ELdestControl output ( logger->attach(outputD) ); // tell logger about it output.setThreshold ( ELerror ); // ignore messages below // ELerror ELstatistics statsD( cout ); // a statistics dest ELdestControl stats ( logger->attach(statsD) ); // tell logger about it // Here is where we set up the threading: // -------------------------------------- // Make a mutex: mutex = &mutex_; pthread_mutexattr_t mattr_; pthread_mutexattr_t *mattr = &mattr_; int status = pthread_mutex_init(mutex, mattr); if (status) cout << "pthread_mutex_init returned status = " <