blob: 52ac70077e372ef6ec21eacfbcae461ef5c82969 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2015-2018 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::lock_guard<wpi::mutex> lock(m_mutex);
33 if (auto thr = m_thread.lock()) return;
34 m_stdThread = std::thread([=] { thr->Main(); });
35 m_thread = thr;
36}
37
38void detail::SafeThreadOwnerBase::Stop() {
39 std::lock_guard<wpi::mutex> lock(m_mutex);
40 if (auto thr = m_thread.lock()) {
41 thr->m_active = false;
42 thr->m_cond.notify_all();
43 m_thread.reset();
44 }
45 if (m_stdThread.joinable()) m_stdThread.detach();
46}
47
48void detail::SafeThreadOwnerBase::Join() {
49 std::unique_lock<wpi::mutex> lock(m_mutex);
50 if (auto thr = m_thread.lock()) {
51 auto stdThread = std::move(m_stdThread);
52 m_thread.reset();
53 lock.unlock();
54 thr->m_active = false;
55 thr->m_cond.notify_all();
56 stdThread.join();
57 } else if (m_stdThread.joinable()) {
58 m_stdThread.detach();
59 }
60}
61
62void detail::swap(SafeThreadOwnerBase& lhs, SafeThreadOwnerBase& rhs) noexcept {
63 using std::swap;
64 if (&lhs == &rhs) return;
65 std::lock(lhs.m_mutex, rhs.m_mutex);
66 std::lock_guard<wpi::mutex> lock_lhs(lhs.m_mutex, std::adopt_lock);
67 std::lock_guard<wpi::mutex> lock_rhs(rhs.m_mutex, std::adopt_lock);
68 std::swap(lhs.m_stdThread, rhs.m_stdThread);
69 std::swap(lhs.m_thread, rhs.m_thread);
70}
71
72detail::SafeThreadOwnerBase::operator bool() const {
73 std::lock_guard<wpi::mutex> lock(m_mutex);
74 return !m_thread.expired();
75}
76
77std::thread::native_handle_type
78detail::SafeThreadOwnerBase::GetNativeThreadHandle() {
79 std::lock_guard<wpi::mutex> lock(m_mutex);
80 return m_stdThread.native_handle();
81}
82
83std::shared_ptr<SafeThread> detail::SafeThreadOwnerBase::GetThread() const {
84 std::lock_guard<wpi::mutex> lock(m_mutex);
85 return m_thread.lock();
86}