File include/jlib/threads/def.h changed (mode: 100644) (index 987bfb9..e057f47) |
23 |
23 |
#include <type_traits> |
#include <type_traits> |
24 |
24 |
|
|
25 |
25 |
namespace jl::threads { |
namespace jl::threads { |
26 |
|
enum class LockType { |
|
27 |
|
SpinLock, Mutex |
|
|
26 |
|
enum class lock_type { |
|
27 |
|
SPINLOCK, MUTEX |
28 |
28 |
}; |
}; |
29 |
|
enum class Create { JOINABLE, DETACHED }; |
|
30 |
|
template<typename lock_t, LockType type> |
|
31 |
|
struct Lock_T; |
|
32 |
|
template<typename T> |
|
33 |
|
struct Condition_T; |
|
34 |
|
template<typename thread_t, typename Result> |
|
35 |
|
struct Thread_T; |
|
|
29 |
|
template<typename t, lock_type type> |
|
30 |
|
struct lock_t; |
|
31 |
|
template<typename t> |
|
32 |
|
struct condition_t; |
|
33 |
|
template<typename result_t> |
|
34 |
|
struct thread_decl; |
|
35 |
|
template<typename t, typename result_t> |
|
36 |
|
struct thread_t; |
36 |
37 |
} |
} |
37 |
|
template<typename lock_t, jl::threads::LockType type> |
|
38 |
|
struct jl::threads::Lock_T { |
|
39 |
|
[[nodiscard]] |
|
40 |
|
inline auto init(); |
|
41 |
|
inline void destroy(); |
|
42 |
|
[[nodiscard]] |
|
43 |
|
inline bool try_lock(); |
|
44 |
|
inline void lock(); |
|
45 |
|
inline void unlock(); |
|
46 |
|
lock_t m; |
|
|
38 |
|
template<typename T, jl::threads::lock_type type> |
|
39 |
|
struct jl::threads::lock_t { |
|
40 |
|
[[nodiscard]] auto |
|
41 |
|
init(); |
|
42 |
|
void |
|
43 |
|
destroy(); |
|
44 |
|
[[nodiscard]] bool |
|
45 |
|
try_lock(); |
|
46 |
|
void |
|
47 |
|
lock(); |
|
48 |
|
void |
|
49 |
|
unlock(); |
|
50 |
|
T m; |
47 |
51 |
}; |
}; |
48 |
52 |
template<typename T> |
template<typename T> |
49 |
|
struct jl::threads::Condition_T { |
|
50 |
|
inline void init(); |
|
51 |
|
inline void destroy(); |
|
52 |
|
template<typename lock_t> |
|
53 |
|
inline void wait(Lock_T<lock_t, LockType::Mutex> *p_mutex); |
|
54 |
|
inline void wake_up_threads(); |
|
55 |
|
inline void wake_up_thread(); |
|
|
53 |
|
struct jl::threads::condition_t { |
|
54 |
|
void |
|
55 |
|
init(); |
|
56 |
|
void |
|
57 |
|
destroy(); |
|
58 |
|
template<typename LT> void |
|
59 |
|
wait(lock_t<LT, lock_type::MUTEX> *p_mutex); |
|
60 |
|
void |
|
61 |
|
wake_up_threads(); |
|
62 |
|
void |
|
63 |
|
wake_up_thread(); |
56 |
64 |
T m; |
T m; |
57 |
65 |
}; |
}; |
58 |
|
template<typename thread_t, typename Result> |
|
59 |
|
struct jl::threads::Thread_T |
|
60 |
|
{ |
|
61 |
|
static_assert (not std::is_void<Result>::value and |
|
62 |
|
(std::is_pointer<Result>::value |
|
63 |
|
or sizeof (Result) <= sizeof (void*))); |
|
64 |
|
|
|
65 |
|
template <Create mode, typename Arg, Result Func(Arg*)> [[nodiscard]] inline |
|
66 |
|
bool run(Arg *p_argument); |
|
67 |
|
template <typename Arg, Result Func(Arg*)> [[nodiscard]] inline |
|
68 |
|
bool run_deteached(Arg *p_arg); |
|
69 |
|
template <typename Arg, Result Func(Arg*)> [[nodiscard]] inline |
|
70 |
|
bool run_joinable (Arg *p_arg); |
|
71 |
|
template <typename Arg, Result Func(Arg*)> [[nodiscard]] inline |
|
72 |
|
bool run(Create mode, Arg *p_argument); |
|
73 |
|
|
|
74 |
|
inline void join(); |
|
75 |
|
inline void deteach(); |
|
76 |
|
|
|
77 |
|
thread_t m; |
|
|
66 |
|
template<typename result_t> |
|
67 |
|
struct jl::threads::thread_decl { |
|
68 |
|
static_assert(not std::is_void<result_t>::value |
|
69 |
|
and |
|
70 |
|
(std::is_pointer<result_t>::value |
|
71 |
|
or |
|
72 |
|
sizeof (result_t) <= sizeof (void*))); |
|
73 |
|
template <typename arg, result_t func(arg*)> |
|
74 |
|
[[nodiscard]] bool |
|
75 |
|
run_deteached(arg *p_arg); |
|
76 |
|
template <typename arg, result_t func(arg*)> |
|
77 |
|
[[nodiscard]] bool |
|
78 |
|
run_joinable (arg *p_arg); |
|
79 |
|
template <typename arg, result_t func(arg*)> |
|
80 |
|
result_t |
|
81 |
|
join(); |
|
82 |
|
void |
|
83 |
|
deteach(); |
78 |
84 |
}; |
}; |
File include/jlib/threads/impl_pthreads.inl changed (mode: 100644) (index 07d1cb6..39f26ae) |
22 |
22 |
#pragma once |
#pragma once |
23 |
23 |
#include "def.h" |
#include "def.h" |
24 |
24 |
#include <tuple> |
#include <tuple> |
25 |
|
#include "../assert.h" |
|
26 |
25 |
extern "C" { |
extern "C" { |
27 |
26 |
#include <pthread.h> |
#include <pthread.h> |
28 |
27 |
} |
} |
|
28 |
|
#include <cstdio> |
29 |
29 |
#include <cerrno> |
#include <cerrno> |
30 |
30 |
|
|
31 |
31 |
namespace jl::threads { |
namespace jl::threads { |
32 |
|
using P_SpinLock_t = pthread_spinlock_t; |
|
33 |
|
using P_SpinLock = Lock_T<P_SpinLock_t, LockType::SpinLock>; |
|
34 |
|
using P_Mutex_t = pthread_mutex_t; |
|
35 |
|
using P_Mutex = Lock_T<P_Mutex_t, LockType::Mutex>; |
|
36 |
|
using P_Condition = Condition_T<pthread_cond_t>; |
|
37 |
|
template<typename Result> |
|
38 |
|
using P_Thread = Thread_T<pthread_t, Result>; |
|
39 |
|
template<typename Arg, typename Result, Result Func(Arg*)> |
|
40 |
|
void* pthread_run(void *p_data); |
|
|
32 |
|
using spinlock_pth = lock_t<pthread_spinlock_t, lock_type::SPINLOCK>; |
|
33 |
|
using mutex_pth = lock_t<pthread_mutex_t, lock_type::MUTEX>; |
|
34 |
|
using condition_pth = condition_t<pthread_cond_t>; |
|
35 |
|
template<typename result_t> |
|
36 |
|
using thread_pth = thread_t<pthread_t, result_t>; |
41 |
37 |
} |
} |
42 |
38 |
namespace jl::threads::check { |
namespace jl::threads::check { |
43 |
|
inline bool pthread_mutex(int i); |
|
|
39 |
|
#ifndef NDEBUG |
|
40 |
|
[[nodiscard]] |
|
41 |
|
inline bool pthread_mutex (int i); |
|
42 |
|
[[nodiscard]] |
44 |
43 |
inline bool pthread_thread(int i); |
inline bool pthread_thread(int i); |
45 |
|
inline void pthread_join(int i); |
|
46 |
|
inline bool pthread_cond(int i); |
|
|
44 |
|
inline void pthread_join (int i); |
|
45 |
|
[[nodiscard]] |
|
46 |
|
inline bool pthread_cond (int i); |
|
47 |
|
#else |
|
48 |
|
[[nodiscard]] |
|
49 |
|
inline bool pthread_mutex (int) { return true; } |
|
50 |
|
[[nodiscard]] |
|
51 |
|
inline bool pthread_thread(int) { return true; } |
|
52 |
|
inline void pthread_join (int) {} |
|
53 |
|
[[nodiscard]] |
|
54 |
|
inline bool pthread_cond (int) { return true; } |
|
55 |
|
#endif |
47 |
56 |
} |
} |
48 |
|
template<> [[nodiscard]] inline auto jl::threads::P_SpinLock::init() { |
|
|
57 |
|
template<> [[nodiscard]] inline auto jl::threads::spinlock_pth:: |
|
58 |
|
init() { |
49 |
59 |
return bool(pthread_spin_init(&m, 0) == 0); |
return bool(pthread_spin_init(&m, 0) == 0); |
50 |
60 |
} |
} |
51 |
|
template<> inline void jl::threads::P_SpinLock::destroy() { |
|
|
61 |
|
template<> inline void jl::threads::spinlock_pth:: |
|
62 |
|
destroy() { |
52 |
63 |
pthread_spin_destroy(&m); |
pthread_spin_destroy(&m); |
53 |
64 |
} |
} |
54 |
|
template<> [[nodiscard]] inline bool jl::threads::P_SpinLock::try_lock() { |
|
|
65 |
|
template<> [[nodiscard]] inline bool jl::threads::spinlock_pth:: |
|
66 |
|
try_lock() { |
55 |
67 |
//if not 0 - EBUSY - The spin lock is currently locked by another thread. |
//if not 0 - EBUSY - The spin lock is currently locked by another thread. |
56 |
68 |
return pthread_spin_trylock(&m) == 0; |
return pthread_spin_trylock(&m) == 0; |
57 |
69 |
} |
} |
58 |
|
template<> inline void jl::threads::P_SpinLock::lock() { |
|
|
70 |
|
template<> inline void jl::threads::spinlock_pth:: |
|
71 |
|
lock() { |
59 |
72 |
auto r = pthread_spin_lock(&m); |
auto r = pthread_spin_lock(&m); |
60 |
|
jassert_soft(r != EDEADLOCK, |
|
61 |
|
"EDEADLOCK The spinlock detected a deadlock condition."); |
|
|
73 |
|
if (r == EDEADLOCK) |
|
74 |
|
fputs("EDEADLOCK The spinlock detected a deadlock condition.", stderr); |
62 |
75 |
} |
} |
63 |
|
template<> inline void jl::threads::P_SpinLock::unlock() { |
|
|
76 |
|
template<> inline void jl::threads::spinlock_pth:: |
|
77 |
|
unlock() { |
64 |
78 |
pthread_spin_unlock(&m); |
pthread_spin_unlock(&m); |
65 |
79 |
} |
} |
66 |
|
inline bool jl::threads::check::pthread_mutex(int i) { |
|
67 |
80 |
#ifndef NDEBUG |
#ifndef NDEBUG |
|
81 |
|
[[nodiscard]] |
|
82 |
|
inline bool jl::threads::check:: |
|
83 |
|
pthread_mutex(int i) { |
68 |
84 |
switch (i) { |
switch (i) { |
69 |
85 |
case EINVAL: |
case EINVAL: |
70 |
|
fprintf(stderr, |
|
71 |
|
"The value specified by mutex does not refer to an initialized " |
|
72 |
|
"mutex object. OR The mutex was created with the protocol " |
|
73 |
|
"attribute having the value" |
|
74 |
|
" PTHREAD_PRIO_PROTECT and the calling thread's priority " |
|
75 |
|
"is higher than the mutex's current priority ceiling."); break; |
|
|
86 |
|
fputs("The value specified by mutex does not refer to an initialized " |
|
87 |
|
"mutex object. OR The mutex was created with the protocol " |
|
88 |
|
"attribute having the value" |
|
89 |
|
" PTHREAD_PRIO_PROTECT and the calling thread's priority " |
|
90 |
|
"is higher than the mutex's current priority ceiling.", stderr); |
|
91 |
|
break; |
76 |
92 |
case EAGAIN: |
case EAGAIN: |
77 |
|
fprintf(stderr, |
|
78 |
|
"The mutex could not be acquired because the maximum number " |
|
79 |
|
"of recursive locks for mutex has been exceeded."); break; |
|
|
93 |
|
fputs("The mutex could not be acquired because the maximum number " |
|
94 |
|
"of recursive locks for mutex has been exceeded.", stderr); |
|
95 |
|
break; |
80 |
96 |
case EDEADLK: |
case EDEADLK: |
81 |
|
fprintf(stderr, "The current thread already owns the mutex."); break; |
|
|
97 |
|
fputs("The current thread already owns the mutex.", stderr); |
|
98 |
|
break; |
82 |
99 |
case EPERM: |
case EPERM: |
83 |
|
fprintf(stderr, "The current thread does not own the mutex."); break; |
|
|
100 |
|
fputs("The current thread does not own the mutex.", stderr); |
|
101 |
|
break; |
84 |
102 |
} |
} |
85 |
|
#endif |
|
86 |
103 |
return i == 0; |
return i == 0; |
87 |
104 |
} |
} |
88 |
|
inline bool jl::threads::check::pthread_thread(int i) |
|
|
105 |
|
[[nodiscard]] |
|
106 |
|
inline bool jl::threads::check:: |
|
107 |
|
pthread_thread(int i) |
89 |
108 |
{ |
{ |
90 |
|
#ifndef NDEBUG |
|
91 |
109 |
switch (i) { |
switch (i) { |
92 |
110 |
case EAGAIN: |
case EAGAIN: |
93 |
|
fprintf(stderr, |
|
94 |
|
"Insufficient resources to create another thread, or a " |
|
95 |
|
"system-imposed limit on the number of threads was encountered. " |
|
96 |
|
"The latter case may occur in two ways: " |
|
97 |
|
"the RLIMIT_NPROC soft resource limit (set via setrlimit(2)), " |
|
98 |
|
"which limits the number of process for a real user ID, " |
|
99 |
|
"was reached; or the kernel's system-wide limit on the number " |
|
100 |
|
"of threads, /proc/sys/kernel/threads-max, was reached."); break; |
|
101 |
|
case EINVAL: fprintf(stderr, "Invalid settings in attr."); break; |
|
|
111 |
|
fputs("Insufficient resources to create another thread, or a " |
|
112 |
|
"system-imposed limit on the number of threads was encountered. " |
|
113 |
|
"The latter case may occur in two ways: " |
|
114 |
|
"the RLIMIT_NPROC soft resource limit (set via setrlimit(2)), " |
|
115 |
|
"which limits the number of process for a real user ID, " |
|
116 |
|
"was reached; or the kernel's system-wide limit on the number " |
|
117 |
|
"of threads, /proc/sys/kernel/threads-max, was reached.", stderr); |
|
118 |
|
break; |
|
119 |
|
case EINVAL: |
|
120 |
|
fputs("Invalid settings in attr.", stderr); |
|
121 |
|
break; |
102 |
122 |
case EPERM: |
case EPERM: |
103 |
|
fprintf(stderr, |
|
104 |
|
"No permission to set the scheduling policy" |
|
105 |
|
" and parameters specified in attr."); break; |
|
|
123 |
|
fputs("No permission to set the scheduling policy" |
|
124 |
|
" and parameters specified in attr.", stderr); |
|
125 |
|
break; |
106 |
126 |
} |
} |
107 |
|
#endif |
|
108 |
127 |
return i == 0; |
return i == 0; |
109 |
128 |
} |
} |
110 |
|
inline void jl::threads::check::pthread_join(int i) { |
|
111 |
|
#ifndef NDEBUG |
|
|
129 |
|
inline void jl::threads::check:: |
|
130 |
|
pthread_join(int i) { |
112 |
131 |
switch (i) { |
switch (i) { |
113 |
132 |
case EDEADLK: |
case EDEADLK: |
114 |
|
fprintf(stderr, |
|
115 |
|
"A deadlock was detected (e.g., two threads tried to join with " |
|
116 |
|
"each other); or thread specifies the calling thread."); break; |
|
|
133 |
|
fputs("A deadlock was detected (e.g., two threads tried to join with " |
|
134 |
|
"each other); or thread specifies the calling thread.", stderr); |
|
135 |
|
break; |
117 |
136 |
case EINVAL: |
case EINVAL: |
118 |
|
fprintf(stderr, |
|
119 |
|
"thread is not a joinable thread. OR Another thread is already " |
|
120 |
|
"waiting to join with this thread. "); break; |
|
|
137 |
|
fputs("thread is not a joinable thread. OR Another thread is already " |
|
138 |
|
"waiting to join with this thread.", stderr); |
|
139 |
|
break; |
121 |
140 |
case ESRCH: |
case ESRCH: |
122 |
|
fprintf(stderr, "No thread with the ID thread could be found."); break; |
|
|
141 |
|
fputs("No thread with the ID thread could be found.", stderr); |
|
142 |
|
break; |
123 |
143 |
} |
} |
124 |
|
#else |
|
125 |
|
(void)i; |
|
126 |
|
#endif |
|
127 |
144 |
} |
} |
128 |
|
inline bool jl::threads::check::pthread_cond(int i) { |
|
129 |
|
#ifndef NDEBUG |
|
|
145 |
|
[[nodiscard]] |
|
146 |
|
inline bool jl::threads::check:: |
|
147 |
|
pthread_cond(int i) { |
130 |
148 |
switch(i) { |
switch(i) { |
131 |
149 |
case EINVAL: |
case EINVAL: |
132 |
|
fprintf(stderr, "The cond argument is invalid. "); break; |
|
|
150 |
|
fputs("The cond argument is invalid. ", stderr); |
|
151 |
|
break; |
133 |
152 |
case ETIMEDOUT: |
case ETIMEDOUT: |
134 |
|
fprintf(stderr, |
|
135 |
|
"The condition variable was not signalled " |
|
136 |
|
"before the timeout specified by abstime."); break; |
|
|
153 |
|
fputs("The condition variable was not signalled " |
|
154 |
|
"before the timeout specified by abstime.", stderr); |
|
155 |
|
break; |
137 |
156 |
case EBUSY: |
case EBUSY: |
138 |
|
fprintf(stderr, "Some threads are currently waiting on cond."); break; |
|
|
157 |
|
fputs("Some threads are currently waiting on cond.", stderr); |
|
158 |
|
break; |
139 |
159 |
} |
} |
140 |
|
#endif |
|
141 |
160 |
return i == 0; |
return i == 0; |
142 |
161 |
} |
} |
143 |
|
template<> inline auto jl::threads::P_Mutex::init() { |
|
|
162 |
|
#endif |
|
163 |
|
template<> inline auto jl::threads::mutex_pth:: |
|
164 |
|
init() { |
144 |
165 |
m = PTHREAD_MUTEX_INITIALIZER; |
m = PTHREAD_MUTEX_INITIALIZER; |
145 |
166 |
return; |
return; |
146 |
167 |
} |
} |
147 |
|
template<> inline void jl::threads::P_Mutex::destroy() { |
|
|
168 |
|
template<> inline void jl::threads::mutex_pth:: |
|
169 |
|
destroy() { |
148 |
170 |
pthread_mutex_destroy(&m); |
pthread_mutex_destroy(&m); |
149 |
171 |
} |
} |
150 |
|
template<> [[nodiscard]] inline bool jl::threads::P_Mutex::try_lock() { |
|
|
172 |
|
template<> [[nodiscard]] inline bool jl::threads::mutex_pth:: |
|
173 |
|
try_lock() { |
151 |
174 |
return check::pthread_mutex(pthread_mutex_trylock(&m)); |
return check::pthread_mutex(pthread_mutex_trylock(&m)); |
152 |
|
// if false - EBUSY - The spin lock is currently locked by another thread. |
|
153 |
175 |
} |
} |
154 |
|
template<> inline void jl::threads::P_Mutex::lock() { |
|
155 |
|
check::pthread_mutex(pthread_mutex_lock(&m)); |
|
|
176 |
|
template<> inline void jl::threads::mutex_pth:: |
|
177 |
|
lock() { |
|
178 |
|
(void)check::pthread_mutex(pthread_mutex_lock(&m)); |
156 |
179 |
} |
} |
157 |
|
template<> inline void jl::threads::P_Mutex::unlock() { |
|
158 |
|
check::pthread_mutex(pthread_mutex_unlock(&m)); |
|
|
180 |
|
template<> inline void jl::threads::mutex_pth:: |
|
181 |
|
unlock() { |
|
182 |
|
(void)check::pthread_mutex(pthread_mutex_unlock(&m)); |
159 |
183 |
} |
} |
160 |
|
template<> inline void jl::threads::P_Condition::init() { |
|
|
184 |
|
template<> inline void jl::threads::condition_pth::init() { |
161 |
185 |
m = PTHREAD_COND_INITIALIZER; |
m = PTHREAD_COND_INITIALIZER; |
162 |
186 |
} |
} |
163 |
|
template<> inline void jl::threads::P_Condition::destroy() { |
|
164 |
|
check::pthread_cond(pthread_cond_destroy(&m)); |
|
165 |
|
} |
|
166 |
|
template<>template<>inline void jl::threads::P_Condition::wait(P_Mutex *p_m) { |
|
167 |
|
check::pthread_cond(pthread_cond_wait(&m, &p_m->m)); |
|
168 |
|
} |
|
169 |
|
template<> inline void jl::threads::P_Condition::wake_up_threads() { |
|
170 |
|
check::pthread_cond(pthread_cond_broadcast(&m)); |
|
171 |
|
} |
|
172 |
|
template<> inline void jl::threads::P_Condition::wake_up_thread() { |
|
173 |
|
check::pthread_cond(pthread_cond_signal(&m)); |
|
174 |
|
} |
|
175 |
|
template<typename Arg, typename Result, Result Func(Arg*)> |
|
176 |
|
void* jl::threads::pthread_run(void *p_data) { |
|
177 |
|
Arg *p_arg = static_cast<Arg*>(p_data); |
|
178 |
|
return reinterpret_cast<void*>(Func(p_arg)); |
|
179 |
|
} |
|
180 |
|
template<typename Result> struct jl::threads::Thread_T<pthread_t, Result> { |
|
181 |
|
static_assert (not std::is_void<Result>::value and |
|
182 |
|
(std::is_pointer<Result>::value |
|
183 |
|
or sizeof (Result) <= sizeof (void*))); |
|
184 |
|
template <Create mode, typename Arg, Result Func(Arg*)> |
|
185 |
|
[[nodiscard]] inline bool run(Arg *p_arg) { |
|
186 |
|
switch (mode) { |
|
187 |
|
case Create::JOINABLE: { |
|
188 |
|
auto r = pthread_create(&m, {}, pthread_run<Arg, Result, Func>, p_arg); |
|
189 |
|
return check::pthread_thread(r); |
|
190 |
|
} |
|
191 |
|
case Create::DETACHED: { |
|
192 |
|
pthread_attr_t a; |
|
193 |
|
bool r = pthread_attr_init(&a) == 0; |
|
194 |
|
if (not r) |
|
195 |
|
return false; |
|
196 |
|
pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); |
|
197 |
|
int p = pthread_create(&m, &a, pthread_run<Arg, Result, Func>, p_arg); |
|
198 |
|
r = check::pthread_thread(p); |
|
199 |
|
pthread_attr_destroy(&a); |
|
200 |
|
return r; |
|
201 |
|
} |
|
202 |
|
} |
|
203 |
|
} |
|
204 |
|
template <typename Arg, Result Func(Arg*)> |
|
205 |
|
[[nodiscard]] inline bool run_deteached(Arg *p_arg) { |
|
206 |
|
return run<Create::DETACHED, Arg, Func>(p_arg); |
|
207 |
|
} |
|
208 |
|
template <typename Arg, Result Func(Arg*)> |
|
209 |
|
[[nodiscard]] inline bool run_joinable(Arg *p_arg) { |
|
210 |
|
return run<Create::JOINABLE, Arg, Func>(p_arg); |
|
|
187 |
|
template<> inline void jl::threads::condition_pth:: |
|
188 |
|
destroy() { |
|
189 |
|
(void)check::pthread_cond(pthread_cond_destroy(&m)); |
|
190 |
|
} |
|
191 |
|
template<> template<> inline void jl::threads::condition_pth:: |
|
192 |
|
wait(mutex_pth *p_m) { |
|
193 |
|
(void)check::pthread_cond(pthread_cond_wait(&m, &p_m->m)); |
|
194 |
|
} |
|
195 |
|
template<> inline void jl::threads::condition_pth:: |
|
196 |
|
wake_up_threads() { |
|
197 |
|
(void)check::pthread_cond(pthread_cond_broadcast(&m)); |
|
198 |
|
} |
|
199 |
|
template<> inline void jl::threads::condition_pth:: |
|
200 |
|
wake_up_thread() { |
|
201 |
|
(void)check::pthread_cond(pthread_cond_signal(&m)); |
|
202 |
|
} |
|
203 |
|
template<typename result_t> |
|
204 |
|
struct jl::threads::thread_t<pthread_t, result_t> : thread_decl<result_t> |
|
205 |
|
{ |
|
206 |
|
template <typename arg> |
|
207 |
|
[[nodiscard]] bool |
|
208 |
|
run_deteached(arg *p_arg, result_t func(arg*)) { |
|
209 |
|
pthread_attr_t a; |
|
210 |
|
if (pthread_attr_init(&a) != 0) |
|
211 |
|
return false; |
|
212 |
|
pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); |
|
213 |
|
auto p_func = reinterpret_cast<void*(*)(void*)>(func); |
|
214 |
|
int p = pthread_create(&m, &a, p_func, p_arg); |
|
215 |
|
bool r = check::pthread_thread(p); |
|
216 |
|
pthread_attr_destroy(&a); |
|
217 |
|
return r; |
211 |
218 |
} |
} |
212 |
|
template <typename Arg, Result Func(Arg*)> |
|
213 |
|
[[nodiscard]] inline bool run(Create mode, Arg *p_argument) { |
|
214 |
|
if (mode == Create::DETACHED) |
|
215 |
|
return run<Create::DETACHED, Arg, Func>(p_argument); |
|
216 |
|
else |
|
217 |
|
return run<Create::JOINABLE, Arg, Func>(p_argument); |
|
|
219 |
|
template <typename arg> |
|
220 |
|
[[nodiscard]] bool |
|
221 |
|
run_joinable(arg *p_arg, result_t func(arg*)) { |
|
222 |
|
auto p_func = reinterpret_cast<void*(*)(void*)>(func); |
|
223 |
|
auto r = pthread_create(&m, {}, p_func, p_arg); |
|
224 |
|
return check::pthread_thread(r); |
218 |
225 |
} |
} |
219 |
|
inline Result join() { |
|
220 |
|
void * res; |
|
|
226 |
|
result_t |
|
227 |
|
join() { |
|
228 |
|
void *res; |
221 |
229 |
check::pthread_join(pthread_join(m, &res)); |
check::pthread_join(pthread_join(m, &res)); |
222 |
|
return static_cast<Result>(reinterpret_cast<intptr_t>(res)); |
|
|
230 |
|
return static_cast<result_t>(reinterpret_cast<intptr_t>(res)); |
223 |
231 |
} |
} |
224 |
|
inline void deteach() { |
|
|
232 |
|
void |
|
233 |
|
deteach() { |
225 |
234 |
check::pthread_join(pthread_detach(m)); |
check::pthread_join(pthread_detach(m)); |
226 |
235 |
} |
} |
227 |
236 |
pthread_t m; |
pthread_t m; |