Squashed 'third_party/ntcore_2016/' content from commit d8de5e4
Change-Id: Id4839f41b6a620d8bae58dcf1710016671cc4992
git-subtree-dir: third_party/ntcore_2016
git-subtree-split: d8de5e4f19e612e7102172c0dbf152ce82d3d63a
diff --git a/src/Notifier.h b/src/Notifier.h
new file mode 100644
index 0000000..d10054c
--- /dev/null
+++ b/src/Notifier.h
@@ -0,0 +1,120 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2015. All Rights Reserved. */
+/* Open Source Software - may be modified and shared by FRC teams. The code */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project. */
+/*----------------------------------------------------------------------------*/
+
+#ifndef NT_NOTIFIER_H_
+#define NT_NOTIFIER_H_
+
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <utility>
+#include <vector>
+
+#include "atomic_static.h"
+#include "ntcore_cpp.h"
+
+namespace nt {
+
+class Notifier {
+ friend class NotifierTest;
+ public:
+ static Notifier& GetInstance() {
+ ATOMIC_STATIC(Notifier, instance);
+ return instance;
+ }
+ ~Notifier();
+
+ void Start();
+ void Stop();
+
+ bool active() const { return m_active; }
+ bool local_notifiers() const { return m_local_notifiers; }
+ static bool destroyed() { return s_destroyed; }
+
+ void SetOnStart(std::function<void()> on_start) { m_on_start = on_start; }
+ void SetOnExit(std::function<void()> on_exit) { m_on_exit = on_exit; }
+
+ unsigned int AddEntryListener(StringRef prefix,
+ EntryListenerCallback callback,
+ unsigned int flags);
+ void RemoveEntryListener(unsigned int entry_listener_uid);
+
+ void NotifyEntry(StringRef name, std::shared_ptr<Value> value,
+ unsigned int flags, EntryListenerCallback only = nullptr);
+
+ unsigned int AddConnectionListener(ConnectionListenerCallback callback);
+ void RemoveConnectionListener(unsigned int conn_listener_uid);
+
+ void NotifyConnection(bool connected, const ConnectionInfo& conn_info,
+ ConnectionListenerCallback only = nullptr);
+
+ private:
+ Notifier();
+
+ void ThreadMain();
+
+ std::atomic_bool m_active;
+ std::atomic_bool m_local_notifiers;
+
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+
+ struct EntryListener {
+ EntryListener(StringRef prefix_, EntryListenerCallback callback_,
+ unsigned int flags_)
+ : prefix(prefix_), callback(callback_), flags(flags_) {}
+
+ std::string prefix;
+ EntryListenerCallback callback;
+ unsigned int flags;
+ };
+ std::vector<EntryListener> m_entry_listeners;
+ std::vector<ConnectionListenerCallback> m_conn_listeners;
+
+ struct EntryNotification {
+ EntryNotification(StringRef name_, std::shared_ptr<Value> value_,
+ unsigned int flags_, EntryListenerCallback only_)
+ : name(name_),
+ value(value_),
+ flags(flags_),
+ only(only_) {}
+
+ std::string name;
+ std::shared_ptr<Value> value;
+ unsigned int flags;
+ EntryListenerCallback only;
+ };
+ std::queue<EntryNotification> m_entry_notifications;
+
+ struct ConnectionNotification {
+ ConnectionNotification(bool connected_, const ConnectionInfo& conn_info_,
+ ConnectionListenerCallback only_)
+ : connected(connected_), conn_info(conn_info_), only(only_) {}
+
+ bool connected;
+ ConnectionInfo conn_info;
+ ConnectionListenerCallback only;
+ };
+ std::queue<ConnectionNotification> m_conn_notifications;
+
+ std::thread m_thread;
+ std::mutex m_shutdown_mutex;
+ std::condition_variable m_shutdown_cv;
+ bool m_shutdown = false;
+
+ std::function<void()> m_on_start;
+ std::function<void()> m_on_exit;
+
+ ATOMIC_STATIC_DECL(Notifier)
+ static bool s_destroyed;
+};
+
+} // namespace nt
+
+#endif // NT_NOTIFIER_H_