blob: 344d2ca31a3fcbe33ae0b7a188a2d8bfa1df079b [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
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 */
Mark Slee9f0c6512007-02-28 23:58:26 +000019
Mark Sleef5f2be42006-09-05 21:05:31 +000020#ifndef _THRIFT_CONCURRENCY_THREAD_H_
21#define _THRIFT_CONCURRENCY_THREAD_H_ 1
Marc Slemko66949872006-07-15 01:52:39 +000022
cyy316723a2019-01-05 16:35:14 +080023#include <memory>
cyyca8af9b2019-01-11 22:13:12 +080024#include <thread>
Marc Slemko6f038a72006-08-03 18:58:09 +000025
cyyca8af9b2019-01-11 22:13:12 +080026#include <thrift/concurrency/Monitor.h>
Roger Meier12d70532011-12-14 23:35:28 +000027
Konrad Grochowski16a23a62014-11-13 15:33:38 +010028namespace apache {
29namespace thrift {
30namespace concurrency {
Marc Slemko66949872006-07-15 01:52:39 +000031
32class Thread;
33
Mark Sleef5f2be42006-09-05 21:05:31 +000034/**
Marc Slemko3a3b53b2007-05-22 23:59:54 +000035 * Minimal runnable class. More or less analogous to java.lang.Runnable.
Mark Sleef5f2be42006-09-05 21:05:31 +000036 *
Mark Sleef5f2be42006-09-05 21:05:31 +000037 * @version $Id:$
38 */
Marc Slemko66949872006-07-15 01:52:39 +000039class Runnable {
40
Konrad Grochowski16a23a62014-11-13 15:33:38 +010041public:
James E. King IIIf95620d2019-01-28 18:15:13 -050042 virtual ~Runnable() = default;
Marc Slemko66949872006-07-15 01:52:39 +000043 virtual void run() = 0;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000044
Mark Sleef5f2be42006-09-05 21:05:31 +000045 /**
46 * Gets the thread object that is hosting this runnable object - can return
Jens Geyer1a8e0482015-04-30 20:29:20 +020047 * an empty boost::shared pointer if no references remain on that thread object
Mark Sleef5f2be42006-09-05 21:05:31 +000048 */
cyy316723a2019-01-05 16:35:14 +080049 virtual std::shared_ptr<Thread> thread() { return thread_.lock(); }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000050
Mark Sleef5f2be42006-09-05 21:05:31 +000051 /**
52 * Sets the thread that is executing this object. This is only meant for
53 * use by concrete implementations of Thread.
54 */
cyy316723a2019-01-05 16:35:14 +080055 virtual void thread(std::shared_ptr<Thread> value) { thread_ = value; }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000056
Konrad Grochowski16a23a62014-11-13 15:33:38 +010057private:
cyy316723a2019-01-05 16:35:14 +080058 std::weak_ptr<Thread> thread_;
Marc Slemko66949872006-07-15 01:52:39 +000059};
60
Mark Sleef5f2be42006-09-05 21:05:31 +000061/**
Marc Slemko3a3b53b2007-05-22 23:59:54 +000062 * Minimal thread class. Returned by thread factory bound to a Runnable object
Mark Sleef5f2be42006-09-05 21:05:31 +000063 * 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
gagansodd7e1172020-04-20 03:20:05 +020066 * ThreadFactory implementations to deal with
Mark Sleef5f2be42006-09-05 21:05:31 +000067 *
T Jake Lucianib5e62212009-01-31 22:36:20 +000068 * @see apache::thrift::concurrency::ThreadFactory)
Mark Sleef5f2be42006-09-05 21:05:31 +000069 */
rglarix10f25562020-10-07 18:34:51 +020070class Thread : public std::enable_shared_from_this<Thread> {
Marc Slemko3a3b53b2007-05-22 23:59:54 +000071
Konrad Grochowski16a23a62014-11-13 15:33:38 +010072public:
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040073 typedef std::thread::id id_t;
rglarix10f25562020-10-07 18:34:51 +020074 typedef void (*thread_funct_t)(std::shared_ptr<Thread> );
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040075
cyyca8af9b2019-01-11 22:13:12 +080076 enum STATE { uninitialized, starting, started, stopping, stopped };
77
78 static void threadMain(std::shared_ptr<Thread> thread);
79
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040080 static inline bool is_current(id_t t) { return t == std::this_thread::get_id(); }
81 static inline id_t get_current() { return std::this_thread::get_id(); }
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040082
cyyca8af9b2019-01-11 22:13:12 +080083 Thread(bool detached, std::shared_ptr<Runnable> runnable)
84 : state_(uninitialized), detached_(detached) {
85 this->_runnable = runnable;
86 }
Marc Slemko3a3b53b2007-05-22 23:59:54 +000087
rglarix10f25562020-10-07 18:34:51 +020088 virtual ~Thread() {
cyyca8af9b2019-01-11 22:13:12 +080089 if (!detached_ && thread_->joinable()) {
90 try {
91 join();
92 } catch (...) {
93 // We're really hosed.
94 }
95 }
96 }
97
98 STATE getState() const
99 {
100 Synchronized sync(monitor_);
101 return state_;
102 }
103
104 void setState(STATE newState)
105 {
106 Synchronized sync(monitor_);
107 state_ = newState;
108
109 // unblock start() with the knowledge that the thread has actually
110 // started running, which avoids a race in detached threads.
111 if (newState == started) {
112 monitor_.notify();
113 }
114 }
Marc Slemko66949872006-07-15 01:52:39 +0000115
Mark Sleef5f2be42006-09-05 21:05:31 +0000116 /**
117 * Starts the thread. Does platform specific thread creation and
118 * configuration then invokes the run method of the Runnable object bound
119 * to this thread.
120 */
rglarix10f25562020-10-07 18:34:51 +0200121 virtual void start() {
cyyca8af9b2019-01-11 22:13:12 +0800122 if (getState() != uninitialized) {
123 return;
124 }
125
126 std::shared_ptr<Thread> selfRef = shared_from_this();
127 setState(starting);
128
129 Synchronized sync(monitor_);
rglarix10f25562020-10-07 18:34:51 +0200130 thread_ = std::unique_ptr<std::thread>(new std::thread(getThreadFunc(), selfRef));
cyyca8af9b2019-01-11 22:13:12 +0800131
132 if (detached_)
133 thread_->detach();
134
135 // Wait for the thread to start and get far enough to grab everything
136 // that it needs from the calling context, thus absolving the caller
137 // from being required to hold on to runnable indefinitely.
138 monitor_.wait();
139 }
Marc Slemko66949872006-07-15 01:52:39 +0000140
Mark Sleef5f2be42006-09-05 21:05:31 +0000141 /**
James E. King, IIIdf899132016-11-12 15:16:30 -0500142 * Join this thread. If this thread is joinable, the calling thread blocks
143 * until this thread completes. If the target thread is not joinable, then
144 * nothing happens.
Mark Sleef5f2be42006-09-05 21:05:31 +0000145 */
rglarix10f25562020-10-07 18:34:51 +0200146 virtual void join() {
cyyca8af9b2019-01-11 22:13:12 +0800147 if (!detached_ && state_ != uninitialized) {
148 thread_->join();
149 }
150 }
Marc Slemko66949872006-07-15 01:52:39 +0000151
Mark Sleef5f2be42006-09-05 21:05:31 +0000152 /**
Marc Slemko3a3b53b2007-05-22 23:59:54 +0000153 * Gets the thread's platform-specific ID
154 */
cyyf83d3f92019-01-12 12:53:12 +0800155 Thread::id_t getId() const { return thread_.get() ? thread_->get_id() : std::thread::id(); }
Marc Slemko3a3b53b2007-05-22 23:59:54 +0000156
157 /**
Mark Sleef5f2be42006-09-05 21:05:31 +0000158 * Gets the runnable object this thread is hosting
159 */
cyyca8af9b2019-01-11 22:13:12 +0800160 std::shared_ptr<Runnable> runnable() const { return _runnable; }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000161
rglarix10f25562020-10-07 18:34:51 +0200162protected:
163
164 virtual thread_funct_t getThreadFunc() const {
165 return threadMain;
166 }
167
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100168private:
cyy316723a2019-01-05 16:35:14 +0800169 std::shared_ptr<Runnable> _runnable;
cyyca8af9b2019-01-11 22:13:12 +0800170 std::unique_ptr<std::thread> thread_;
171 Monitor monitor_;
172 STATE state_;
James E. King, IIIdf899132016-11-12 15:16:30 -0500173 bool detached_;
Marc Slemko66949872006-07-15 01:52:39 +0000174};
Jim King5a3f8552016-04-05 12:17:51 -0400175
cyyca8af9b2019-01-11 22:13:12 +0800176
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100177}
178}
179} // apache::thrift::concurrency
Marc Slemko66949872006-07-15 01:52:39 +0000180
Mark Sleef5f2be42006-09-05 21:05:31 +0000181#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_