blob: d10054cf95f0599b98044371bd5bc664ddd9d3f1 [file] [log] [blame]
Brian Silvermanf7bd1c22015-12-24 16:07:11 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2015. 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#ifndef NT_NOTIFIER_H_
9#define NT_NOTIFIER_H_
10
11#include <atomic>
12#include <condition_variable>
13#include <mutex>
14#include <queue>
15#include <thread>
16#include <utility>
17#include <vector>
18
19#include "atomic_static.h"
20#include "ntcore_cpp.h"
21
22namespace nt {
23
24class Notifier {
25 friend class NotifierTest;
26 public:
27 static Notifier& GetInstance() {
28 ATOMIC_STATIC(Notifier, instance);
29 return instance;
30 }
31 ~Notifier();
32
33 void Start();
34 void Stop();
35
36 bool active() const { return m_active; }
37 bool local_notifiers() const { return m_local_notifiers; }
38 static bool destroyed() { return s_destroyed; }
39
40 void SetOnStart(std::function<void()> on_start) { m_on_start = on_start; }
41 void SetOnExit(std::function<void()> on_exit) { m_on_exit = on_exit; }
42
43 unsigned int AddEntryListener(StringRef prefix,
44 EntryListenerCallback callback,
45 unsigned int flags);
46 void RemoveEntryListener(unsigned int entry_listener_uid);
47
48 void NotifyEntry(StringRef name, std::shared_ptr<Value> value,
49 unsigned int flags, EntryListenerCallback only = nullptr);
50
51 unsigned int AddConnectionListener(ConnectionListenerCallback callback);
52 void RemoveConnectionListener(unsigned int conn_listener_uid);
53
54 void NotifyConnection(bool connected, const ConnectionInfo& conn_info,
55 ConnectionListenerCallback only = nullptr);
56
57 private:
58 Notifier();
59
60 void ThreadMain();
61
62 std::atomic_bool m_active;
63 std::atomic_bool m_local_notifiers;
64
65 std::mutex m_mutex;
66 std::condition_variable m_cond;
67
68 struct EntryListener {
69 EntryListener(StringRef prefix_, EntryListenerCallback callback_,
70 unsigned int flags_)
71 : prefix(prefix_), callback(callback_), flags(flags_) {}
72
73 std::string prefix;
74 EntryListenerCallback callback;
75 unsigned int flags;
76 };
77 std::vector<EntryListener> m_entry_listeners;
78 std::vector<ConnectionListenerCallback> m_conn_listeners;
79
80 struct EntryNotification {
81 EntryNotification(StringRef name_, std::shared_ptr<Value> value_,
82 unsigned int flags_, EntryListenerCallback only_)
83 : name(name_),
84 value(value_),
85 flags(flags_),
86 only(only_) {}
87
88 std::string name;
89 std::shared_ptr<Value> value;
90 unsigned int flags;
91 EntryListenerCallback only;
92 };
93 std::queue<EntryNotification> m_entry_notifications;
94
95 struct ConnectionNotification {
96 ConnectionNotification(bool connected_, const ConnectionInfo& conn_info_,
97 ConnectionListenerCallback only_)
98 : connected(connected_), conn_info(conn_info_), only(only_) {}
99
100 bool connected;
101 ConnectionInfo conn_info;
102 ConnectionListenerCallback only;
103 };
104 std::queue<ConnectionNotification> m_conn_notifications;
105
106 std::thread m_thread;
107 std::mutex m_shutdown_mutex;
108 std::condition_variable m_shutdown_cv;
109 bool m_shutdown = false;
110
111 std::function<void()> m_on_start;
112 std::function<void()> m_on_exit;
113
114 ATOMIC_STATIC_DECL(Notifier)
115 static bool s_destroyed;
116};
117
118} // namespace nt
119
120#endif // NT_NOTIFIER_H_