1 #include <sdeventplus/clock.hpp>
2 #include <sdeventplus/internal/cexec.hpp>
3 #include <sdeventplus/internal/sdevent.hpp>
4 #include <sdeventplus/source/time.hpp>
5 #include <sdeventplus/types.hpp>
6 
7 #include <memory>
8 #include <type_traits>
9 #include <utility>
10 
11 namespace sdeventplus
12 {
13 namespace source
14 {
15 
16 template <ClockId Id>
Time(const Event & event,TimePoint time,Accuracy accuracy,Callback && callback)17 Time<Id>::Time(const Event& event, TimePoint time, Accuracy accuracy,
18                Callback&& callback) :
19     Base(event, create_source(event, time, accuracy), std::false_type())
20 {
21     set_userdata(
22         std::make_unique<detail::TimeData<Id>>(*this, std::move(callback)));
23 }
24 
25 template <ClockId Id>
Time(const Time<Id> & other,sdeventplus::internal::NoOwn)26 Time<Id>::Time(const Time<Id>& other, sdeventplus::internal::NoOwn) :
27     Base(other, sdeventplus::internal::NoOwn())
28 {}
29 
30 template <ClockId Id>
set_callback(Callback && callback)31 void Time<Id>::set_callback(Callback&& callback)
32 {
33     get_userdata().callback = std::move(callback);
34 }
35 
36 template <ClockId Id>
get_time() const37 typename Time<Id>::TimePoint Time<Id>::get_time() const
38 {
39     uint64_t usec;
40     SDEVENTPLUS_CHECK(
41         "sd_event_source_get_time",
42         event.getSdEvent()->sd_event_source_get_time(get(), &usec));
43     return Time<Id>::TimePoint(SdEventDuration(usec));
44 }
45 
46 template <ClockId Id>
set_time(TimePoint time) const47 void Time<Id>::set_time(TimePoint time) const
48 {
49     SDEVENTPLUS_CHECK(
50         "sd_event_source_set_time",
51         event.getSdEvent()->sd_event_source_set_time(
52             get(), SdEventDuration(time.time_since_epoch()).count()));
53 }
54 
55 template <ClockId Id>
get_accuracy() const56 typename Time<Id>::Accuracy Time<Id>::get_accuracy() const
57 {
58     uint64_t usec;
59     SDEVENTPLUS_CHECK(
60         "sd_event_source_get_time_accuracy",
61         event.getSdEvent()->sd_event_source_get_time_accuracy(get(), &usec));
62     return SdEventDuration(usec);
63 }
64 
65 template <ClockId Id>
set_accuracy(Accuracy accuracy) const66 void Time<Id>::set_accuracy(Accuracy accuracy) const
67 {
68     SDEVENTPLUS_CHECK("sd_event_source_set_time_accuracy",
69                       event.getSdEvent()->sd_event_source_set_time_accuracy(
70                           get(), SdEventDuration(accuracy).count()));
71 }
72 
73 template <ClockId Id>
get_userdata() const74 detail::TimeData<Id>& Time<Id>::get_userdata() const
75 {
76     return static_cast<detail::TimeData<Id>&>(Base::get_userdata());
77 }
78 
79 template <ClockId Id>
get_callback()80 typename Time<Id>::Callback& Time<Id>::get_callback()
81 {
82     return get_userdata().callback;
83 }
84 
85 template <ClockId Id>
create_source(const Event & event,TimePoint time,Accuracy accuracy)86 sd_event_source* Time<Id>::create_source(const Event& event, TimePoint time,
87                                          Accuracy accuracy)
88 {
89     sd_event_source* source;
90     SDEVENTPLUS_CHECK(
91         "sd_event_add_time",
92         event.getSdEvent()->sd_event_add_time(
93             event.get(), &source, static_cast<clockid_t>(Id),
94             SdEventDuration(time.time_since_epoch()).count(),
95             SdEventDuration(accuracy).count(), timeCallback, nullptr));
96     return source;
97 }
98 
99 template <ClockId Id>
timeCallback(sd_event_source * source,uint64_t usec,void * userdata)100 int Time<Id>::timeCallback(sd_event_source* source, uint64_t usec,
101                            void* userdata)
102 {
103     return sourceCallback<Callback, detail::TimeData<Id>, &Time::get_callback>(
104         "timeCallback", source, userdata, TimePoint(SdEventDuration(usec)));
105 }
106 
107 template class Time<ClockId::RealTime>;
108 template class Time<ClockId::Monotonic>;
109 template class Time<ClockId::BootTime>;
110 template class Time<ClockId::RealTimeAlarm>;
111 template class Time<ClockId::BootTimeAlarm>;
112 
113 namespace detail
114 {
115 
116 template <ClockId Id>
TimeData(const Time<Id> & base,typename Time<Id>::Callback && callback)117 TimeData<Id>::TimeData(const Time<Id>& base,
118                        typename Time<Id>::Callback&& callback) :
119     Time<Id>(base, sdeventplus::internal::NoOwn()), BaseData(base),
120     callback(std::move(callback))
121 {}
122 
123 } // namespace detail
124 
125 } // namespace source
126 } // namespace sdeventplus
127