Use scoped locks instead of CRITICAL_BLOCK #1052

pull sipa wants to merge 3 commits into bitcoin:master from sipa:scopedlocks changing 19 files +300 −204
  1. sipa commented at 9:39 PM on April 6, 2012: member

    Remove CRITICAL_BLOCK and TRY_CRITICAL_BLOCK, and replace them with LOCK, TRY_LOCK and IS_LOCKED. These are macros that define a local CCriticalBlock variable (a boost::interprocess::scoped_lock wrapper), which is much more C++ than the if and/or for constructions in macros.

    I've intentionally not touched formattng/indentation where possible, in order not to break other patches. There are several cases where simplications are possible now, though.

  2. in src/net.cpp:None in 469a013cfd outdated
     550 | -                     TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
     551 | -                      TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
     552 | -                       TRY_CRITICAL_BLOCK(pnode->cs_inventory)
     553 | -                        fDelete = true;
     554 | +                    {
     555 | +                        TRY_LOCK(pnode->cs_vSend);
    


    laanwj commented at 2:32 PM on April 7, 2012:

    This code becomes reasonably ugly. Would it be possible to redefine TRY_CRITICAL_BLOCK to use the scoped locks and keep this code (approximately) the same?


    sipa commented at 2:37 PM on April 7, 2012:

    You could just have several scoped locks (like with your suggestion below to include a name for the lock), and test whether they all succeed. That would however be different from the code above (which unlocks everything as soon as a failure occurs).

    EDIT: The problem to do it correctly with only one line of code is that you do need a conditional block of code somewhere that depends on the lock, which is simply not doable with a scoped lock (except using exceptions maybe...).

  3. in src/util.h:None in 469a013cfd outdated
     289 | @@ -289,6 +290,13 @@ class CMutexLock
     290 |  #define WAITABLE_CRITICAL_BLOCK(cs)     \
     291 |      for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by WAITABLE_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
     292 |          for (CWaitableCriticalBlock waitablecriticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false)
     293 | +*/
     294 | +
     295 | +#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
    


    laanwj commented at 2:35 PM on April 7, 2012:

    Hm I'd prefer passing the name of the lock ("criticalblock") as a macro parameter to LOCK, TRY_LOCK and IS_LOCKED. Especially the bare IS_LOCKED (with hardcoded name) look too much like magic to my taste, as there is no visual clue what lock it refers to.


    sipa commented at 2:38 PM on April 7, 2012:

    Yes, it's a balance between code size and clean code. Note that the current master already has hardcoded names as well...


    laanwj commented at 2:45 PM on April 7, 2012:

    Well yes but we're trying to improve. IMO it'd be best to completely get rid of the macros, if possible. But making them less "magical" would already be good.

    Maybe add the name argument only for TRY_LOCK? For LOCK and LOCK2 you never need to refer to them anyway.


    sipa commented at 2:51 PM on April 7, 2012:

    I considered removing all macros and go to pure boost::interprocess, but there is no way to keep Gavin's fancy deadlock detection then, which needs FILE and LINE to track code locations. I'm fine with just an argument for TRY_LOCK and IS_LOCKED.


    laanwj commented at 2:53 PM on April 7, 2012:

    You mean boost::thread, please no more boost::interprocess :)

    OK, let's do that then.

  4. sipa commented at 3:31 PM on April 7, 2012: member

    Updated; I like this even more: TRY_LOCK(cs, name); if (name) { ... }

  5. laanwj commented at 3:32 PM on April 7, 2012: member

    Yes this is much better :)

  6. Diapolo commented at 5:11 PM on April 7, 2012: none

    To understand that stuff, LOCK() is used, when code needs to be thread safe and UNLOCK() is used if that part has been processed?

  7. sipa commented at 5:17 PM on April 7, 2012: member

    LOCK() implements what is called a scoped lock: it makes sure that inside the current block of code (surrounded by { }), a lock on a particular mutex is taken, and released when that block of code exits. Because of that, there is no need for an UNLOCK().

  8. Use scoped locks instead of CRITICAL_BLOCK f8dcd5ca6f
  9. Support for parametrized locks in deadlock detector 908037fe16
  10. Do not report spurious deadlocks caused by TRY_LOCK f342dac1cb
  11. in src/test/util_tests.cpp:None in 6927b9d551 outdated
      24 |      } while(0);
      25 |  
      26 |      do {
      27 | -        TRY_CRITICAL_BLOCK(cs)
      28 | +        TRY_LOCK(cs);
      29 | +        if (IS_LOCKED)
    


    gavinandresen commented at 11:46 PM on April 8, 2012:

    Where is IS_LOCKED defined?


    sipa commented at 12:02 AM on April 9, 2012:

    Oh, right. Leftover from an older version. Fixed now.

  12. gavinandresen commented at 1:43 PM on April 9, 2012: contributor

    ACK.

  13. sipa referenced this in commit 1a275bac2b on Apr 9, 2012
  14. sipa merged this on Apr 9, 2012
  15. sipa closed this on Apr 9, 2012

  16. coblee referenced this in commit e9520e489d on Jul 17, 2012
  17. suprnurd referenced this in commit 0d324eafa8 on Dec 5, 2017
  18. ptschip referenced this in commit 5e479f3a57 on May 1, 2018
  19. lateminer referenced this in commit dd62f3f66a on Oct 30, 2019
  20. Bushstar referenced this in commit b7b8c33d0e on Jan 5, 2020
  21. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-19 09:16 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me