WPILibC++  unspecified
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
SafeThread.h
1 /*----------------------------------------------------------------------------*/
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_SAFETHREAD_H_
9 #define NT_SAFETHREAD_H_
10 
11 #include <atomic>
12 #include <condition_variable>
13 #include <mutex>
14 #include <thread>
15 
16 namespace nt {
17 
18 // Base class for SafeThreadOwner threads.
19 class SafeThread {
20  public:
21  virtual ~SafeThread() = default;
22  virtual void Main() = 0;
23 
24  std::mutex m_mutex;
25  bool m_active = true;
26  std::condition_variable m_cond;
27 };
28 
29 namespace detail {
30 
31 // Non-template proxy base class for common proxy code.
33  public:
34  SafeThreadProxyBase(SafeThread* thr) : m_thread(thr) {
35  if (!m_thread) return;
36  std::unique_lock<std::mutex>(m_thread->m_mutex).swap(m_lock);
37  if (!m_thread->m_active) {
38  m_lock.unlock();
39  m_thread = nullptr;
40  return;
41  }
42  }
43  explicit operator bool() const { return m_thread != nullptr; }
44  std::unique_lock<std::mutex>& GetLock() { return m_lock; }
45 
46  protected:
47  SafeThread* m_thread;
48  std::unique_lock<std::mutex> m_lock;
49 };
50 
51 // A proxy for SafeThread.
52 // Also serves as a scoped lock on SafeThread::m_mutex.
53 template <typename T>
55  public:
57  T& operator*() const { return *static_cast<T*>(m_thread); }
58  T* operator->() const { return static_cast<T*>(m_thread); }
59 };
60 
61 // Non-template owner base class for common owner code.
63  public:
64  void Stop();
65 
66  protected:
67  SafeThreadOwnerBase() { m_thread = nullptr; }
69  SafeThreadOwnerBase& operator=(const SafeThreadOwnerBase&) = delete;
70  ~SafeThreadOwnerBase() { Stop(); }
71 
72  void Start(SafeThread* thr);
73  SafeThread* GetThread() { return m_thread.load(); }
74 
75  private:
76  std::atomic<SafeThread*> m_thread;
77 };
78 
79 } // namespace detail
80 
81 template <typename T>
83  public:
84  void Start() { Start(new T); }
85  void Start(T* thr) { detail::SafeThreadOwnerBase::Start(thr); }
86 
87  using Proxy = typename detail::SafeThreadProxy<T>;
88  Proxy GetThread() { return Proxy(detail::SafeThreadOwnerBase::GetThread()); }
89 };
90 
91 } // namespace nt
92 
93 #endif // NT_SAFETHREAD_H_
Definition: SafeThread.h:82
Definition: SafeThread.h:19
Definition: SafeThread.h:54
Definition: SafeThread.h:32
Definition: SafeThread.h:62