|
|
|
@ -169,6 +169,7 @@ class Client { |
|
|
|
|
// Must call AwaitThreadsCompletion before destructor to avoid a race
|
|
|
|
|
// between destructor and invocation of virtual ThreadFunc
|
|
|
|
|
void AwaitThreadsCompletion() { |
|
|
|
|
gpr_atm_rel_store(&thread_pool_done_, static_cast<gpr_atm>(1)); |
|
|
|
|
DestroyMultithreading(); |
|
|
|
|
std::unique_lock<std::mutex> g(thread_completion_mu_); |
|
|
|
|
while (threads_remaining_ != 0) { |
|
|
|
@ -180,6 +181,7 @@ class Client { |
|
|
|
|
bool closed_loop_; |
|
|
|
|
|
|
|
|
|
void StartThreads(size_t num_threads) { |
|
|
|
|
gpr_atm_rel_store(&thread_pool_done_, static_cast<gpr_atm>(0)); |
|
|
|
|
threads_remaining_ = num_threads; |
|
|
|
|
for (size_t i = 0; i < num_threads; i++) { |
|
|
|
|
threads_.emplace_back(new Thread(this, i)); |
|
|
|
@ -241,16 +243,11 @@ class Client { |
|
|
|
|
class Thread { |
|
|
|
|
public: |
|
|
|
|
Thread(Client* client, size_t idx) |
|
|
|
|
: done_(false), |
|
|
|
|
client_(client), |
|
|
|
|
: client_(client), |
|
|
|
|
idx_(idx), |
|
|
|
|
impl_(&Thread::ThreadFunc, this) {} |
|
|
|
|
|
|
|
|
|
~Thread() { |
|
|
|
|
{ |
|
|
|
|
std::lock_guard<std::mutex> g(mu_); |
|
|
|
|
done_ = true; |
|
|
|
|
} |
|
|
|
|
impl_.join(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -280,11 +277,14 @@ class Client { |
|
|
|
|
if (entry.used()) { |
|
|
|
|
histogram_.Add(entry.value()); |
|
|
|
|
} |
|
|
|
|
bool done = false; |
|
|
|
|
if (!thread_still_ok) { |
|
|
|
|
gpr_log(GPR_ERROR, "Finishing client thread due to RPC error"); |
|
|
|
|
done_ = true; |
|
|
|
|
done = true; |
|
|
|
|
} |
|
|
|
|
if (done_) { |
|
|
|
|
done = done || (gpr_atm_acq_load(&client_->thread_pool_done_) != |
|
|
|
|
static_cast<gpr_atm>(0)); |
|
|
|
|
if (done) { |
|
|
|
|
client_->CompleteThread(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -292,7 +292,6 @@ class Client { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::mutex mu_; |
|
|
|
|
bool done_; |
|
|
|
|
Histogram histogram_; |
|
|
|
|
Client* client_; |
|
|
|
|
const size_t idx_; |
|
|
|
@ -305,6 +304,7 @@ class Client { |
|
|
|
|
InterarrivalTimer interarrival_timer_; |
|
|
|
|
std::vector<gpr_timespec> next_time_; |
|
|
|
|
|
|
|
|
|
gpr_atm thread_pool_done_; |
|
|
|
|
std::mutex thread_completion_mu_; |
|
|
|
|
size_t threads_remaining_; |
|
|
|
|
std::condition_variable threads_complete_; |
|
|
|
|