From 4f4c52d6d5db76b4a2ce250c3abe8ae5cac1d93b Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 23 Oct 2016 14:18:46 -0700 Subject: [PATCH] Switches JNI to use SafeThread from WPIUtil (#282) --- wpilibj/src/athena/cpp/lib/InterruptJNI.cpp | 6 +- wpilibj/src/athena/cpp/lib/NotifierJNI.cpp | 6 +- wpilibj/src/athena/cpp/lib/SafeThread.cpp | 31 ------- wpilibj/src/athena/cpp/lib/SafeThread.h | 93 --------------------- 4 files changed, 6 insertions(+), 130 deletions(-) delete mode 100644 wpilibj/src/athena/cpp/lib/SafeThread.cpp delete mode 100644 wpilibj/src/athena/cpp/lib/SafeThread.h diff --git a/wpilibj/src/athena/cpp/lib/InterruptJNI.cpp b/wpilibj/src/athena/cpp/lib/InterruptJNI.cpp index 3f11ccbc09..fc69c0e718 100644 --- a/wpilibj/src/athena/cpp/lib/InterruptJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/InterruptJNI.cpp @@ -15,8 +15,8 @@ #include "HAL/Interrupts.h" #include "HALUtil.h" -#include "SafeThread.h" #include "edu_wpi_first_wpilibj_hal_InterruptJNI.h" +#include "support/SafeThread.h" TLogLevel interruptJNILogLevel = logERROR; @@ -38,7 +38,7 @@ TLogLevel interruptJNILogLevel = logERROR; // // We don't want to use a FIFO here. If the user code takes too long to // process, we will just ignore the redundant wakeup. -class InterruptThreadJNI : public SafeThread { +class InterruptThreadJNI : public wpi::SafeThread { public: void Main(); @@ -49,7 +49,7 @@ class InterruptThreadJNI : public SafeThread { jobject m_param = nullptr; }; -class InterruptJNI : public SafeThreadOwner { +class InterruptJNI : public wpi::SafeThreadOwner { public: void SetFunc(JNIEnv* env, jobject func, jmethodID mid, jobject param); diff --git a/wpilibj/src/athena/cpp/lib/NotifierJNI.cpp b/wpilibj/src/athena/cpp/lib/NotifierJNI.cpp index bb8bed3627..344ef49b41 100644 --- a/wpilibj/src/athena/cpp/lib/NotifierJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/NotifierJNI.cpp @@ -16,8 +16,8 @@ #include #include "HALUtil.h" #include "HAL/cpp/Log.h" -#include "SafeThread.h" #include "edu_wpi_first_wpilibj_hal_NotifierJNI.h" +#include "support/SafeThread.h" // set the logging level TLogLevel notifierJNILogLevel = logWARNING; @@ -40,7 +40,7 @@ TLogLevel notifierJNILogLevel = logWARNING; // // We don't want to use a FIFO here. If the user code takes too long to // process, we will just ignore the redundant wakeup. -class NotifierThreadJNI : public SafeThread { +class NotifierThreadJNI : public wpi::SafeThread { public: void Main(); @@ -50,7 +50,7 @@ class NotifierThreadJNI : public SafeThread { uint64_t m_currentTime; }; -class NotifierJNI : public SafeThreadOwner { +class NotifierJNI : public wpi::SafeThreadOwner { public: void SetFunc(JNIEnv *env, jobject func, jmethodID mid); diff --git a/wpilibj/src/athena/cpp/lib/SafeThread.cpp b/wpilibj/src/athena/cpp/lib/SafeThread.cpp deleted file mode 100644 index ca931a6db6..0000000000 --- a/wpilibj/src/athena/cpp/lib/SafeThread.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) FIRST 2015-2016. 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. */ -/*----------------------------------------------------------------------------*/ - -#include "SafeThread.h" - -// using namespace nt; - -void detail::SafeThreadOwnerBase::Start(SafeThread* thr) { - SafeThread* curthr = nullptr; - SafeThread* newthr = thr; - if (!m_thread.compare_exchange_strong(curthr, newthr)) { - delete newthr; - return; - } - std::thread([=]() { - newthr->Main(); - delete newthr; - }).detach(); -} - -void detail::SafeThreadOwnerBase::Stop() { - SafeThread* thr = m_thread.exchange(nullptr); - if (!thr) return; - std::lock_guard lock(thr->m_mutex); - thr->m_active = false; - thr->m_cond.notify_one(); -} diff --git a/wpilibj/src/athena/cpp/lib/SafeThread.h b/wpilibj/src/athena/cpp/lib/SafeThread.h deleted file mode 100644 index b20c83bc76..0000000000 --- a/wpilibj/src/athena/cpp/lib/SafeThread.h +++ /dev/null @@ -1,93 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) FIRST 2015-2016. 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_SAFETHREAD_H_ -#define NT_SAFETHREAD_H_ - -#include -#include -#include -#include - -// namespace nt { - -// Base class for SafeThreadOwner threads. -class SafeThread { - public: - virtual ~SafeThread() = default; - virtual void Main() = 0; - - std::mutex m_mutex; - bool m_active = true; - std::condition_variable m_cond; -}; - -namespace detail { - -// Non-template proxy base class for common proxy code. -class SafeThreadProxyBase { - public: - SafeThreadProxyBase(SafeThread* thr) : m_thread(thr) { - if (!m_thread) return; - std::unique_lock(m_thread->m_mutex).swap(m_lock); - if (!m_thread->m_active) { - m_lock.unlock(); - m_thread = nullptr; - return; - } - } - explicit operator bool() const { return m_thread != nullptr; } - std::unique_lock& GetLock() { return m_lock; } - - protected: - SafeThread* m_thread; - std::unique_lock m_lock; -}; - -// A proxy for SafeThread. -// Also serves as a scoped lock on SafeThread::m_mutex. -template -class SafeThreadProxy : public SafeThreadProxyBase { - public: - SafeThreadProxy(SafeThread* thr) : SafeThreadProxyBase(thr) {} - T& operator*() const { return *static_cast(m_thread); } - T* operator->() const { return static_cast(m_thread); } -}; - -// Non-template owner base class for common owner code. -class SafeThreadOwnerBase { - public: - void Stop(); - - protected: - SafeThreadOwnerBase() { m_thread = nullptr; } - SafeThreadOwnerBase(const SafeThreadOwnerBase&) = delete; - SafeThreadOwnerBase& operator=(const SafeThreadOwnerBase&) = delete; - ~SafeThreadOwnerBase() { Stop(); } - - void Start(SafeThread* thr); - SafeThread* GetThread() { return m_thread.load(); } - - private: - std::atomic m_thread; -}; - -} // namespace detail - -template -class SafeThreadOwner : public detail::SafeThreadOwnerBase { - public: - void Start() { Start(new T); } - void Start(T* thr) { detail::SafeThreadOwnerBase::Start(thr); } - - using Proxy = typename detail::SafeThreadProxy; - Proxy GetThread() { return Proxy(detail::SafeThreadOwnerBase::GetThread()); } -}; - -//} // namespace nt - -#endif // NT_SAFETHREAD_H_