Try catch with locks in C++

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
25
down vote

favorite
6












In Java:



Lock lock = new ReentrantLock();
try
lock.lock();
someFunctionLikelyToCauseAnException();

catch(e)...
finally
lock.unlock();



My question is with this above example we know that the lock WILL always get unlocked because finally always executes, but what is the guarantee with C++?



mutex m;
m.lock();
someFunctionLikelyToCauseAnException();
/// ????


How will this work and why?







share|improve this question









New contributor




Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • 23




    Use std::lock_guard for RAII approach. std::lock_guard object will unlock whatever mutex it had in destructor.
    – Yksisarvinen
    Sep 6 at 14:55






  • 7




    You should read about stack unwinding, a very important feature of c++.
    – François Andrieux
    Sep 6 at 14:56






  • 16




    in a nutshell: c++ does not need finally, because it has destructors
    – user463035818
    Sep 6 at 14:58






  • 5




    @user4581301 Where have you read that Java has destructors? It has finalizers. It's called something different specifically because it's not a destructor. The issue is that the Finalizer is often called a Destructor, which I have a problem with.
    – Andrew T Finnell
    Sep 6 at 17:24






  • 14




    A lock is typically used with the pattern: "(1) state is consistent but wrong (2) enter the try (3) wait until you can take the lock (4) make state inconsistent (5) make state right and consistent, (6) enter the finally (7) release the lock (8) state is now consistent and right." What happens if a throw occurs after step 4 and before step 5? We go directly to step 6 but state is now both inconsistent and wrong! We then unlock the lock, and code that is waiting now has access to inconsistent wrong state, and it crashes. This pattern of unlocking in a finally is super dangerous.
    – Eric Lippert
    Sep 6 at 17:39















up vote
25
down vote

favorite
6












In Java:



Lock lock = new ReentrantLock();
try
lock.lock();
someFunctionLikelyToCauseAnException();

catch(e)...
finally
lock.unlock();



My question is with this above example we know that the lock WILL always get unlocked because finally always executes, but what is the guarantee with C++?



mutex m;
m.lock();
someFunctionLikelyToCauseAnException();
/// ????


How will this work and why?







share|improve this question









New contributor




Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • 23




    Use std::lock_guard for RAII approach. std::lock_guard object will unlock whatever mutex it had in destructor.
    – Yksisarvinen
    Sep 6 at 14:55






  • 7




    You should read about stack unwinding, a very important feature of c++.
    – François Andrieux
    Sep 6 at 14:56






  • 16




    in a nutshell: c++ does not need finally, because it has destructors
    – user463035818
    Sep 6 at 14:58






  • 5




    @user4581301 Where have you read that Java has destructors? It has finalizers. It's called something different specifically because it's not a destructor. The issue is that the Finalizer is often called a Destructor, which I have a problem with.
    – Andrew T Finnell
    Sep 6 at 17:24






  • 14




    A lock is typically used with the pattern: "(1) state is consistent but wrong (2) enter the try (3) wait until you can take the lock (4) make state inconsistent (5) make state right and consistent, (6) enter the finally (7) release the lock (8) state is now consistent and right." What happens if a throw occurs after step 4 and before step 5? We go directly to step 6 but state is now both inconsistent and wrong! We then unlock the lock, and code that is waiting now has access to inconsistent wrong state, and it crashes. This pattern of unlocking in a finally is super dangerous.
    – Eric Lippert
    Sep 6 at 17:39













up vote
25
down vote

favorite
6









up vote
25
down vote

favorite
6






6





In Java:



Lock lock = new ReentrantLock();
try
lock.lock();
someFunctionLikelyToCauseAnException();

catch(e)...
finally
lock.unlock();



My question is with this above example we know that the lock WILL always get unlocked because finally always executes, but what is the guarantee with C++?



mutex m;
m.lock();
someFunctionLikelyToCauseAnException();
/// ????


How will this work and why?







share|improve this question









New contributor




Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










In Java:



Lock lock = new ReentrantLock();
try
lock.lock();
someFunctionLikelyToCauseAnException();

catch(e)...
finally
lock.unlock();



My question is with this above example we know that the lock WILL always get unlocked because finally always executes, but what is the guarantee with C++?



mutex m;
m.lock();
someFunctionLikelyToCauseAnException();
/// ????


How will this work and why?









share|improve this question









New contributor




Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited Sep 6 at 16:51









Peter Mortensen

12.9k1983111




12.9k1983111






New contributor




Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Sep 6 at 14:53









Brijendar Bakchodia

18126




18126




New contributor




Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Brijendar Bakchodia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







  • 23




    Use std::lock_guard for RAII approach. std::lock_guard object will unlock whatever mutex it had in destructor.
    – Yksisarvinen
    Sep 6 at 14:55






  • 7




    You should read about stack unwinding, a very important feature of c++.
    – François Andrieux
    Sep 6 at 14:56






  • 16




    in a nutshell: c++ does not need finally, because it has destructors
    – user463035818
    Sep 6 at 14:58






  • 5




    @user4581301 Where have you read that Java has destructors? It has finalizers. It's called something different specifically because it's not a destructor. The issue is that the Finalizer is often called a Destructor, which I have a problem with.
    – Andrew T Finnell
    Sep 6 at 17:24






  • 14




    A lock is typically used with the pattern: "(1) state is consistent but wrong (2) enter the try (3) wait until you can take the lock (4) make state inconsistent (5) make state right and consistent, (6) enter the finally (7) release the lock (8) state is now consistent and right." What happens if a throw occurs after step 4 and before step 5? We go directly to step 6 but state is now both inconsistent and wrong! We then unlock the lock, and code that is waiting now has access to inconsistent wrong state, and it crashes. This pattern of unlocking in a finally is super dangerous.
    – Eric Lippert
    Sep 6 at 17:39













  • 23




    Use std::lock_guard for RAII approach. std::lock_guard object will unlock whatever mutex it had in destructor.
    – Yksisarvinen
    Sep 6 at 14:55






  • 7




    You should read about stack unwinding, a very important feature of c++.
    – François Andrieux
    Sep 6 at 14:56






  • 16




    in a nutshell: c++ does not need finally, because it has destructors
    – user463035818
    Sep 6 at 14:58






  • 5




    @user4581301 Where have you read that Java has destructors? It has finalizers. It's called something different specifically because it's not a destructor. The issue is that the Finalizer is often called a Destructor, which I have a problem with.
    – Andrew T Finnell
    Sep 6 at 17:24






  • 14




    A lock is typically used with the pattern: "(1) state is consistent but wrong (2) enter the try (3) wait until you can take the lock (4) make state inconsistent (5) make state right and consistent, (6) enter the finally (7) release the lock (8) state is now consistent and right." What happens if a throw occurs after step 4 and before step 5? We go directly to step 6 but state is now both inconsistent and wrong! We then unlock the lock, and code that is waiting now has access to inconsistent wrong state, and it crashes. This pattern of unlocking in a finally is super dangerous.
    – Eric Lippert
    Sep 6 at 17:39








23




23




Use std::lock_guard for RAII approach. std::lock_guard object will unlock whatever mutex it had in destructor.
– Yksisarvinen
Sep 6 at 14:55




Use std::lock_guard for RAII approach. std::lock_guard object will unlock whatever mutex it had in destructor.
– Yksisarvinen
Sep 6 at 14:55




7




7




You should read about stack unwinding, a very important feature of c++.
– François Andrieux
Sep 6 at 14:56




You should read about stack unwinding, a very important feature of c++.
– François Andrieux
Sep 6 at 14:56




16




16




in a nutshell: c++ does not need finally, because it has destructors
– user463035818
Sep 6 at 14:58




in a nutshell: c++ does not need finally, because it has destructors
– user463035818
Sep 6 at 14:58




5




5




@user4581301 Where have you read that Java has destructors? It has finalizers. It's called something different specifically because it's not a destructor. The issue is that the Finalizer is often called a Destructor, which I have a problem with.
– Andrew T Finnell
Sep 6 at 17:24




@user4581301 Where have you read that Java has destructors? It has finalizers. It's called something different specifically because it's not a destructor. The issue is that the Finalizer is often called a Destructor, which I have a problem with.
– Andrew T Finnell
Sep 6 at 17:24




14




14




A lock is typically used with the pattern: "(1) state is consistent but wrong (2) enter the try (3) wait until you can take the lock (4) make state inconsistent (5) make state right and consistent, (6) enter the finally (7) release the lock (8) state is now consistent and right." What happens if a throw occurs after step 4 and before step 5? We go directly to step 6 but state is now both inconsistent and wrong! We then unlock the lock, and code that is waiting now has access to inconsistent wrong state, and it crashes. This pattern of unlocking in a finally is super dangerous.
– Eric Lippert
Sep 6 at 17:39





A lock is typically used with the pattern: "(1) state is consistent but wrong (2) enter the try (3) wait until you can take the lock (4) make state inconsistent (5) make state right and consistent, (6) enter the finally (7) release the lock (8) state is now consistent and right." What happens if a throw occurs after step 4 and before step 5? We go directly to step 6 but state is now both inconsistent and wrong! We then unlock the lock, and code that is waiting now has access to inconsistent wrong state, and it crashes. This pattern of unlocking in a finally is super dangerous.
– Eric Lippert
Sep 6 at 17:39













3 Answers
3






active

oldest

votes

















up vote
53
down vote



accepted










For this we use the RAII-style construct std::lock_guard. When you use



std::mutex m;
// start of some scope
std::lock_guard lg(m);
// stuff
// end of scope


lg will ensure that m will be unlocked no matter what path the scope is left as it is destroyed at scope exit and std::lock_guards destructor will call unlock



Even if an exception is thrown the stack will be unwound (stack unwinding) and that process destroys lg which in turn will call unlock guaranteeing that the lock is released.






share|improve this answer


















  • 9




    Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
    – besmirched
    Sep 6 at 15:42







  • 12




    Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
    – user4581301
    Sep 6 at 16:38










  • So lock_guard is wrapping the mutex m basically like a smart pointer?
    – Brijendar Bakchodia
    Sep 6 at 17:28







  • 4




    @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
    – Justin
    Sep 6 at 18:00






  • 1




    @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
    – besmirched
    Sep 6 at 19:12


















up vote
26
down vote














what is the guarantee with C++?




The relevant guarantee in C++ works a bit differently in comparison to the one you mention in Java. Instead of a finally block, it's relying on the destruction of automatic variables that happens upon the scope's exit, when the stack frame gets unwound. This stack unwinding occurs regardless of how the scope was exited, whether gracefully or due to an exception.



The preferred approach for the scenario concerning such locks is to use RAII, as implemented for example by std::lock_guard. It holds a mutex object passed to its constructor -- inside of which it calls the mutex's lock() method, after which the thread owns the mutex -- and upon stack unwinding at the scope's exit its destructor is called -- inside of which it calls the mutex's unlock() method, thus releasing it.



The code will look like this:



std::mutex m;

std::lock_guard lock(m);
// Everything here is mutex-protected.

// Here you are guaranteed the std::mutex is released.





share|improve this answer


















  • 2




    Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
    – Jan Hudec
    Sep 6 at 21:30

















up vote
0
down vote













If an exception is thrown during execution of a piece of code protected by a critical section, that is, codes between "lock()" and "unlock()", it means the associated object that piece of code is operating on is no longer in a valid state. This, may or may not be rolled back by automatic unwinding of the stack triggered by the exception, because some side effect might have taken place before the exception is thrown ( a message has been sent through socket, a machine has been started, for example). At this point, the bigger issue here is not if the mutex will be released (the only guarantee from using lock_guard instead). There might well be some cases that the mutex still being locked is the desirable behavior, and can be explicitly reset after the caller cleaning all mess up.



My point is: this is not a language issue. No language feature can guarantee correct error handling. Don't take lock_guard and RAII as a silver bullet.






share|improve this answer




















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    Brijendar Bakchodia is a new contributor. Be nice, and check out our Code of Conduct.









     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52206884%2ftry-catch-with-locks-in-c%23new-answer', 'question_page');

    );

    Post as a guest






























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    53
    down vote



    accepted










    For this we use the RAII-style construct std::lock_guard. When you use



    std::mutex m;
    // start of some scope
    std::lock_guard lg(m);
    // stuff
    // end of scope


    lg will ensure that m will be unlocked no matter what path the scope is left as it is destroyed at scope exit and std::lock_guards destructor will call unlock



    Even if an exception is thrown the stack will be unwound (stack unwinding) and that process destroys lg which in turn will call unlock guaranteeing that the lock is released.






    share|improve this answer


















    • 9




      Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
      – besmirched
      Sep 6 at 15:42







    • 12




      Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
      – user4581301
      Sep 6 at 16:38










    • So lock_guard is wrapping the mutex m basically like a smart pointer?
      – Brijendar Bakchodia
      Sep 6 at 17:28







    • 4




      @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
      – Justin
      Sep 6 at 18:00






    • 1




      @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
      – besmirched
      Sep 6 at 19:12















    up vote
    53
    down vote



    accepted










    For this we use the RAII-style construct std::lock_guard. When you use



    std::mutex m;
    // start of some scope
    std::lock_guard lg(m);
    // stuff
    // end of scope


    lg will ensure that m will be unlocked no matter what path the scope is left as it is destroyed at scope exit and std::lock_guards destructor will call unlock



    Even if an exception is thrown the stack will be unwound (stack unwinding) and that process destroys lg which in turn will call unlock guaranteeing that the lock is released.






    share|improve this answer


















    • 9




      Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
      – besmirched
      Sep 6 at 15:42







    • 12




      Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
      – user4581301
      Sep 6 at 16:38










    • So lock_guard is wrapping the mutex m basically like a smart pointer?
      – Brijendar Bakchodia
      Sep 6 at 17:28







    • 4




      @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
      – Justin
      Sep 6 at 18:00






    • 1




      @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
      – besmirched
      Sep 6 at 19:12













    up vote
    53
    down vote



    accepted







    up vote
    53
    down vote



    accepted






    For this we use the RAII-style construct std::lock_guard. When you use



    std::mutex m;
    // start of some scope
    std::lock_guard lg(m);
    // stuff
    // end of scope


    lg will ensure that m will be unlocked no matter what path the scope is left as it is destroyed at scope exit and std::lock_guards destructor will call unlock



    Even if an exception is thrown the stack will be unwound (stack unwinding) and that process destroys lg which in turn will call unlock guaranteeing that the lock is released.






    share|improve this answer














    For this we use the RAII-style construct std::lock_guard. When you use



    std::mutex m;
    // start of some scope
    std::lock_guard lg(m);
    // stuff
    // end of scope


    lg will ensure that m will be unlocked no matter what path the scope is left as it is destroyed at scope exit and std::lock_guards destructor will call unlock



    Even if an exception is thrown the stack will be unwound (stack unwinding) and that process destroys lg which in turn will call unlock guaranteeing that the lock is released.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Sep 6 at 15:09

























    answered Sep 6 at 14:58









    NathanOliver

    75k15103153




    75k15103153







    • 9




      Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
      – besmirched
      Sep 6 at 15:42







    • 12




      Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
      – user4581301
      Sep 6 at 16:38










    • So lock_guard is wrapping the mutex m basically like a smart pointer?
      – Brijendar Bakchodia
      Sep 6 at 17:28







    • 4




      @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
      – Justin
      Sep 6 at 18:00






    • 1




      @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
      – besmirched
      Sep 6 at 19:12













    • 9




      Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
      – besmirched
      Sep 6 at 15:42







    • 12




      Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
      – user4581301
      Sep 6 at 16:38










    • So lock_guard is wrapping the mutex m basically like a smart pointer?
      – Brijendar Bakchodia
      Sep 6 at 17:28







    • 4




      @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
      – Justin
      Sep 6 at 18:00






    • 1




      @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
      – besmirched
      Sep 6 at 19:12








    9




    9




    Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
    – besmirched
    Sep 6 at 15:42





    Just in case the OP doesn't see what's really going on here; lg is a local variable. The lg(m) expression calls the constructor of the std::lock_guard class, and C++ guarantees that the destructor of any local variable will be promptly called when the thread exits from the variable's scope--no matter how the thread exits. The lock_guard constructor locks the given lock m, and the destructor unlocks it.
    – besmirched
    Sep 6 at 15:42





    12




    12




    Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
    – user4581301
    Sep 6 at 16:38




    Note to future readers: RAII is one of C++'s most important idioms and describes one of the biggest ideological differences between C++ and Java. If you are coming to C++ from Java you life will be hundreds of times easier once you start taking advantages of it. Read the given link and this one.
    – user4581301
    Sep 6 at 16:38












    So lock_guard is wrapping the mutex m basically like a smart pointer?
    – Brijendar Bakchodia
    Sep 6 at 17:28





    So lock_guard is wrapping the mutex m basically like a smart pointer?
    – Brijendar Bakchodia
    Sep 6 at 17:28





    4




    4




    @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
    – Justin
    Sep 6 at 18:00




    @BrijendarBakchodia First, you often don't need to allocate the mutex on the heap. If you do, you should be using a smart pointer rather than raw new or delete, so you'd write it auto m = std::make_unique<mutex>(); Second, notice that std::lock_guard's constructor takes a std::mutex&. So just turn that pointer into a reference by dereferencing it: std::lock_guard lg(*m)
    – Justin
    Sep 6 at 18:00




    1




    1




    @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
    – besmirched
    Sep 6 at 19:12





    @BrijendarBakchodia making sure that a mutex eventually gets unlocked and making sure that a heap-allocated object eventually gets freed are two separate problems. They are separate problems even if the heap-allocated thing happens to be a mutex. They are separate problems even though the preferred solutions, std::lock_guard and std::unique_ptr, both happen to use the same design pattern (RAII). An important skill for software engineering is learning to recognize and untangle separate problems that appear in the same space, and to keep their solutions separated.
    – besmirched
    Sep 6 at 19:12













    up vote
    26
    down vote














    what is the guarantee with C++?




    The relevant guarantee in C++ works a bit differently in comparison to the one you mention in Java. Instead of a finally block, it's relying on the destruction of automatic variables that happens upon the scope's exit, when the stack frame gets unwound. This stack unwinding occurs regardless of how the scope was exited, whether gracefully or due to an exception.



    The preferred approach for the scenario concerning such locks is to use RAII, as implemented for example by std::lock_guard. It holds a mutex object passed to its constructor -- inside of which it calls the mutex's lock() method, after which the thread owns the mutex -- and upon stack unwinding at the scope's exit its destructor is called -- inside of which it calls the mutex's unlock() method, thus releasing it.



    The code will look like this:



    std::mutex m;

    std::lock_guard lock(m);
    // Everything here is mutex-protected.

    // Here you are guaranteed the std::mutex is released.





    share|improve this answer


















    • 2




      Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
      – Jan Hudec
      Sep 6 at 21:30














    up vote
    26
    down vote














    what is the guarantee with C++?




    The relevant guarantee in C++ works a bit differently in comparison to the one you mention in Java. Instead of a finally block, it's relying on the destruction of automatic variables that happens upon the scope's exit, when the stack frame gets unwound. This stack unwinding occurs regardless of how the scope was exited, whether gracefully or due to an exception.



    The preferred approach for the scenario concerning such locks is to use RAII, as implemented for example by std::lock_guard. It holds a mutex object passed to its constructor -- inside of which it calls the mutex's lock() method, after which the thread owns the mutex -- and upon stack unwinding at the scope's exit its destructor is called -- inside of which it calls the mutex's unlock() method, thus releasing it.



    The code will look like this:



    std::mutex m;

    std::lock_guard lock(m);
    // Everything here is mutex-protected.

    // Here you are guaranteed the std::mutex is released.





    share|improve this answer


















    • 2




      Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
      – Jan Hudec
      Sep 6 at 21:30












    up vote
    26
    down vote










    up vote
    26
    down vote










    what is the guarantee with C++?




    The relevant guarantee in C++ works a bit differently in comparison to the one you mention in Java. Instead of a finally block, it's relying on the destruction of automatic variables that happens upon the scope's exit, when the stack frame gets unwound. This stack unwinding occurs regardless of how the scope was exited, whether gracefully or due to an exception.



    The preferred approach for the scenario concerning such locks is to use RAII, as implemented for example by std::lock_guard. It holds a mutex object passed to its constructor -- inside of which it calls the mutex's lock() method, after which the thread owns the mutex -- and upon stack unwinding at the scope's exit its destructor is called -- inside of which it calls the mutex's unlock() method, thus releasing it.



    The code will look like this:



    std::mutex m;

    std::lock_guard lock(m);
    // Everything here is mutex-protected.

    // Here you are guaranteed the std::mutex is released.





    share|improve this answer















    what is the guarantee with C++?




    The relevant guarantee in C++ works a bit differently in comparison to the one you mention in Java. Instead of a finally block, it's relying on the destruction of automatic variables that happens upon the scope's exit, when the stack frame gets unwound. This stack unwinding occurs regardless of how the scope was exited, whether gracefully or due to an exception.



    The preferred approach for the scenario concerning such locks is to use RAII, as implemented for example by std::lock_guard. It holds a mutex object passed to its constructor -- inside of which it calls the mutex's lock() method, after which the thread owns the mutex -- and upon stack unwinding at the scope's exit its destructor is called -- inside of which it calls the mutex's unlock() method, thus releasing it.



    The code will look like this:



    std::mutex m;

    std::lock_guard lock(m);
    // Everything here is mutex-protected.

    // Here you are guaranteed the std::mutex is released.






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 2 days ago

























    answered Sep 6 at 14:57









    SkepticalEmpiricist

    2,821720




    2,821720







    • 2




      Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
      – Jan Hudec
      Sep 6 at 21:30












    • 2




      Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
      – Jan Hudec
      Sep 6 at 21:30







    2




    2




    Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
    – Jan Hudec
    Sep 6 at 21:30




    Well, the guarantee in C++ is almost exactly the same as the one in Java. It just concerns destructors of automatic variables rather than finally blocks.
    – Jan Hudec
    Sep 6 at 21:30










    up vote
    0
    down vote













    If an exception is thrown during execution of a piece of code protected by a critical section, that is, codes between "lock()" and "unlock()", it means the associated object that piece of code is operating on is no longer in a valid state. This, may or may not be rolled back by automatic unwinding of the stack triggered by the exception, because some side effect might have taken place before the exception is thrown ( a message has been sent through socket, a machine has been started, for example). At this point, the bigger issue here is not if the mutex will be released (the only guarantee from using lock_guard instead). There might well be some cases that the mutex still being locked is the desirable behavior, and can be explicitly reset after the caller cleaning all mess up.



    My point is: this is not a language issue. No language feature can guarantee correct error handling. Don't take lock_guard and RAII as a silver bullet.






    share|improve this answer
























      up vote
      0
      down vote













      If an exception is thrown during execution of a piece of code protected by a critical section, that is, codes between "lock()" and "unlock()", it means the associated object that piece of code is operating on is no longer in a valid state. This, may or may not be rolled back by automatic unwinding of the stack triggered by the exception, because some side effect might have taken place before the exception is thrown ( a message has been sent through socket, a machine has been started, for example). At this point, the bigger issue here is not if the mutex will be released (the only guarantee from using lock_guard instead). There might well be some cases that the mutex still being locked is the desirable behavior, and can be explicitly reset after the caller cleaning all mess up.



      My point is: this is not a language issue. No language feature can guarantee correct error handling. Don't take lock_guard and RAII as a silver bullet.






      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        If an exception is thrown during execution of a piece of code protected by a critical section, that is, codes between "lock()" and "unlock()", it means the associated object that piece of code is operating on is no longer in a valid state. This, may or may not be rolled back by automatic unwinding of the stack triggered by the exception, because some side effect might have taken place before the exception is thrown ( a message has been sent through socket, a machine has been started, for example). At this point, the bigger issue here is not if the mutex will be released (the only guarantee from using lock_guard instead). There might well be some cases that the mutex still being locked is the desirable behavior, and can be explicitly reset after the caller cleaning all mess up.



        My point is: this is not a language issue. No language feature can guarantee correct error handling. Don't take lock_guard and RAII as a silver bullet.






        share|improve this answer












        If an exception is thrown during execution of a piece of code protected by a critical section, that is, codes between "lock()" and "unlock()", it means the associated object that piece of code is operating on is no longer in a valid state. This, may or may not be rolled back by automatic unwinding of the stack triggered by the exception, because some side effect might have taken place before the exception is thrown ( a message has been sent through socket, a machine has been started, for example). At this point, the bigger issue here is not if the mutex will be released (the only guarantee from using lock_guard instead). There might well be some cases that the mutex still being locked is the desirable behavior, and can be explicitly reset after the caller cleaning all mess up.



        My point is: this is not a language issue. No language feature can guarantee correct error handling. Don't take lock_guard and RAII as a silver bullet.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        John Z. Li

        1308




        1308




















            Brijendar Bakchodia is a new contributor. Be nice, and check out our Code of Conduct.









             

            draft saved


            draft discarded


















            Brijendar Bakchodia is a new contributor. Be nice, and check out our Code of Conduct.












            Brijendar Bakchodia is a new contributor. Be nice, and check out our Code of Conduct.











            Brijendar Bakchodia is a new contributor. Be nice, and check out our Code of Conduct.













             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52206884%2ftry-catch-with-locks-in-c%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            Long meetings (6-7 hours a day): Being “babysat” by supervisor

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            Confectionery