www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What is the point of a synchronized lock on a single return statement?

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
From: 
https://github.com/dlang/phobos/blob/10b9174ddcadac52f6a1ea532deab3310d3a8c03/std/concurrency.d#L1913-L1916:

-----
///
final  property bool isClosed()  safe  nogc pure
{
     synchronized (m_lock)
     {
         return m_closed;
     }
}
-----

I don't understand the purpose of this lock. The lock will be 
released as soon as the function returns, and it returns a copy 
of a boolean anyway. Am I missing something here?
Nov 25 2019
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, November 25, 2019 1:22:17 AM MST Andrej Mitrovic via Digitalmars-
d-learn wrote:
 From:
 https://github.com/dlang/phobos/blob/10b9174ddcadac52f6a1ea532deab3310d3a8
 c03/std/concurrency.d#L1913-L1916:

 -----
 ///
 final  property bool isClosed()  safe  nogc pure
 {
      synchronized (m_lock)
      {
          return m_closed;
      }
 }
 -----

 I don't understand the purpose of this lock. The lock will be
 released as soon as the function returns, and it returns a copy
 of a boolean anyway. Am I missing something here?
It ensures that no other code that locks m_lock is running when m_closed is accessed. I'd have to study std.concurrency in detail to know for sure why that would be needed, but it's not atypical when trying to maintain consistent state when multiple threads are interacting with each other. - Jonathan M Davis
Nov 25 2019
parent Andrea Fontana <nospam example.com> writes:
On Monday, 25 November 2019 at 09:24:43 UTC, Jonathan M Davis 
wrote:
 On Monday, November 25, 2019 1:22:17 AM MST Andrej Mitrovic via 
 Digitalmars- d-learn wrote:
 From: 
 https://github.com/dlang/phobos/blob/10b9174ddcadac52f6a1ea532deab3310d3a8
c03/std/concurrency.d#L1913-L1916:

 -----
 ///
 final  property bool isClosed()  safe  nogc pure
 {
      synchronized (m_lock)
      {
          return m_closed;
      }
 }
 -----

 I don't understand the purpose of this lock. The lock will be 
 released as soon as the function returns, and it returns a 
 copy of a boolean anyway. Am I missing something here?
It ensures that no other code that locks m_lock is running when m_closed is accessed. I'd have to study std.concurrency in detail to know for sure why that would be needed, but it's not atypical when trying to maintain consistent state when multiple threads are interacting with each other. - Jonathan M Davis
Probably to be sure to have a consistent status returned. See for example: https://github.com/dlang/phobos/blob/10b9174ddcadac52f6a1ea532deab3310d3a8c03/std/concurrency.d#L2250
Nov 25 2019
prev sibling next sibling parent angel <andrey.gelman gmail.com> writes:
On Monday, 25 November 2019 at 08:22:17 UTC, Andrej Mitrovic 
wrote:
 From: 
 https://github.com/dlang/phobos/blob/10b9174ddcadac52f6a1ea532deab3310d3a8c03/std/concurrency.d#L1913-L1916:

 -----
 ///
 final  property bool isClosed()  safe  nogc pure
 {
     synchronized (m_lock)
     {
         return m_closed;
     }
 }
 -----

 I don't understand the purpose of this lock. The lock will be 
 released as soon as the function returns, and it returns a copy 
 of a boolean anyway. Am I missing something here?
I think this code can be rewritten as --- final property bool isClosed() safe nogc pure { bool ret; synchronized (m_lock) { ret = m_closed; } return ret; } --- Normally, if the memory location of m_closed is aligned, the assignment to 'ret' should be atomic, however if you cannot make assumptions about alignment, the access should be protected.
Nov 25 2019
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/25/19 3:22 AM, Andrej Mitrovic wrote:
 From: 
 https://github.com/dlang/phobos/blob/10b9174ddcadac52f6a1ea532deab3310d3a8c03/std/concur
ency.d#L1913-L1916: 
 
 
 -----
 ///
 final  property bool isClosed()  safe  nogc pure
 {
      synchronized (m_lock)
      {
          return m_closed;
      }
 }
 -----
 
 I don't understand the purpose of this lock. The lock will be released 
 as soon as the function returns, and it returns a copy of a boolean 
 anyway. Am I missing something here?
Locks ensure the CPU and compiler use the correct memory model. It's complicated, but necessary. Look up Herb Sutter's atomic weapons talk. The key takeaway is that the "gurus" who make compilers and cpus have the rule "If you use mutex locks, the code will behave like you wrote it for all observations". With out the locks, crazy things can happen. Note also, that even though x86 CPUs are atomic for single values without locks, not all CPUs are. However, I think a bool is likely always atomic. But that doesn't mean the compiler or CPU will not reorder your instructions. The locks keep it consistent. -Steve
Nov 25 2019
parent Robert Schadek <rschadek symmetryinvestments.com> writes:
But be aware, even though the bool is returned from a 
synchronized block,
its actual value has no meaning at all.

All the meaning you get out of that bool is that the MessageBox 
was closed
when you called that function.
If there is a function in MessageBox that can reopen the instance,
you can not assume that the MessageBox is still closed when you
read the bool.
Assuming your program has more than one thread touching that 
instance of
the MessageBox.

Consider

```
auto mb = new MessageBox();
bool c = mb.isClosed();
// this thread gets preempted, and another thread
// does something with mb that changes its state

if(!c) { // the value of c might not what you expected
    // start rockets
}
```

This problem, at least partly, spawn concepts like Monitors,
the Rendezvous concept, Message Passing, and others.
Nov 25 2019