summaryrefslogtreecommitdiffstats
path: root/timer.hpp
blob: 058740e9e93fdf4203b5f195636d38bea08c7ae3 (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
140
141
142
143
144
145
146
147
#pragma once

#include <functional>
#include <memory>
#include <chrono>
#include <systemd/sd-event.h>
namespace phosphor
{
namespace watchdog
{

/* Need a custom deleter for freeing up sd_event */
struct EventDeleter
{
    void operator()(sd_event* event) const
    {
        event = sd_event_unref(event);
    }
};
using EventPtr = std::unique_ptr<sd_event, EventDeleter>;

/* Need a custom deleter for freeing up sd_event_source */
struct EventSourceDeleter
{
    void operator()(sd_event_source* eventSource) const
    {
        eventSource = sd_event_source_unref(eventSource);
    }
};
using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;

/** @class Timer
 *  @brief Manages starting timers and handling timeouts
 */
class Timer
{
    public:
        Timer() = delete;
        ~Timer() = default;
        Timer(const Timer&) = delete;
        Timer& operator=(const Timer&) = delete;
        Timer(Timer&&) = delete;
        Timer& operator=(Timer&&) = delete;

        /** @brief Constructs timer object
         *
         *  @param[in] event        - sd_event unique pointer
         *  @param[in] userCallBack - Optional function callback
         *                            for timer expiration
         */
        Timer(EventPtr& event,
              std::function<void()> userCallBack = nullptr)
            : event(event),
              userCallBack(userCallBack)
        {
            // Initialize the timer
            initialize();
        }

        void clearExpired(void)
        {
            expire = false;
        }

        /** @brief Tells whether the timer is expired or not */
        inline auto expired() const
        {
            return expire;
        }

        /** @brief Returns the current Timer enablement type */
        int getEnabled() const;

        /** @brief Enables / disables the timer.
         *         <T> is an integral constant boolean
         */
        template <typename T> void setEnabled()
        {
            constexpr auto type = T::value ? SD_EVENT_ONESHOT : SD_EVENT_OFF;
            return setEnabled(type);
        }

        /** @brief Returns time remaining in usec before expiration
         *         which is an offset to current steady clock
         */
        std::chrono::microseconds getRemaining() const;

        /** @brief Starts the timer with specified expiration value.
         *         std::steady_clock is used for base time.
         *
         *  @param[in] usec - Microseconds from the current time
         *                    before expiration.
         *
         *  @return None.
         *
         *  @error Throws exception
         */
        void start(std::chrono::microseconds usec);

        /** @brief Gets the current time from steady clock */
        static std::chrono::microseconds getCurrentTime();

    private:
        /** @brief Reference to sd_event unique pointer */
        EventPtr& event;

        /** @brief event source */
        EventSourcePtr eventSource;

        /** @brief Set to true when the timeoutHandler is called into */
        bool expire = false;

        /** @brief Optional function to call on timer expiration
         *         This is called from timeout handler.
         */
        std::function<void()> userCallBack;

        /** @brief Initializes the timer object with infinite
         *         expiration time and sets up the callback handler
         *
         *  @return None.
         *
         *  @error Throws exception
         */
        void initialize();

        /** @brief Callback function when timer goes off
         *
         *  @param[in] eventSource - Source of the event
         *  @param[in] usec        - time in microseconds
         *  @param[in] userData    - User data pointer
         *
         */
        static int timeoutHandler(sd_event_source* eventSource,
                                  uint64_t usec, void* userData);

        /** @brief Enables / disables the timer
         *
         *  @param[in] type - Timer type.
         *                    This implementation uses only SD_EVENT_OFF
         *                    and SD_EVENT_ONESHOT
         */
        void setEnabled(int type);
};

} // namespace watchdog
} // namespace phosphor
OpenPOWER on IntegriCloud