~aleteoryx/muditaos

ref: d9ae779a37f5d9efe5f18035f746420dd35306e1 muditaos/module-sys/Service/Timer.hpp -rw-r--r-- 3.8 KiB
d9ae779a — Borys Jelenski [EGD-5503] Add watchdog implementation 5 years ago
                                                                                
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
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "FreeRTOS.h"
#include "portmacro.h"                             // for TickType_t
#include <module-os/RTOSWrapper/include/timer.hpp> // for Timer
#include <functional>                              // for function
#include <string>                                  // for string
#include <atomic>
namespace sys
{
    class Service;
} // namespace sys

namespace sys
{
    using ms = unsigned int;

    class TimerIDGenerator
    {
      public:
        virtual ~TimerIDGenerator() = default;

        virtual void incrementID() const                                           = 0;
        [[nodiscard]] virtual std::string generateID(const std::string &val) const = 0;
    };

    class UserTimerIDGenerator : public TimerIDGenerator
    {
      public:
        void incrementID() const override{};

        [[nodiscard]] std::string generateID(const std::string &val) const override
        {
            return val;
        }
    };
    class SystemTimerIDGenerator : public TimerIDGenerator
    {
        static uint32_t &getId() noexcept
        {
            static uint32_t timer_id = 0;
            return timer_id;
        }

      public:
        void incrementID() const override
        {
            getId()++;
        };

        [[nodiscard]] std::string generateID(const std::string &val) const override
        {
            return val + "_" + std::to_string(getId());
        }
    };

    /// Base timer for all coarse timers in system
    class Timer : private cpp_freertos::Timer
    {
      public:
        static const ms timeout_infinite;

        enum class Type
        {
            Periodic,
            SingleShot
        };

        /// Create named timer and register it in parent
        /// @param name this will be name of timer + postfix
        /// @param parent service on which behalf timer events will be sent and received
        /// @param interval time for next timer event in
        Timer(const std::string &name,
              Service *parent,
              ms interval,
              Type type                         = Type::Periodic,
              const TimerIDGenerator &generator = SystemTimerIDGenerator());

        /// Create timer with default name `_<id_number>` and register it in parent
        /// @param parent service on which behalf timer events will be sent and received
        /// @param interval time for next timer event in
        Timer(Service *parent, ms interval, Type type = Type::Periodic);

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

        /// just to stop timer
        ~Timer() override;

        /// This is final by design - to avoid missuse we send Timer notification to Service
        /// and then handle it like any other event. Not by callback as this could cause unrestricted access (no mutex)
        void Run() final;

        /// executed when we receive timeout notification (from overriden Run()) on bus
        void onTimeout();

        /// @defgroup API
        /// {
        void start();
        void reload(ms from_time = 0);
        void stop();
        void setInterval(ms new_interval);
        /// }

      protected:
        Service *parent = nullptr;

      private:
        Type type;
        ms interval;
        std::function<void(Timer &)> callback = nullptr;
        std::atomic_bool isActive             = false;
        const std::string name;

      public:
        void connect(std::function<void(Timer &)> new_callback)
        {
            callback = new_callback;
        }

        [[nodiscard]] constexpr auto getName() const -> const std::string &
        {
            return name;
        }
    };
}; // namespace sys