Austin Schuh | 36244a1 | 2019-09-21 17:52:38 -0700 | [diff] [blame^] | 1 | // |
| 2 | // Copyright 2019 The Abseil Authors. |
| 3 | // |
| 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | // you may not use this file except in compliance with the License. |
| 6 | // You may obtain a copy of the License at |
| 7 | // |
| 8 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 9 | // |
| 10 | // Unless required by applicable law or agreed to in writing, software |
| 11 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | // See the License for the specific language governing permissions and |
| 14 | // limitations under the License. |
| 15 | |
| 16 | #include "absl/flags/internal/flag.h" |
| 17 | |
| 18 | #include "absl/synchronization/mutex.h" |
| 19 | |
| 20 | namespace absl { |
| 21 | namespace flags_internal { |
| 22 | |
| 23 | // If the flag has a mutation callback this function invokes it. While the |
| 24 | // callback is being invoked the primary flag's mutex is unlocked and it is |
| 25 | // re-locked back after call to callback is completed. Callback invocation is |
| 26 | // guarded by flag's secondary mutex instead which prevents concurrent |
| 27 | // callback invocation. Note that it is possible for other thread to grab the |
| 28 | // primary lock and update flag's value at any time during the callback |
| 29 | // invocation. This is by design. Callback can get a value of the flag if |
| 30 | // necessary, but it might be different from the value initiated the callback |
| 31 | // and it also can be different by the time the callback invocation is |
| 32 | // completed. Requires that *primary_lock be held in exclusive mode; it may be |
| 33 | // released and reacquired by the implementation. |
| 34 | void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu, |
| 35 | FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu) { |
| 36 | if (!cb) return; |
| 37 | |
| 38 | // When executing the callback we need the primary flag's mutex to be |
| 39 | // unlocked so that callback can retrieve the flag's value. |
| 40 | primary_mu->Unlock(); |
| 41 | |
| 42 | { |
| 43 | absl::MutexLock lock(callback_mu); |
| 44 | cb(); |
| 45 | } |
| 46 | |
| 47 | primary_mu->Lock(); |
| 48 | } |
| 49 | |
| 50 | } // namespace flags_internal |
| 51 | } // namespace absl |