blob: 0f4035819cdbd00a72654d42feb0b26b7c664c23 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001//
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
20namespace absl {
21namespace 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.
34void 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