TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

In the C++ bag of tricks: scoped locks

43 pointsby s_kanevover 11 years ago

17 comments

vinkelhakeover 11 years ago
The real advantage of a scoped lock is that it promises to release the mutex, no matter how the scope is exited. If this LOCKED macro is used and an exception is thrown from within the block, that mutex now stays locked.<p>&gt; The only gotcha is, there is some overhead involved in this approach. The class instance takes up some space on the stack (several bytes) for every lock acquisition.<p>Not so fast. A decent compiler will eliminate the overhead and not actually allocate stack space for the lock. Here&#x27;s an example using one of the lock guards in C++:<p><pre><code> struct foo { int var; std::mutex m; }; void process1(foo&amp; f) { std::lock_guard&lt;std::mutex&gt; lock(f.m); ++f.var; } void process2(foo&amp; f) { f.m.lock(); ++f.var; f.m.unlock(); } </code></pre> GCC 4.8.1 generates identical code for process1 and process2.
评论 #7197636 未加载
评论 #7197470 未加载
评论 #7197532 未加载
评论 #7197474 未加载
fighterjetover 11 years ago
I fail to see the point of using a macro (ew) to accomplish something that&#x27;s included, with several different implementations, in the c++11 standard library
taway2012over 11 years ago
Don&#x27;t do this. The whole thing gave off a bad smell on first reading so I would never have done this.<p>Thank you vinkelhake for nailing the the real problem (exceptions) and bothering to check whether the stack overhead really exists.<p>Just wanted to chime in with a comment because HN doesn&#x27;t show vote counts, so future readers will &quot;see&quot; my upvote on vinkelhake&#x27;s comment.
jacobparkerover 11 years ago
Exception issues aside, an odd definition of &quot;scoped&quot;. A very non-C++ solution. Use RAII and lock_guard (if possible) as vinkelhake demonstrates. Consider,<p><pre><code> LOCKED(lk_var) { return 42; &#x2F;&#x2F; whoops }</code></pre>
VikingCoderover 11 years ago
You&#x27;re also consuming the variable name i, which everyone else is probably using.<p>Speaking of which, this means you can&#x27;t have one of your locks scoped inside another one.
评论 #7198442 未加载
评论 #7198063 未加载
steveklabnikover 11 years ago
This kind of thing is one area I&#x27;m excited to see work in Rust: you can use Rust&#x27;s safety guarantees to ensure that all access goes through the lock.
JoeAltmaierover 11 years ago
Works, but requires {} for scope. The local-object version can be scoped however you like. It optimizes away just fine, similar to the for loop.
ef47d35620c1over 11 years ago
C++11 has scoped locks built-in, doesn&#x27;t it?
评论 #7197555 未加载
infogulchover 11 years ago
What about:<p><pre><code> #define LOCKED(lk) for(int i=lk_lock(lk); i == 0; lk_unlock(lk), i++) </code></pre> Probably better to test for 0 exactly, in case it fails. You don&#x27;t want it to unlock twice just because it returns -1.
评论 #7198197 未加载
8_hours_agoover 11 years ago
A very important gotcha with this approach is that any variable named &quot;i&quot; will be reset to 0 inside of the lock, and modifying &quot;i&quot; inside of the lock can cause an infinite loop.<p>This can be mitigated by generating a unique variable name with the C preprocessor: <a href="http://stackoverflow.com/questions/1132751/how-can-i-generate-unique-values-in-the-c-preprocessor" rel="nofollow">http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1132751&#x2F;how-can-i-generat...</a><p>That being said, it&#x27;s much better to use a standard method of scoped locking instead of trying to reinvent the wheel.
ambrop7over 11 years ago
I learned about the for loop hack from avr-libc[1][2]. It even does some preprocessor abuse to implement different kinds of atomic and non-atomic sections.<p>[1] <a href="http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html" rel="nofollow">http:&#x2F;&#x2F;www.nongnu.org&#x2F;avr-libc&#x2F;user-manual&#x2F;group__util__atom...</a><p>[2] <a href="http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/util/atomic.h?root=avr-libc&amp;view=markup" rel="nofollow">http:&#x2F;&#x2F;svn.savannah.nongnu.org&#x2F;viewvc&#x2F;trunk&#x2F;avr-libc&#x2F;include...</a>
mojubaover 11 years ago
Wouldn&#x27;t this be exception-safe, provided lock_iter defines a ctor, dtor, operator bool() and operator ++()?<p><pre><code> #define LOCKED(lk) for (lock_iter i = lk; i; i++) </code></pre> (Edit: I thought lock_iter could be an empty class but no, it can not, so I edited my post. lock_iter will have an internal flag that should be optimized away following the same logic int i is optimized in the OP&#x27;s version)
skaover 11 years ago
People have already pointed out the specific problems with this approach so I won&#x27;t repeat them.<p>It&#x27;s worth reiterating, though: If you are writing c++ these days and find yourself reaching for a preprocessor macro, I think that&#x27;s a good sign you should think really carefully about what you are actually trying to do. Chances are really good there is a (much) better way.
dllthomasover 11 years ago
You can do some of this with the cleanup attribute in GCC, although it doesn&#x27;t trigger in the case of a longjmp.
评论 #7197575 未加载
评论 #7198497 未加载
评论 #7198435 未加载
cbsmithover 11 years ago
Boost.Scopexit addresses this point pretty well I think: <a href="http://www.boost.org/doc/libs/1_55_0/libs/scope_exit/doc/html/index.html" rel="nofollow">http:&#x2F;&#x2F;www.boost.org&#x2F;doc&#x2F;libs&#x2F;1_55_0&#x2F;libs&#x2F;scope_exit&#x2F;doc&#x2F;htm...</a>
zeroonetwothreeover 11 years ago
folly::Synchronized implements this in a correct way (and also prevents access without acquiring the lock):<p>SYNCHRONIZED(data) { &#x2F;&#x2F; modify data }<p><a href="https://github.com/facebook/folly/blob/master/folly/Synchronized.h" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;facebook&#x2F;folly&#x2F;blob&#x2F;master&#x2F;folly&#x2F;Synchron...</a>
bltover 11 years ago
This is not exception-safe like scoped locks are.