blob: 2e9f88f776e88508ebb03c92fae93898fb5fff91 [file] [log] [blame]
Brian Silvermanf7f267a2017-02-04 16:16:08 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#pragma once
9
10#include <atomic>
11#include <functional>
12#include <list>
13#include <thread>
14#include <utility>
15
16#include "ErrorBase.h"
17#include "HAL/cpp/priority_mutex.h"
18
19namespace frc {
20
21typedef std::function<void()> TimerEventHandler;
22
23class Notifier : public ErrorBase {
24 public:
25 explicit Notifier(TimerEventHandler handler);
26
27 template <typename Callable, typename Arg, typename... Args>
28 Notifier(Callable&& f, Arg&& arg, Args&&... args)
29 : Notifier(std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
30 std::forward<Args>(args)...)) {}
31 virtual ~Notifier();
32
33 Notifier(const Notifier&) = delete;
34 Notifier& operator=(const Notifier&) = delete;
35
36 void StartSingle(double delay);
37 void StartPeriodic(double period);
38 void Stop();
39
40 private:
41 static std::list<Notifier*> timerQueue;
42 static priority_recursive_mutex queueMutex;
43 static priority_mutex halMutex;
44 static void* m_notifier;
45 static std::atomic<int> refcount;
46
47 // Process the timer queue on a timer event
48 static void ProcessQueue(int mask, void* params);
49
50 // Update the FPGA alarm since the queue has changed
51 static void UpdateAlarm();
52
53 // Insert the Notifier in the timer queue
54 void InsertInQueue(bool reschedule);
55
56 // Delete this Notifier from the timer queue
57 void DeleteFromQueue();
58
59 // Address of the handler
60 TimerEventHandler m_handler;
61 // The relative time (either periodic or single)
62 double m_period = 0;
63 // Absolute expiration time for the current event
64 double m_expirationTime = 0;
65 // True if this is a periodic event
66 bool m_periodic = false;
67 // Indicates if this entry is queued
68 bool m_queued = false;
69 // Held by interrupt manager task while handler call is in progress
70 priority_mutex m_handlerMutex;
71 static std::thread m_task;
72 static std::atomic<bool> m_stopped;
73 static void Run();
74};
75
76} // namespace frc