The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.3 KiB
134 lines
4.3 KiB
/* |
|
* |
|
* Copyright 2015 gRPC authors. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*/ |
|
|
|
#ifndef GRPC_CORE_LIB_GPRPP_THD_H |
|
#define GRPC_CORE_LIB_GPRPP_THD_H |
|
|
|
/** Internal thread interface. */ |
|
|
|
#include <grpc/support/port_platform.h> |
|
|
|
#include <grpc/support/log.h> |
|
#include <grpc/support/sync.h> |
|
#include <grpc/support/thd_id.h> |
|
#include <grpc/support/time.h> |
|
|
|
#include "src/core/lib/gprpp/abstract.h" |
|
#include "src/core/lib/gprpp/memory.h" |
|
|
|
namespace grpc_core { |
|
namespace internal { |
|
|
|
/// Base class for platform-specific thread-state |
|
class ThreadInternalsInterface { |
|
public: |
|
virtual ~ThreadInternalsInterface() {} |
|
virtual void Start() GRPC_ABSTRACT; |
|
virtual void Join() GRPC_ABSTRACT; |
|
GRPC_ABSTRACT_BASE_CLASS |
|
}; |
|
} // namespace internal |
|
|
|
class Thread { |
|
public: |
|
/// Default constructor only to allow use in structs that lack constructors |
|
/// Does not produce a validly-constructed thread; must later |
|
/// use placement new to construct a real thread. Does not init mu_ and cv_ |
|
Thread() : state_(FAKE), impl_(nullptr) {} |
|
|
|
/// Normal constructor to create a thread with name \a thd_name, |
|
/// which will execute a thread based on function \a thd_body |
|
/// with argument \a arg once it is started. |
|
/// The optional \a success argument indicates whether the thread |
|
/// is successfully created. |
|
Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg, |
|
bool* success = nullptr); |
|
|
|
/// Move constructor for thread. After this is called, the other thread |
|
/// no longer represents a living thread object |
|
Thread(Thread&& other) : state_(other.state_), impl_(other.impl_) { |
|
other.state_ = MOVED; |
|
other.impl_ = nullptr; |
|
} |
|
|
|
/// Move assignment operator for thread. After this is called, the other |
|
/// thread no longer represents a living thread object. Not allowed if this |
|
/// thread actually exists |
|
Thread& operator=(Thread&& other) { |
|
if (this != &other) { |
|
// TODO(vjpai): if we can be sure that all Thread's are actually |
|
// constructed, then we should assert GPR_ASSERT(impl_ == nullptr) here. |
|
// However, as long as threads come in structures that are |
|
// allocated via gpr_malloc, this will not be the case, so we cannot |
|
// assert it for the time being. |
|
state_ = other.state_; |
|
impl_ = other.impl_; |
|
other.state_ = MOVED; |
|
other.impl_ = nullptr; |
|
} |
|
return *this; |
|
} |
|
|
|
/// The destructor is strictly optional; either the thread never came to life |
|
/// and the constructor itself killed it or it has already been joined and |
|
/// the Join function kills it. The destructor shouldn't have to do anything. |
|
~Thread() { GPR_ASSERT(impl_ == nullptr); } |
|
|
|
void Start() { |
|
if (impl_ != nullptr) { |
|
GPR_ASSERT(state_ == ALIVE); |
|
state_ = STARTED; |
|
impl_->Start(); |
|
} else { |
|
GPR_ASSERT(state_ == FAILED); |
|
} |
|
}; |
|
void Join() { |
|
if (impl_ != nullptr) { |
|
GPR_ASSERT(state_ == STARTED); |
|
impl_->Join(); |
|
grpc_core::Delete(impl_); |
|
state_ = DONE; |
|
impl_ = nullptr; |
|
} else { |
|
GPR_ASSERT(state_ == FAILED); |
|
} |
|
}; |
|
|
|
static void Init(); |
|
static bool AwaitAll(gpr_timespec deadline); |
|
|
|
private: |
|
Thread(const Thread&) = delete; |
|
Thread& operator=(const Thread&) = delete; |
|
|
|
/// The thread states are as follows: |
|
/// FAKE -- just a dummy placeholder Thread created by the default constructor |
|
/// ALIVE -- an actual thread of control exists associated with this thread |
|
/// STARTED -- the thread of control has been started |
|
/// DONE -- the thread of control has completed and been joined |
|
/// FAILED -- the thread of control never came alive |
|
/// MOVED -- contents were moved out and we're no longer tracking them |
|
enum ThreadState { FAKE, ALIVE, STARTED, DONE, FAILED, MOVED }; |
|
ThreadState state_; |
|
internal::ThreadInternalsInterface* impl_; |
|
}; |
|
|
|
} // namespace grpc_core |
|
|
|
#endif /* GRPC_CORE_LIB_GPRPP_THD_H */
|
|
|