// // Copyright 2019 The Abseil 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 // // https://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. #include "absl/flags/internal/flag.h" #include "absl/synchronization/mutex.h" namespace absl { namespace flags_internal { // If the flag has a mutation callback this function invokes it. While the // callback is being invoked the primary flag's mutex is unlocked and it is // re-locked back after call to callback is completed. Callback invocation is // guarded by flag's secondary mutex instead which prevents concurrent // callback invocation. Note that it is possible for other thread to grab the // primary lock and update flag's value at any time during the callback // invocation. This is by design. Callback can get a value of the flag if // necessary, but it might be different from the value initiated the callback // and it also can be different by the time the callback invocation is // completed. Requires that *primary_lock be held in exclusive mode; it may be // released and reacquired by the implementation. void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu, FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu) { if (!cb) return; // When executing the callback we need the primary flag's mutex to be // unlocked so that callback can retrieve the flag's value. primary_mu->Unlock(); { absl::MutexLock lock(callback_mu); cb(); } primary_mu->Lock(); } } // namespace flags_internal } // namespace absl