But given that, it makes sense to use AssertLockHeld
instead of WeaklyAssertLockHeld
to provide runtime checking inside a lambda annotated with EXCLUSIVE_LOCKS_REQUIRED
called through a std::function
Both the current LockAssertion
and your proposed WeaklyAssertLockHeld
do runtime checking, so there’s no advantage there.
I don’t think AssertLockHeld in lambdas ever makes much sense: there are two ways to use lambdas – one where thread safety annotations work as expected, and one where they’re broken because the lambda’s a callback passed to an unannotated function. In the former case you’re writing:
0 LOCK(cs);
1 [&]() EXCLUSIVE_LOCKS_REQUIRED(cs) { ++foo; }();
where it’s already obvious that cs
is held when the lambda is called, and you’re just adding the annotation to make the compiler happy.
In the latter case, you’re writing:
0 LOCK(cs_main);
1 connman->ForEachNode([&](CNode* pnode) {
2 WeaklyAssertLockHeld(cs_main);
3 ...
4 });
because you can’t pass the fact that cs_main
is still held through the un-annotated ForEachNode
.
inside an overridden virtual method annotated EXCLUSIVE_LOCKS_REQUIRED
called through a base method which is not annotated.
I think that is something we should go out of our way to avoid. Either the base method should be annotated as requiring the lock, or the overriding method should acquire the lock itself – with annotations, locking is part of the function signature, and you shouldn’t change the signature when overriding a method. We don’t have any code like this now, and I don’t think there’s any reason ever to, so I’m not sure it’s worth addressing it explicitly, but if we are, better to discourage it outright.