| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 1 | #pragma once | 
 | 2 |  | 
 | 3 | #include <chrono> | 
 | 4 | #include <memory> | 
 | 5 | #include <systemd/sd-event.h> | 
 | 6 |  | 
 | 7 | // TODO: openbmc/openbmc#1720 - add error handling for sd_event API failures | 
 | 8 |  | 
 | 9 | namespace sdevent | 
 | 10 | { | 
 | 11 | namespace source | 
 | 12 | { | 
 | 13 |  | 
 | 14 | using SourcePtr = sd_event_source*; | 
 | 15 |  | 
 | 16 | namespace details | 
 | 17 | { | 
 | 18 |  | 
 | 19 | /** @brief unique_ptr functor to release a source reference. */ | 
 | 20 | struct SourceDeleter | 
 | 21 | { | 
 | 22 |     void operator()(sd_event_source* ptr) const | 
 | 23 |     { | 
 | 24 |         deleter(ptr); | 
 | 25 |     } | 
 | 26 |  | 
 | 27 |     decltype(&sd_event_source_unref) deleter = sd_event_source_unref; | 
 | 28 | }; | 
 | 29 |  | 
 | 30 | /* @brief Alias 'source' to a unique_ptr type for auto-release. */ | 
 | 31 | using source = std::unique_ptr<sd_event_source, SourceDeleter>; | 
 | 32 |  | 
 | 33 | } // namespace details | 
 | 34 |  | 
 | 35 | /** @class Source | 
 | 36 |  *  @brief Provides C++ bindings to the sd_event_source* functions. | 
 | 37 |  */ | 
 | 38 | class Source | 
 | 39 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 40 |   public: | 
 | 41 |     /* Define all of the basic class operations: | 
 | 42 |      *     Not allowed: | 
 | 43 |      *         - Default constructor to avoid nullptrs. | 
 | 44 |      *         - Copy operations due to internal unique_ptr. | 
 | 45 |      *     Allowed: | 
 | 46 |      *         - Move operations. | 
 | 47 |      *         - Destructor. | 
 | 48 |      */ | 
 | 49 |     Source() = delete; | 
 | 50 |     Source(const Source&) = delete; | 
 | 51 |     Source& operator=(const Source&) = delete; | 
 | 52 |     Source(Source&&) = default; | 
 | 53 |     Source& operator=(Source&&) = default; | 
 | 54 |     ~Source() = default; | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 55 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 56 |     /** @brief Conversion constructor from 'SourcePtr'. | 
 | 57 |      * | 
 | 58 |      *  Increments ref-count of the source-pointer and releases it | 
 | 59 |      *  when done. | 
 | 60 |      */ | 
 | 61 |     explicit Source(SourcePtr s) : src(sd_event_source_ref(s)) | 
 | 62 |     { | 
 | 63 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 64 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 65 |     /** @brief Constructor for 'source'. | 
 | 66 |      * | 
 | 67 |      *  Takes ownership of the source-pointer and releases it when done. | 
 | 68 |      */ | 
 | 69 |     Source(SourcePtr s, std::false_type) : src(s) | 
 | 70 |     { | 
 | 71 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 72 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 73 |     /** @brief Check if source contains a real pointer. (non-nullptr). */ | 
 | 74 |     explicit operator bool() const | 
 | 75 |     { | 
 | 76 |         return bool(src); | 
 | 77 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 78 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 79 |     /** @brief Test whether or not the source can generate events. */ | 
 | 80 |     auto enabled() | 
 | 81 |     { | 
 | 82 |         int enabled; | 
 | 83 |         sd_event_source_get_enabled(src.get(), &enabled); | 
 | 84 |         return enabled; | 
 | 85 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 86 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 87 |     /** @brief Allow the source to generate events. */ | 
 | 88 |     void enable(int enable) | 
 | 89 |     { | 
 | 90 |         sd_event_source_set_enabled(src.get(), enable); | 
 | 91 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 92 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 93 |     /** @brief Set the expiration on a timer source. */ | 
 | 94 |     void setTime(const std::chrono::steady_clock::time_point& expires) | 
 | 95 |     { | 
 | 96 |         using namespace std::chrono; | 
 | 97 |         auto epoch = expires.time_since_epoch(); | 
 | 98 |         auto time = duration_cast<microseconds>(epoch); | 
 | 99 |         sd_event_source_set_time(src.get(), time.count()); | 
 | 100 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 101 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 102 |     /** @brief Get the expiration on a timer source. */ | 
 | 103 |     auto getTime() | 
 | 104 |     { | 
 | 105 |         using namespace std::chrono; | 
 | 106 |         uint64_t usec; | 
 | 107 |         sd_event_source_get_time(src.get(), &usec); | 
 | 108 |         microseconds d(usec); | 
 | 109 |         return steady_clock::time_point(d); | 
 | 110 |     } | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 111 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 112 |   private: | 
 | 113 |     details::source src; | 
| Brad Bishop | 605662d | 2017-05-30 12:39:09 -0400 | [diff] [blame] | 114 | }; | 
 | 115 | } // namespace source | 
 | 116 | } // namespace sdevent |