summaryrefslogtreecommitdiffstats
path: root/src/sdevent/timer.hpp
blob: 863e725672b1fcf9ebc88a4e6f1e8e547194cfb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once

#include <chrono>
#include <functional>
#include <memory>
#include <systemd/sd-event.h>

#include "sdevent/source.hpp"
#include "sdevent/event.hpp"

// TODO: openbmc/openbmc#1720 - add error handling for sd_event API failures

namespace sdevent
{
namespace event
{
namespace timer
{

/** @class Timer
 *  @brief Provides C++ bindings to the sd_event_source* timer functions.
 */
class Timer
{
    public:
        /* Define all of the basic class operations:
         *     Not allowed:
         *         - Default constructor to avoid nullptrs.
         *         - Copy operations due to internal unique_ptr.
         *     Allowed:
         *         - Move operations.
         *         - Destructor.
         */
        Timer() = delete;
        Timer(const Timer&) = delete;
        Timer& operator=(const Timer&) = delete;
        Timer(Timer&&) = default;
        Timer& operator=(Timer&&) = default;
        ~Timer() = default;

        using Callback = std::function<void(source::Source&)>;

        /** @brief Register a timer callback.
         *
         *  @param[in] event - The event to register on.
         *  @param[in] expires - The initial timer expiration time.
         *  @param[in] callback - The callback method.
         */
        Timer(
            sdevent::event::Event& event,
            const std::chrono::steady_clock::time_point& expires,
            Callback callback)
            : src(nullptr),
              cb(std::make_unique<Callback>(std::move(callback)))
        {
            using namespace std::chrono;
            auto epoch = expires.time_since_epoch();
            auto time = duration_cast<microseconds>(epoch);
            sd_event_source* source = nullptr;
            sd_event_add_time(
                event.get(),
                &source,
                CLOCK_MONOTONIC,
                time.count(),
                0,
                callCallback,
                cb.get());
// **INDENT-OFF**
            src = decltype(src){source, std::false_type()};
// **INDENT-ON**
        }

        /** @brief Register a disabled timer callback.
         *
         *  @param[in] event - The event to register on.
         *  @param[in] callback - The callback method.
         */
        Timer(
            sdevent::event::Event& event,
            Callback callback)
            : src(nullptr),
              cb(std::make_unique<Callback>(std::move(callback)))
        {
            sd_event_source* source = nullptr;
            sd_event_add_time(
                event.get(),
                &source,
                CLOCK_MONOTONIC,
                ULLONG_MAX,
                0,
                callCallback,
                cb.get());
// **INDENT-OFF**
            src = decltype(src){source, std::false_type()};
// **INDENT-ON**
        }

        /** @brief Set the timer expiration time. */
        void setTime(
            const std::chrono::steady_clock::time_point& expires)
        {
            src.setTime(expires);
        }

        /** @brief Get the timer expiration time. */
        auto getTime()
        {
            return src.getTime();
        }

        /** @brief Set the timer source enable state. */
        void enable(int enable)
        {
            src.enable(enable);
        }

        /** @brief Query timer state. */
        auto enabled()
        {
            return src.enabled();
        }

    private:
        source::Source src;
        std::unique_ptr<Callback> cb = nullptr;

        static int callCallback(sd_event_source* s, uint64_t usec,
                                void* context)
        {
            source::Source source(s);
            auto c = static_cast<Callback*>(context);
            (*c)(source);

            return 0;
        }
};
} // namespace timer
} // namespace event
} // namespace sdevent
OpenPOWER on IntegriCloud