Skip to content

Commit 4da49e0

Browse files
committed
Add thread::Timer for per process timers
1 parent caff8e2 commit 4da49e0

6 files changed

Lines changed: 171 additions & 5 deletions

File tree

libraries/ThreadAPI/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(SOURCES
77
thread/Mutex.hpp
88
thread/Signal.hpp
99
thread/Sched.hpp
10+
thread/Timer.hpp
1011
thread/Sem.hpp
1112
PARENT_SCOPE
1213
)

libraries/ThreadAPI/include/thread.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace thread {}
1212
#include "thread/Sem.hpp"
1313
#include "thread/Signal.hpp"
1414
#include "thread/Thread.hpp"
15+
#include "thread/Timer.hpp"
1516

1617
using namespace thread;
1718

libraries/ThreadAPI/include/thread/Signal.hpp

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ union sigval {
4646

4747
namespace thread {
4848

49-
class SignalFlags {
49+
class SignalFlags : public api::ExecutionContext{
5050
public:
5151
enum class Number {
5252
null = 0,
@@ -88,7 +88,7 @@ class SignalFlags {
8888
};
8989
};
9090

91-
class SignalHandler : public api::ExecutionContext, public SignalFlags {
91+
class SignalHandler : public SignalFlags {
9292
public:
9393
class Construct {
9494
API_AF(Construct, signal_function_callback_t, signal_function, nullptr);
@@ -105,26 +105,86 @@ class SignalHandler : public api::ExecutionContext, public SignalFlags {
105105
m_sig_action.sa_handler = (_sig_func_ptr)options.signal_function();
106106
#endif
107107
m_sig_action.sa_flags = 0;
108-
m_sig_action.sa_mask = {0};
108+
m_sig_action.sa_mask = {};
109109
} else {
110110
m_sig_action.sa_sigaction = options.signal_action();
111111
m_sig_action.sa_flags = options.flags() | SIGNAL_SIGINFO_FLAG;
112112
m_sig_action.sa_mask = options.mask();
113113
}
114114
}
115115

116+
explicit SignalHandler(signal_function_callback_t function){
117+
m_sig_action.sa_handler = (_sig_func_ptr)function;
118+
}
119+
120+
explicit SignalHandler(signal_action_callback_t action){
121+
m_sig_action.sa_sigaction = action;
122+
m_sig_action.sa_flags = SIGNAL_SIGINFO_FLAG;
123+
}
124+
116125
API_NO_DISCARD const struct sigaction *sigaction() const {
117126
return &m_sig_action;
118127
}
119128

129+
static SignalHandler default_(){
130+
return SignalHandler(SignalHandler::Construct().set_signal_function((signal_function_callback_t)SIG_DFL));
131+
}
132+
133+
static SignalHandler ignore(){
134+
return SignalHandler(SignalHandler::Construct().set_signal_function((signal_function_callback_t)SIG_IGN));
135+
}
136+
120137
private:
121-
struct sigaction m_sig_action;
138+
struct sigaction m_sig_action = {};
122139
};
123140

124-
class Signal : public api::ExecutionContext, public SignalFlags {
141+
class Signal : public SignalFlags {
125142
public:
126143

127144
#if !defined __link
145+
class Event {
146+
public:
147+
enum class Notify {
148+
none = SIGEV_NONE,
149+
signal = SIGEV_SIGNAL,
150+
thread = SIGEV_THREAD
151+
};
152+
153+
Event & set_notify(Notify value){
154+
m_event.sigev_notify = int(value);
155+
return *this;
156+
}
157+
158+
Event & set_number(Number value){
159+
m_event.sigev_signo = int(value);
160+
return *this;
161+
}
162+
163+
Event & set_value(int value){
164+
m_event.sigev_value.sival_int = value;
165+
return *this;
166+
}
167+
168+
Event & set_value(void * value){
169+
m_event.sigev_value.sival_ptr = value;
170+
return *this;
171+
}
172+
173+
Event & set_notify_function(void (*value)(sigval)){
174+
m_event.sigev_notify_function = value;
175+
return *this;
176+
}
177+
178+
Event & set_notify_attributes(pthread_attr_t * value){
179+
m_event.sigev_notify_attributes = value;
180+
return *this;
181+
}
182+
183+
private:
184+
friend class Timer;
185+
struct sigevent m_event = {};
186+
};
187+
128188
class Set {
129189
public:
130190
Set &add(Number signo) {
@@ -183,6 +243,7 @@ class Signal : public api::ExecutionContext, public SignalFlags {
183243
static Signal wait(const Set &set);
184244
#endif
185245

246+
Number number() const { return Number(m_signo); }
186247
API_NO_DISCARD int signo() const { return m_signo; }
187248
API_NO_DISCARD int sigvalue() const { return m_sigvalue.sival_int; }
188249
API_NO_DISCARD void *sigptr() const { return m_sigvalue.sival_ptr; }
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2011-2021 Tyler Gilbert and Stratify Labs, Inc; see LICENSE.md
2+
3+
#ifndef THREADAPI_THREAD_TIMER_HPP
4+
#define THREADAPI_THREAD_TIMER_HPP
5+
6+
#include <signal.h>
7+
8+
#include "chrono/ClockTime.hpp"
9+
#include "Signal.hpp"
10+
11+
namespace thread {
12+
13+
class Timer : public api::ExecutionContext {
14+
public:
15+
using ClockId = chrono::ClockTime::ClockId;
16+
Timer(Signal::Event& signal_event, ClockId clock_id = ClockId::realtime);
17+
~Timer();
18+
19+
Timer(const Timer & a) = delete;
20+
Timer& operator=(const Timer &a) = delete;
21+
22+
Timer(Timer && a){
23+
std::swap(m_timer, a.m_timer);
24+
}
25+
26+
Timer& operator=(Timer &&a){
27+
std::swap(m_timer, a.m_timer);
28+
return *this;
29+
}
30+
31+
bool is_valid() const {
32+
return m_timer != timer_t(-1);
33+
}
34+
35+
enum class Flags {
36+
null = 0,
37+
absolute_time = TIMER_ABSTIME
38+
};
39+
40+
class SetTime {
41+
API_AC(SetTime, chrono::ClockTime, interval);
42+
API_AC(SetTime, chrono::ClockTime, value);
43+
API_AF(SetTime, Flags, flags, Flags::null);
44+
};
45+
46+
Timer & set_time(const SetTime & options);
47+
48+
class Info {
49+
API_RAC(Info, chrono::ClockTime, interval);
50+
API_RAC(Info, chrono::ClockTime, value);
51+
friend class Timer;
52+
};
53+
54+
Info get_info() const;
55+
56+
private:
57+
timer_t m_timer = timer_t(-1);
58+
59+
};
60+
61+
} // namespace thread
62+
63+
#endif // THREADAPI_THREAD_TIMER_HPP

libraries/ThreadAPI/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ set(SOURCES
77
Sem.cpp
88
Mq.cpp
99
Sched.cpp
10+
Timer.cpp
1011
PARENT_SCOPE
1112
)

libraries/ThreadAPI/src/Timer.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include "thread/Timer.hpp"
2+
3+
using namespace thread;
4+
5+
Timer::Timer(Signal::Event &signal_event, ClockId clock_id) {
6+
API_RETURN_IF_ERROR();
7+
API_SYSTEM_CALL(
8+
"", timer_create(clockid_t(clock_id), &signal_event.m_event, &m_timer));
9+
}
10+
11+
Timer::~Timer() {
12+
if (is_valid()) {
13+
timer_delete(m_timer);
14+
}
15+
}
16+
17+
Timer &Timer::set_time(const SetTime &options) {
18+
API_RETURN_VALUE_IF_ERROR(*this);
19+
API_ASSERT(is_valid());
20+
21+
struct itimerspec value = {.it_interval = *options.interval().timespec(),
22+
.it_value = *options.value().timespec()};
23+
24+
API_SYSTEM_CALL("", timer_settime(m_timer, int(options.flags()), &value, nullptr));
25+
return *this;
26+
}
27+
28+
29+
Timer::Info Timer::get_info() const {
30+
API_RETURN_VALUE_IF_ERROR(Info());
31+
32+
Info result;
33+
struct itimerspec value;
34+
API_SYSTEM_CALL("", timer_gettime(m_timer, &value));
35+
result.m_interval = value.it_interval;
36+
result.m_value = value.it_value;
37+
return result;
38+
}
39+

0 commit comments

Comments
 (0)