]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/cpp/src/thrift/concurrency/Thread.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / thrift / lib / cpp / src / thrift / concurrency / Thread.h
CommitLineData
f67539c2
TL
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#ifndef _THRIFT_CONCURRENCY_THREAD_H_
21#define _THRIFT_CONCURRENCY_THREAD_H_ 1
22
23#include <memory>
24#include <thread>
25
26#include <thrift/concurrency/Monitor.h>
27
28namespace apache {
29namespace thrift {
30namespace concurrency {
31
32class Thread;
33
34/**
35 * Minimal runnable class. More or less analogous to java.lang.Runnable.
36 *
37 * @version $Id:$
38 */
39class Runnable {
40
41public:
42 virtual ~Runnable() = default;
43 virtual void run() = 0;
44
45 /**
46 * Gets the thread object that is hosting this runnable object - can return
47 * an empty boost::shared pointer if no references remain on that thread object
48 */
49 virtual std::shared_ptr<Thread> thread() { return thread_.lock(); }
50
51 /**
52 * Sets the thread that is executing this object. This is only meant for
53 * use by concrete implementations of Thread.
54 */
55 virtual void thread(std::shared_ptr<Thread> value) { thread_ = value; }
56
57private:
58 std::weak_ptr<Thread> thread_;
59};
60
61/**
62 * Minimal thread class. Returned by thread factory bound to a Runnable object
63 * and ready to start execution. More or less analogous to java.lang.Thread
64 * (minus all the thread group, priority, mode and other baggage, since that
65 * is difficult to abstract across platforms and is left for platform-specific
66 * ThreadFactory implemtations to deal with
67 *
68 * @see apache::thrift::concurrency::ThreadFactory)
69 */
70class Thread final : public std::enable_shared_from_this<Thread> {
71
72public:
73 typedef std::thread::id id_t;
74
75 enum STATE { uninitialized, starting, started, stopping, stopped };
76
77 static void threadMain(std::shared_ptr<Thread> thread);
78
79 static inline bool is_current(id_t t) { return t == std::this_thread::get_id(); }
80 static inline id_t get_current() { return std::this_thread::get_id(); }
81
82 Thread(bool detached, std::shared_ptr<Runnable> runnable)
83 : state_(uninitialized), detached_(detached) {
84 this->_runnable = runnable;
85 }
86
87 ~Thread() {
88 if (!detached_ && thread_->joinable()) {
89 try {
90 join();
91 } catch (...) {
92 // We're really hosed.
93 }
94 }
95 }
96
97 STATE getState() const
98 {
99 Synchronized sync(monitor_);
100 return state_;
101 }
102
103 void setState(STATE newState)
104 {
105 Synchronized sync(monitor_);
106 state_ = newState;
107
108 // unblock start() with the knowledge that the thread has actually
109 // started running, which avoids a race in detached threads.
110 if (newState == started) {
111 monitor_.notify();
112 }
113 }
114
115 /**
116 * Starts the thread. Does platform specific thread creation and
117 * configuration then invokes the run method of the Runnable object bound
118 * to this thread.
119 */
120 void start() {
121 if (getState() != uninitialized) {
122 return;
123 }
124
125 std::shared_ptr<Thread> selfRef = shared_from_this();
126 setState(starting);
127
128 Synchronized sync(monitor_);
129 thread_ = std::unique_ptr<std::thread>(new std::thread(threadMain, selfRef));
130
131 if (detached_)
132 thread_->detach();
133
134 // Wait for the thread to start and get far enough to grab everything
135 // that it needs from the calling context, thus absolving the caller
136 // from being required to hold on to runnable indefinitely.
137 monitor_.wait();
138 }
139
140 /**
141 * Join this thread. If this thread is joinable, the calling thread blocks
142 * until this thread completes. If the target thread is not joinable, then
143 * nothing happens.
144 */
145 void join() {
146 if (!detached_ && state_ != uninitialized) {
147 thread_->join();
148 }
149 }
150
151 /**
152 * Gets the thread's platform-specific ID
153 */
154 Thread::id_t getId() const { return thread_.get() ? thread_->get_id() : std::thread::id(); }
155
156 /**
157 * Gets the runnable object this thread is hosting
158 */
159 std::shared_ptr<Runnable> runnable() const { return _runnable; }
160
161private:
162 std::shared_ptr<Runnable> _runnable;
163 std::unique_ptr<std::thread> thread_;
164 Monitor monitor_;
165 STATE state_;
166 bool detached_;
167};
168
169
170}
171}
172} // apache::thrift::concurrency
173
174#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_