Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:30:15

0001 // -*- C++ -*-
0002 //
0003 // Package:     SimG4Core/Application
0004 // Class  :     ThreadHandoff
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Christopher Jones
0010 //         Created:  Mon, 16 Aug 2021 14:37:29 GMT
0011 //
0012 
0013 // system include files
0014 
0015 // user include files
0016 #include "SimG4Core/Application/interface/ThreadHandoff.h"
0017 #include "FWCore/Utilities/interface/Exception.h"
0018 #include <array>
0019 
0020 //
0021 // constants, enums and typedefs
0022 //
0023 
0024 namespace {
0025   std::string errorMessage(int erno) {
0026     std::array<char, 1024> buffer;
0027     strerror_r(erno, &buffer[0], buffer.size());
0028     buffer.back() = '\0';
0029     return std::string(&buffer[0]);
0030   }
0031 }  // namespace
0032 //
0033 // static data member definitions
0034 //
0035 
0036 //
0037 // constructors and destructor
0038 //
0039 using namespace omt;
0040 
0041 ThreadHandoff::ThreadHandoff(int stackSize) {
0042   pthread_attr_t attr;
0043   int erno;
0044   if (0 != (erno = pthread_attr_init(&attr))) {
0045     throw cms::Exception("ThreadInitFailed")
0046         << "Failed to initialize thread attributes (" << erno << ") " << errorMessage(erno);
0047   }
0048 
0049   if (0 != (erno = pthread_attr_setstacksize(&attr, stackSize))) {
0050     throw cms::Exception("ThreadStackSizeFailed")
0051         << "Failed to set stack size " << stackSize << " " << errorMessage(erno);
0052   }
0053   std::unique_lock<std::mutex> lk(m_mutex);
0054 
0055   erno = pthread_create(&m_thread, &attr, threadLoop, this);
0056   if (0 != erno) {
0057     throw cms::Exception("ThreadCreateFailed") << " failed to create a pthread (" << erno << ") " << errorMessage(erno);
0058   }
0059   m_loopReady = false;
0060   m_threadHandoff.wait(lk, [this]() { return m_loopReady; });
0061 }
0062 
0063 // ThreadHandoff::ThreadHandoff(const ThreadHandoff& rhs)
0064 // {
0065 //    // do actual copying here;
0066 // }
0067 
0068 ThreadHandoff::~ThreadHandoff() {
0069   if (not m_stopThread) {
0070     stopThread();
0071   }
0072   void* ret;
0073   pthread_join(m_thread, &ret);
0074 }
0075 
0076 //
0077 // assignment operators
0078 //
0079 // const ThreadHandoff& ThreadHandoff::operator=(const ThreadHandoff& rhs)
0080 // {
0081 //   //An exception safe implementation is
0082 //   ThreadHandoff temp(rhs);
0083 //   swap(rhs);
0084 //
0085 //   return *this;
0086 // }
0087 
0088 //
0089 // member functions
0090 //
0091 
0092 //
0093 // const member functions
0094 //
0095 
0096 //
0097 // static member functions
0098 //
0099 void* ThreadHandoff::threadLoop(void* iArgs) {
0100   auto theThis = reinterpret_cast<ThreadHandoff*>(iArgs);
0101 
0102   //need to hold lock until wait to avoid both threads
0103   // being stuck in wait
0104   std::unique_lock<std::mutex> lck(theThis->m_mutex);
0105   theThis->m_loopReady = true;
0106   theThis->m_threadHandoff.notify_one();
0107 
0108   do {
0109     theThis->m_toRun = nullptr;
0110     theThis->m_threadHandoff.wait(lck, [theThis]() { return nullptr != theThis->m_toRun; });
0111     theThis->m_toRun->execute();
0112     theThis->m_loopReady = true;
0113     theThis->m_threadHandoff.notify_one();
0114   } while (not theThis->m_stopThread);
0115   theThis->m_loopReady = true;
0116   return nullptr;
0117 }