template <typename Transaction>
class ChainLock
Defined at line 69 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
ChainLock
<Transaction
> provides the environment-independent chain lock interface and protocol.
The Transaction template type specifies the envrionment-specific transaction implementation,
which provides the active transaction and debug/tracing hook interfaces.
The Transaction type must provide the following methods, which do not need to be public but must
be accessible to ChainLock
<Transaction
>:
- static Transaction* Transaction::Active()
- static Transaction* Transaction::Yield()
- static void Transaction::Accounting::OnAcquire(Transaction*)
- static void Transaction::Accounting::OnRelease(Transaction*)
- static void Transaction::Accounting::OnContention(Transaction*)
- static bool Transaction::Contention::RecordBackoffOrRetry(Token, atd::atomic
<Token
>
&
,
Transaction::ContentionState
&
)
- TransactionBase::Token Transaction::token()
ChainLockTransaction
<Transaction
> is a nearly complete transaction implementation that
environment-specific transaction types may derive from that includes additional interfaces and
affordances.
Public Methods
void ChainLock<Transaction> ()
Defined at line 73 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void ~ChainLock<Transaction> ()
Defined at line 75 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void ChainLock<Transaction> (const ChainLock<Transaction> & )
Defined at line 81 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void ChainLock<Transaction> (ChainLock<Transaction> && )
Defined at line 82 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
ChainLock<Transaction> & operator= (const ChainLock<Transaction> & )
Defined at line 83 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
ChainLock<Transaction> & operator= (ChainLock<Transaction> && )
Defined at line 84 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void AcquireFirstInChain ()
Acquires the lock without backoff, spinning until acquired. This method may be used for the
first chain lock acquired in a transaction as an optimization, since backoff is unnecessary
when no other chain locks are held.
Asserts if a cycle is detected or if any chain locks are currently held.
Defined at line 108 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
bool AcquireOrBackoff ()
Acquires the lock, spinning until acquired or returning failure because the caller should
backoff due to contention with a higher priority transaction. Returns true if the lock was
acquired or false if the current transaction should back off. Asserts if a cycle is detected.
Defined at line 131 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
bool AcquireOrResult (Result & result_out)
Acquires the lock, spinning until acquired or returning failure and backoff or cycle as an out
parameter. Returns true if the lock was acquired or false if acquiring the lock failed.
Defined at line 162 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
bool TryAcquire (AllowFinalized allow_finalized, RecordBackoff record_backoff)
Attempts to acquire the lock. Returns true if the lock was acquired or false if acquiring the
lock failed. Asserts if a cycle is detected.
Defined at line 207 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void Release ()
Releases the lock.
Defined at line 234 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void AssertHeld ()
Asserts that the lock is held by the current transaction.
Defined at line 274 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void AssertAcquired ()
Asserts that the lock is held by the current transaction and must be released by the
appropriately annotated scope.
Defined at line 285 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void MarkHeld ()
A no-op version of assert held. USE WITH EXTREME CAUTION. This tells the static analyzer that
we are holding the lock, but makes no actual runtime effort to verify this.
There are very few places where it is OK to use this method, but here are two examples.
Example 1: We just verified that we have the lock.
```
if (const ChainLock::Result res = my_obj.lock_.Acquire(token);
res != ChainLock::Result::Ok) {
return SomeError;
}
my_obj.lock_MarkHeld();
```
It is OK to skip the actual assert operations here because we just checked to make sure that
the operation succeeded. There is not much point in wasting cycles to do any more.
Example 2: The analyzer is confused about which lock is which because of some tricky code, like
a dynamic downcast.
```
Obj* GetObj(BaseClass* base) TA_REQ(base->lock_) {
DerivedClass* derived = DowncastToDerived(base);
if (derived) {
derived->lock_.MarkHeld();
derived->protected_obj_;
}
return nullptr;
}
```
In this case, we have a base class with a lock, and a derived class with a member which is
protected by the base class's lock. We are also operating in an environment where RTTI is
disabled, so we cannot use dynamic_cast. Instead, we need to write our own dynamic downcast
function using some internal mechanism to ensure that we can do so safely.
We are attempting to fetch the protected member from the derived class, but only if exists,
which is may not if the base class pointer we have does not actually point to an instance of
the derived class.
We have already statically required that the base class instance be locked, but when we perform
our downcast, the static analyzer is not smart enough to understand that base->lock_ is the
same thing as derived->lock_, we we use the no-op form of AssertHeld to satisfy it instead.
Defined at line 332 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void MarkNeedsRelease ()
Defined at line 333 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void MarkReleased ()
Complementary function to MarkNeedsRelease to assure static analysis that the lock is released.
Defined at line 336 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
bool MarkNeedsReleaseIfHeld ()
Conditionally marks the lock as held if held by the current transaction.
Defined at line 339 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
bool is_held ()
Returns true if the lock is held by the current transaction.
Defined at line 345 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
bool is_unlocked ()
Returns true if the lock is unlocked.
Defined at line 353 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
void SyncToken ()
Syncs the held token value of this lock with the current transaction token. Used for saving and
restoring state in special circumstances that use reserved tokens.
Defined at line 357 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
Token state_for_testing ()
Defined at line 363 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
Enumerations
enum Result
| Name | Value |
|---|---|
| Ok | 0 |
| Retry | 0 |
| Backoff | 0 |
| Cycle | 0 |
Defined at line 86 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
enum AllowFinalized
| Name | Value |
|---|---|
| No | 0 |
| Yes | 0 |
Defined at line 196 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h
enum RecordBackoff
| Name | Value |
|---|---|
| No | 0 |
| Yes | 0 |
Defined at line 200 of file ../../zircon/system/ulib/concurrent/include/lib/concurrent/chainlock.h