Belle II Software  release-08-01-10
PThread.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #ifndef _Belle2_PThread_hh
9 #define _Belle2_PThread_hh
10 
11 #include <daq/slc/system/LogFile.h>
12 
13 #include <pthread.h>
14 #include <signal.h>
15 #include <cstdio>
16 
17 namespace Belle2 {
23  class PThread {
24 
25  private:
26  template<class WORKER>
27  static void destroy(void* arg)
28  {
29  WORKER* worker = (WORKER*)arg;
30  delete worker;
31  worker = NULL;
32  }
33  template<class WORKER>
34  static void* create_destroy(void* arg)
35  {
36  WORKER* worker = (WORKER*)arg;
37  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
38  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
39  pthread_cleanup_push(PThread::destroy<WORKER>, arg);
40  try {
41  worker->run();
42  } catch (const std::exception& e) {
43  LogFile::fatal(e.what());
44  }
45  pthread_cleanup_pop(1);
46  return NULL;
47  }
48  template<class WORKER>
49  static void* create(void* arg)
50  {
51  WORKER* worker = (WORKER*)arg;
52  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
53  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
54  try {
55  worker->run();
56  } catch (const std::exception& e) {
57  LogFile::fatal(e.what());
58  }
59  return NULL;
60  }
61 
62  public:
63  static void exit() { pthread_exit(NULL); }
64 
65  public:
66  PThread() : m_th(0) {}
67  template<class WORKER>
68  PThread(WORKER* worker, bool destroyed = true, bool detached = true, [[maybe_unused]] const std::string& thread_name = "")
69  {
70  m_th = 0;
71  if (destroyed) {
72  if (pthread_create(&m_th, NULL, PThread::create_destroy<WORKER>,
73  (void*)worker) != 0) {
74  m_th = 0;
75  }
76  } else {
77  if (pthread_create(&m_th, NULL, PThread::create<WORKER>,
78  (void*)worker) != 0) {
79  m_th = 0;
80  }
81  }
82 #if (defined(__GLIBC__) && defined(__GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 12)
83  if ((m_th != 0) && (thread_name != "")) {
84  try {
85  if (pthread_setname_np(m_th, thread_name.c_str()) != 0) {
86  LogFile::info("Failed to set process name %d", m_th);
87  }
88  char comp_name[64];
89  pthread_getname_np(m_th, comp_name, 16);
90  if (strcmp(thread_name.c_str(), comp_name) != 0) {
91  prctl(PR_SET_NAME, thread_name.c_str());
92  }
93  } catch (const std::exception& e) {
94  LogFile::error(e.what());
95  }
96  }
97 #endif
98  if (detached) {
99  detach();
100  m_th = 0;
101  }
102  }
103  ~PThread() {}
104 
105  public:
106  pthread_t id() { return m_th; }
107  pthread_t get_id() { return m_th; }
108  bool kill(int signo)
109  {
110  if (m_th == 0) return false;
111  return ::pthread_kill(m_th, signo) == 0;
112  }
113  bool is_alive() { return this->kill(0); }
114  bool detach()
115  {
116  if (m_th == 0) return false;
117  return ::pthread_detach(m_th) == 0;
118  }
119  bool join()
120  {
121  if (m_th == 0) return false;
122  return ::pthread_join(m_th, NULL) == 0;
123  }
124  bool cancel()
125  {
126  if (m_th == 0) return false;
127  return ::pthread_cancel(m_th) == 0;
128  }
129 
130  private:
131  pthread_t m_th;
132 
133  };
134 
136 }
137 
138 #endif
Abstract base class for different kinds of events.