1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/synchronization/barrier.h" 16 17 #include "absl/base/internal/raw_logging.h" 18 #include "absl/synchronization/mutex.h" 19 20 namespace absl { 21 ABSL_NAMESPACE_BEGIN 22 23 // Return whether int *arg is zero. IsZero(void * arg)24static bool IsZero(void *arg) { 25 return 0 == *reinterpret_cast<int *>(arg); 26 } 27 Block()28bool Barrier::Block() { 29 MutexLock l(&this->lock_); 30 31 this->num_to_block_--; 32 if (this->num_to_block_ < 0) { 33 ABSL_RAW_LOG( 34 FATAL, 35 "Block() called too many times. num_to_block_=%d out of total=%d", 36 this->num_to_block_, this->num_to_exit_); 37 } 38 39 this->lock_.Await(Condition(IsZero, &this->num_to_block_)); 40 41 // Determine which thread can safely delete this Barrier object 42 this->num_to_exit_--; 43 ABSL_RAW_CHECK(this->num_to_exit_ >= 0, "barrier underflow"); 44 45 // If num_to_exit_ == 0 then all other threads in the barrier have 46 // exited the Wait() and have released the Mutex so this thread is 47 // free to delete the barrier. 48 return this->num_to_exit_ == 0; 49 } 50 51 ABSL_NAMESPACE_END 52 } // namespace absl 53