summaryrefslogtreecommitdiffstats
path: root/timer.hpp
blob: 979a1cc42eea92e15c28743d4f37e4e38d834a4c (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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#pragma once

#include <chrono>
#include <functional>
#include <memory>
#include "event.hpp"

namespace phosphor
{
namespace fan
{
namespace util
{


/**
 * @class Timer
 *
 * This class implements a simple timer that runs an arbitrary
 * function on expiration.  The timeout value is set in microseconds.
 * It can be stopped while it is running, and queried to see if it is
 * running.
 *
 * If started with the 'repeating' argument, it will keep calling the
 * callback function every <timeout> microseconds.  If started with the
 * 'oneshot' argument, it will just call the callback function one time.
 *
 * It needs an sd_event loop to function.
 */
class Timer
{
    public:

        enum class TimerType
        {
            oneshot,
            repeating
        };

        Timer() = delete;
        Timer(const Timer&) = delete;
        Timer& operator=(const Timer&) = delete;
        Timer(Timer&&) = default;
        Timer& operator=(Timer&&) = default;

        /**
         * @brief Constructs timer object
         *
         * @param[in] events - sd_event pointer, previously created
         * @param[in] callbackFunc - The function to call on timer expiration
         */
        Timer(phosphor::fan::event::EventPtr& events,
              std::function<void()> callbackFunc);

        /**
         * @brief Destructor
         */
        ~Timer();

        /**
         * @brief Starts the timer
         *
         * The input is an offset from the current steady clock.
         *
         * @param[in] usec - the timeout value in microseconds
         * @param[in] type - either a oneshot, or repeating
         */
        void start(std::chrono::microseconds usec,
                   TimerType type = TimerType::oneshot);

        /**
         * @brief Stop the timer
         */
        void stop();

        /**
         * @brief Returns true if the timer is running
         */
        bool running();

        /**
         * @brief Returns the timeout value
         *
         * @return - the last value sent in via start().
         *
         * Could be used to restart the timer with the same
         * timeout.  i.e.  start(getTimeout());
         */
         inline auto getTimeout() const
         {
            return timeout;
         }

        /**
         * @brief Returns the timer type
         */
        inline auto getType() const
        {
            return type;
        }

    private:

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

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

        /**
         * @brief Wrapper around sd_event_source_set_enabled
         *
         * @param[in] action - either SD_EVENT_OFF, SD_EVENT_ON,
         *                     or SD_EVENT_ONESHOT
         */
        void setTimer(int action);


        /**
         * @brief Sets the expiration time for the timer
         *
         * Sets it to timeout microseconds in the future
         */
        void setTimeout();

        /**
         * @brief The sd_event structure
         */
        phosphor::fan::event::EventPtr& timeEvent;

        /**
         * @brief Source of events
         */
        phosphor::fan::event::EventSourcePtr eventSource;

        /**
         * @brief Either 'repeating' or 'oneshot'
         */
        TimerType type = TimerType::oneshot;

        /**
         * @brief The function to call when the timer expires
         */
        std::function<void()> callback;

        /**
         * @brief What the timer was set to run for
         *
         * Not cleared on timer expiration
         */
        std::chrono::microseconds timeout;
};

}
}
}
OpenPOWER on IntegriCloud