It's already allowed to prematurely release a scoped lock, now we also
allow relocking it again, possibly even in another mode.
Arguably the solution is not very elegant, but maybe that can only be
solved by comprehensive refactoring.
Differential D49885
Thread safety analysis: Allow relockable scopes aaronpuchert on Jul 26 2018, 4:05 PM. Authored by
Details It's already allowed to prematurely release a scoped lock, now we also Arguably the solution is not very elegant, but maybe that can only be
Diff Detail
Event TimelineComment Actions Imagine having a producer loop, where we check a loop condition while holding a mutex, but release it in the loop body to let other producers/consumers do their work. In that scenario it makes sense to allow "relocking" a scope. RelockableScope Scope(mu); while (WorkToDo()) { Scope.Unlock(); // Produce something... Scope.Lock(); PublishWork(); }
Comment Actions The changes look reasonable to me (after fixing a few nits), but please give @delesley a chance to weigh in before committing.
Comment Actions Committed in r339456; if @delesley has concerns with the commit, they can be addressed post-commit. Thank you for the patch! Comment Actions Hello, this patch seems introduce a new crash, and I have reverted it in r339558. Here is the minimal test case: class SCOPED_LOCKABLE FileLock { public: explicit FileLock() EXCLUSIVE_LOCK_FUNCTION(file_); ~FileLock() UNLOCK_FUNCTION(file_); //void Release() UNLOCK_FUNCTION(file_); void Lock() EXCLUSIVE_LOCK_FUNCTION(file_); Mutex file_; }; void relockShared2() { FileLock file_lock; file_lock.Lock(); } Comment Actions This didn't cross my mind, because an ACQUIRES attribute with arguments on a function other than the constructor does not add the argument locks to the set of managed mutexes. So while I'm not sure why someone would do that, it's completely possible without warning. Indeed it would be possible to have ACQUIRES both with and without arguments on the same function. Comment Actions Fix crash. The problem was that ACQUIRES with arguments did no longer have (only) this as argument, hence our assumption that we would have only ScopedLockableFactEntry's was false. So now we look a bit closer which kind of ACQUIRES we actually have. Comment Actions The case distinction in case attr::AcquireCapability is not very beautiful, but it's due to the fact that scoped capabilities are not "real" capabilities and so we need to distinguish them. What this still doesn't allow for is attributes on other classes than the scoped capability that reacquire it from the outside. So maybe this isn't the right solution, and we need to approach it in a different way. Maybe instead of modifying the BuildLockset::handleCall, we should change ThreadSafetyAnalyzer::addLock. I'll think about that, but not today.
Comment Actions Found a much simpler solution. After introducing a new virtual function HandleLock() in FactEntry, I just needed to change two lines in ThreadSafetyAnalyzer::addLock. Changes in BuildLockset::handleCall are no longer necessary. Comment Actions @aaron.ballman Maybe you can have a look again — this is much more elegant. I'm not sure why I didn't see this in the first place.
Comment Actions This looks good to me. Thanks for the patch.
|
Minor nit. Use curly braces on the if, to match the else.