3 ms·
These analysis passes also work just fine with scoped locks, using the SCOPE_CAPABILITY annotation (see the included mutex.h example). Scoped locks by themselv
by aseipp 10y ago
These analysis passes also work just fine with scoped locks, using the SCOPE_CAPABILITY annotation (see the included mutex.h example).
Scoped locks by themselves cannot statically rule out the same kinds of errors that this analysis can, in any case. Even if you only use scoped locks -- an obvious (but trivial) example is when you have a lock held but then attempt to take a lock again in some control path (perhaps through a recursive or deep call stack, or, in your case, calling another member function which also takes the lock unconditionally.) This is a trivial case for this analysis to detect but std::lock_guard<> alone will not save you.
The annotations also serve as useful commentary and 'guiding tools' for refactoring as well, in my experience. If you annotate a function as yielding or taking a lock, and later change this -- the compiler will warn you that your annotation is out of sync with the implementation. In practice I find this quite useful to keep code clean, but it also obviously helps tell you if your change is correct, too.
I normally just turn this analysis on in Clang, because IME it has very little negative effect and is very useful in practice.
- duneroadrunner 10y ago> when you have a lock held but then attempt to take a lock again in some control path (perhaps through a recursive or deep call stack, or, in your case, calling another member function The standard library provides std::recursive_mutex which supports being locked multiple times by the same thread. Unfortunately, it doesn't provide an std::recursive_shared_timed_mutex for the general case where you might want to support multiple simultaneous read operations. The SaferCPlusPlus library does implement such a mutex, and, like I mentioned in another comment, provides data types that automatically control access to shared objects. I think for most cases, it's the safest and easiest way to share objects asynchronously (in C++). (The data types are kind of analogous to Arc<> and Arc< Mutex<> > for those familiar with Rust.) Btw, the implementation is self-contained, so you can use the safe sharing data types without having to include the rest of the library. Or you can just copy the source code and make your own safe sharing data types.
- aseipp 10y agoThere are many people who would largely consider recursive mutexes a complete mistake, for the most part. I'm one of those people. :) But I admit I sort of willfully skipped over this point precisely because I dislike recursive mutexes. But they are there for this case, you are 100% right.