mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
Switches JNI to use SafeThread from WPIUtil (#282)
This commit is contained in:
committed by
Peter Johnson
parent
499da6d08d
commit
4f4c52d6d5
@@ -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<InterruptThreadJNI> {
|
||||
class InterruptJNI : public wpi::SafeThreadOwner<InterruptThreadJNI> {
|
||||
public:
|
||||
void SetFunc(JNIEnv* env, jobject func, jmethodID mid, jobject param);
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include <thread>
|
||||
#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<NotifierThreadJNI> {
|
||||
class NotifierJNI : public wpi::SafeThreadOwner<NotifierThreadJNI> {
|
||||
public:
|
||||
void SetFunc(JNIEnv *env, jobject func, jmethodID mid);
|
||||
|
||||
|
||||
@@ -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<std::mutex> lock(thr->m_mutex);
|
||||
thr->m_active = false;
|
||||
thr->m_cond.notify_one();
|
||||
}
|
||||
@@ -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 <atomic>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
// 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<std::mutex>(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<std::mutex>& GetLock() { return m_lock; }
|
||||
|
||||
protected:
|
||||
SafeThread* m_thread;
|
||||
std::unique_lock<std::mutex> m_lock;
|
||||
};
|
||||
|
||||
// A proxy for SafeThread.
|
||||
// Also serves as a scoped lock on SafeThread::m_mutex.
|
||||
template <typename T>
|
||||
class SafeThreadProxy : public SafeThreadProxyBase {
|
||||
public:
|
||||
SafeThreadProxy(SafeThread* thr) : SafeThreadProxyBase(thr) {}
|
||||
T& operator*() const { return *static_cast<T*>(m_thread); }
|
||||
T* operator->() const { return static_cast<T*>(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<SafeThread*> m_thread;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class SafeThreadOwner : public detail::SafeThreadOwnerBase {
|
||||
public:
|
||||
void Start() { Start(new T); }
|
||||
void Start(T* thr) { detail::SafeThreadOwnerBase::Start(thr); }
|
||||
|
||||
using Proxy = typename detail::SafeThreadProxy<T>;
|
||||
Proxy GetThread() { return Proxy(detail::SafeThreadOwnerBase::GetThread()); }
|
||||
};
|
||||
|
||||
//} // namespace nt
|
||||
|
||||
#endif // NT_SAFETHREAD_H_
|
||||
Reference in New Issue
Block a user