blob: 3a906bd9c5f77f08e2d1d6bedf8ebf0eebe521a2 [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2015-2019 FIRST. 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#include "wpi/SafeThread.h"
9
10using namespace wpi;
11
12detail::SafeThreadProxyBase::SafeThreadProxyBase(
13 std::shared_ptr<SafeThread> thr)
14 : m_thread(std::move(thr)) {
15 if (!m_thread) return;
16 m_lock = std::unique_lock<wpi::mutex>(m_thread->m_mutex);
17 if (!m_thread->m_active) {
18 m_lock.unlock();
19 m_thread = nullptr;
20 return;
21 }
22}
23
24detail::SafeThreadOwnerBase::~SafeThreadOwnerBase() {
25 if (m_joinAtExit)
26 Join();
27 else
28 Stop();
29}
30
31void detail::SafeThreadOwnerBase::Start(std::shared_ptr<SafeThread> thr) {
32 std::scoped_lock lock(m_mutex);
33 if (auto thr = m_thread.lock()) return;
34 m_stdThread = std::thread([=] { thr->Main(); });
35 thr->m_threadId = m_stdThread.get_id();
36 m_thread = thr;
37}
38
39void detail::SafeThreadOwnerBase::Stop() {
40 std::scoped_lock lock(m_mutex);
41 if (auto thr = m_thread.lock()) {
42 thr->m_active = false;
43 thr->m_cond.notify_all();
44 m_thread.reset();
45 }
46 if (m_stdThread.joinable()) m_stdThread.detach();
47}
48
49void detail::SafeThreadOwnerBase::Join() {
50 std::unique_lock lock(m_mutex);
51 if (auto thr = m_thread.lock()) {
52 auto stdThread = std::move(m_stdThread);
53 m_thread.reset();
54 lock.unlock();
55 thr->m_active = false;
56 thr->m_cond.notify_all();
57 stdThread.join();
58 } else if (m_stdThread.joinable()) {
59 m_stdThread.detach();
60 }
61}
62
63void detail::swap(SafeThreadOwnerBase& lhs, SafeThreadOwnerBase& rhs) noexcept {
64 using std::swap;
65 if (&lhs == &rhs) return;
66 std::scoped_lock lock(lhs.m_mutex, rhs.m_mutex);
67 std::swap(lhs.m_stdThread, rhs.m_stdThread);
68 std::swap(lhs.m_thread, rhs.m_thread);
69}
70
71detail::SafeThreadOwnerBase::operator bool() const {
72 std::scoped_lock lock(m_mutex);
73 return !m_thread.expired();
74}
75
76std::thread::native_handle_type
77detail::SafeThreadOwnerBase::GetNativeThreadHandle() {
78 std::scoped_lock lock(m_mutex);
79 return m_stdThread.native_handle();
80}
81
82std::shared_ptr<SafeThread> detail::SafeThreadOwnerBase::GetThreadSharedPtr()
83 const {
84 std::scoped_lock lock(m_mutex);
85 return m_thread.lock();
86}