MatLogger2  1.0.0
Library for logging of numeric data to HDF5 MAT-files, which is RT-safe and multithreaded.
thread_replacement.h
Go to the documentation of this file.
1 #ifndef __XBOT_MATLOGGER2_UTIL_THREAD_REPLACEMENT_H__
2 #define __XBOT_MATLOGGER2_UTIL_THREAD_REPLACEMENT_H__
3 
4 /* Define minimalistic C++-like thread, mutex and condition_variable
5  * using POSIX */
6 
7 #include <pthread.h>
8 #include <functional>
9 #include <mutex>
10 
11 namespace XBot { namespace matlogger2
12 {
13  class thread
14  {
15 
16  public:
17 
18  template <typename Callable, typename... Args>
19  thread(Callable&& callable, Args&&... args):
20  _main_func(std::bind(callable, args...))
21  {
22  create(SCHED_OTHER, 10);
23  }
24 
25  template <typename Callable, typename... Args>
26  thread(int sched_policy, int prio, Callable&& callable, Args&&... args):
27  _main_func(std::bind(callable, args...))
28  {
29  create(sched_policy, prio);
30  }
31 
32  void join()
33  {
34  int ret = pthread_join(_handle, nullptr);
35 
36  if(ret != 0)
37  {
38  throw std::runtime_error("error while joining thread");
39  }
40  }
41 
42  private:
43 
44  thread(const thread&) = delete;
45  thread& operator=(const thread&) = delete;
46 
47  void create(int sched_policy, int prio)
48  {
49  pthread_attr_t attr;
50  pthread_attr_init (&attr);
51  pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
52  pthread_attr_setschedpolicy (&attr, sched_policy);
53  sched_param schedparam;
54  schedparam.sched_priority = prio;
55  pthread_attr_setschedparam(&attr, &schedparam);
56  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
57 
58  int ret = pthread_create(&_handle, &attr, &thread::thread_main, this);
59 
60  if(ret != 0)
61  {
62  throw std::runtime_error("unable to start thread");
63  }
64 
65  pthread_attr_destroy(&attr);
66  }
67 
68  static void * thread_main(void * arg)
69  {
70  ((thread *)arg)->_main_func();
71  return nullptr;
72  }
73 
74  pthread_t _handle;
75  std::function<void(void)> _main_func;
76 
77  };
78 
79  class mutex
80  {
81 
82  public:
83 
85  {
86  pthread_mutexattr_t attr;
87  pthread_mutexattr_init(&attr);
88 
89  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
90  int ret = pthread_mutex_init(&_handle, &attr);
91  if(ret != 0){
92  throw std::runtime_error("error initializing the mutex (" + std::to_string(ret) + ")");
93  }
94 
95  pthread_mutexattr_destroy(&attr);
96  }
97 
98  void lock()
99  {
100  int ret = pthread_mutex_lock(&_handle);
101  if(ret != 0){
102  throw std::runtime_error("error acquiring the mutex (" + std::to_string(ret) + ")");
103  }
104  }
105 
106  bool try_lock()
107  {
108  int ret = pthread_mutex_trylock(&_handle);
109  if(ret == EBUSY){
110  return false;
111  }
112  if(ret != 0){
113  throw std::runtime_error("error acquiring the mutex (" + std::to_string(ret) + ")");
114  }
115  return true;
116  }
117 
118  void unlock()
119  {
120  int ret = pthread_mutex_unlock(&_handle);
121  if(ret != 0){
122  throw std::runtime_error("error releasing the mutex (" + std::to_string(ret) + ")");
123  }
124  }
125 
126  pthread_mutex_t * get_native_handle()
127  {
128  return &_handle;
129  }
130 
131 
132 
133  private:
134 
135  mutex(const mutex&) = delete;
136  mutex(const mutex&&) = delete;
137  mutex& operator=(const mutex&) = delete;
138  mutex& operator=(const mutex&&) = delete;
139 
140  pthread_mutex_t _handle;
141 
142 
143  };
144 
145 
147  {
148 
149  public:
150 
152  {
153 
154  pthread_condattr_t attr;
155  pthread_condattr_init(&attr);
156  int ret_1 = pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
157  if(0 != ret_1)
158  {
159  throw std::runtime_error("error in pthread_condattr_setpshared (" + std::to_string(ret_1) + ")");
160  }
161 
162  int ret = pthread_cond_init(&_handle, &attr);
163  if(ret != 0){
164  throw std::runtime_error("error initializing condition_variable (" + std::to_string(ret) + ")");
165  }
166  }
167 
168  template <typename Predicate>
169  void wait(std::unique_lock<mutex>& lock, const Predicate& pred)
170  {
171  pthread_mutex_t * mutex = lock.mutex()->get_native_handle();
172 
173  while(!pred())
174  {
175  int ret = pthread_cond_wait(&_handle, mutex);
176  if(ret != 0){
177  throw std::runtime_error("error in pthread_cond_wait (" + std::to_string(ret) + ")");
178  }
179  }
180  }
181 
182  void notify_one()
183  {
184  int ret = pthread_cond_signal(&_handle);
185  if(ret != 0){
186  throw std::runtime_error("error in pthread_cond_signal (" + std::to_string(ret) + ")");
187  }
188  }
189 
190  private:
191 
192  pthread_cond_t _handle;
193 
194 
195  };
196 } }
197 
198 #endif
void wait(std::unique_lock< mutex > &lock, const Predicate &pred)
STL namespace.
pthread_mutex_t * get_native_handle()
thread(int sched_policy, int prio, Callable &&callable, Args &&...args)
thread(Callable &&callable, Args &&...args)