Belle II Software development
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
17namespace 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.