Thread overview
What is the point of a synchronized lock on a single return statement?
Nov 25, 2019
Andrej Mitrovic
Nov 25, 2019
Jonathan M Davis
Nov 25, 2019
Andrea Fontana
Nov 25, 2019
angel
Nov 25, 2019
Robert Schadek
November 25, 2019
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?
November 25, 2019
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



November 25, 2019
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


November 25, 2019
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.
November 25, 2019
On 11/25/19 3:22 AM, 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?

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
November 25, 2019
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.