00001 // Copyright 2017 The Abseil Authors. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "absl/synchronization/barrier.h" 00016 00017 #include "absl/base/internal/raw_logging.h" 00018 #include "absl/synchronization/mutex.h" 00019 00020 namespace absl { 00021 00022 // Return whether int *arg is zero. 00023 static bool IsZero(void *arg) { 00024 return 0 == *reinterpret_cast<int *>(arg); 00025 } 00026 00027 bool Barrier::Block() { 00028 MutexLock l(&this->lock_); 00029 00030 this->num_to_block_--; 00031 if (this->num_to_block_ < 0) { 00032 ABSL_RAW_LOG( 00033 FATAL, 00034 "Block() called too many times. num_to_block_=%d out of total=%d", 00035 this->num_to_block_, this->num_to_exit_); 00036 } 00037 00038 this->lock_.Await(Condition(IsZero, &this->num_to_block_)); 00039 00040 // Determine which thread can safely delete this Barrier object 00041 this->num_to_exit_--; 00042 ABSL_RAW_CHECK(this->num_to_exit_ >= 0, "barrier underflow"); 00043 00044 // If num_to_exit_ == 0 then all other threads in the barrier have 00045 // exited the Wait() and have released the Mutex so this thread is 00046 // free to delete the barrier. 00047 return this->num_to_exit_ == 0; 00048 } 00049 00050 } // namespace absl