Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread 'Axel Wagner' via golang-nuts
On Fri, Apr 23, 2021 at 1:36 AM Nail Islamov  wrote:

> Answers above don't explain the difference in behavior:
> [1] https://play.golang.org/p/lXA2F4b880W
> [2] https://play.golang.org/p/doruBxrquhw
>
> Why did deadlock happen in [1], despite creating a variable?
>
If I change the order ([2]), I do avoid a deadlock (meaning that I have two
> separate mutexes).
>

In [1], you copy a locked mutex and try to lock that. In [2], you copy an
unlocked Mutex (really, the zero value of a Mutex) and try to lock that
(which works).
Note that in case [1] the behavior actually is undefined:
https://golang.org/pkg/sync/#Mutex

> A Mutex must not be copied after first use.

In case [2] you copy it before first use, which is fine (as I said, you are
copying the zero value of a Mutex).


>
> Obviously both examples are not for production use, just trying to
> understand what's happening there.
> On Thursday, 22 April 2021 at 10:19:15 pm UTC+10 axel.wa...@googlemail.com
> wrote:
>
>> I think what is going on here is that it is wrong to say that
>> `(*observer)` creates a copy:
>>
>> https://golang.org/ref/spec#Address_operators
>>
>>> For an operand x of pointer type *T, the pointer indirection *x denotes
>>> the variable of type T pointed to by x.
>>
>>
>> That variable is addressable and contains a `sync.RWMutex`. It's method
>> set contains `Lock`, as methods on a pointer receiver are promoted to
>> value receivers . And "If x is
>> addressable and &x's method set contains m, x.m() is shorthand for (&x).m()"
>> .
>>
>> Thus, `(*observer).Lock()` is a shorthand for `(&(*observer)).Lock()`
>> which is the same as `observer.Lock()`.
>>
>> If, OTOH, you do
>> lock := (*observer)
>> lock.Lock()
>> you *would* create a copy - you'd create a new variable and assign to it
>> the value in the variable pointed at by observer.
>>
>> Either way, I think that code should be changed. It's pretty messy and
>> obviously not clear, even if it's correct.
>>
>> On Thu, Apr 22, 2021 at 1:49 PM Jan Mercl <0xj...@gmail.com> wrote:
>>
>>> On Thu, Apr 22, 2021 at 1:39 PM Mikhail Mazurskiy
>>>  wrote:
>>>
>>> > Thanks for the response, I didn't see this section. However, I'm still
>>> confused as it says the exception in 3. only applies to fields, not to
>>> methods. RLock() is obviously a method, not a field.
>>>
>>> You're right. And because the playground link seems to work for
>>> methods as well, I'm now pretty confused if there's a compiler bug or
>>> specs bug or I don't understand what's going on at all.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "golang-nuts" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to golang-nuts...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/golang-nuts/CAA40n-WdkuXq2u1NYfPWL2pJYq6m1pBrhEOA-qsToNUeVkFz2Q%40mail.gmail.com
>>> .
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/14845b83-4292-4b39-8098-ef914e2b4254n%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfG9k1ZJ4ioxnSr6X3PFM7syL1NfddUKA-Ta-u%3DEArhXGA%40mail.gmail.com.


Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread Nail Islamov
Sorry, ignore that. In [1], I make a copy of a locked mutex, which creates 
a *new *locked mutex.
Basically the only non-obvious behavior here is that `&(*m) == m` by the 
rules of Go, the rest was explained above.

On Friday, 23 April 2021 at 9:36:26 am UTC+10 Nail Islamov wrote:

> Answers above don't explain the difference in behavior:
> [1] https://play.golang.org/p/lXA2F4b880W
> [2] https://play.golang.org/p/doruBxrquhw
>
> Why did deadlock happen in [1], despite creating a variable?
> If I change the order ([2]), I do avoid a deadlock (meaning that I have 
> two separate mutexes).
>
> Obviously both examples are not for production use, just trying to 
> understand what's happening there.
> On Thursday, 22 April 2021 at 10:19:15 pm UTC+10 axel.wa...@googlemail.com 
> wrote:
>
>> I think what is going on here is that it is wrong to say that 
>> `(*observer)` creates a copy:
>>
>> https://golang.org/ref/spec#Address_operators
>>
>>> For an operand x of pointer type *T, the pointer indirection *x denotes 
>>> the variable of type T pointed to by x.
>>
>>
>> That variable is addressable and contains a `sync.RWMutex`. It's method 
>> set contains `Lock`, as methods on a pointer receiver are promoted to 
>> value receivers . And "If x is 
>> addressable and &x's method set contains m, x.m() is shorthand for (&x).m()" 
>> .
>>
>> Thus, `(*observer).Lock()` is a shorthand for `(&(*observer)).Lock()` 
>> which is the same as `observer.Lock()`.
>>  
>> If, OTOH, you do
>> lock := (*observer)
>> lock.Lock()
>> you *would* create a copy - you'd create a new variable and assign to it 
>> the value in the variable pointed at by observer.
>>
>> Either way, I think that code should be changed. It's pretty messy and 
>> obviously not clear, even if it's correct.
>>
>> On Thu, Apr 22, 2021 at 1:49 PM Jan Mercl <0xj...@gmail.com> wrote:
>>
>>> On Thu, Apr 22, 2021 at 1:39 PM Mikhail Mazurskiy
>>>  wrote:
>>>
>>> > Thanks for the response, I didn't see this section. However, I'm still 
>>> confused as it says the exception in 3. only applies to fields, not to 
>>> methods. RLock() is obviously a method, not a field.
>>>
>>> You're right. And because the playground link seems to work for
>>> methods as well, I'm now pretty confused if there's a compiler bug or
>>> specs bug or I don't understand what's going on at all.
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "golang-nuts" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to golang-nuts...@googlegroups.com.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/golang-nuts/CAA40n-WdkuXq2u1NYfPWL2pJYq6m1pBrhEOA-qsToNUeVkFz2Q%40mail.gmail.com
>>> .
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/50acc2a9-64ad-45ad-84af-5ba9477aea34n%40googlegroups.com.


Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread Nail Islamov
Answers above don't explain the difference in behavior:
[1] https://play.golang.org/p/lXA2F4b880W
[2] https://play.golang.org/p/doruBxrquhw

Why did deadlock happen in [1], despite creating a variable?
If I change the order ([2]), I do avoid a deadlock (meaning that I have two 
separate mutexes).

Obviously both examples are not for production use, just trying to 
understand what's happening there.
On Thursday, 22 April 2021 at 10:19:15 pm UTC+10 axel.wa...@googlemail.com 
wrote:

> I think what is going on here is that it is wrong to say that 
> `(*observer)` creates a copy:
>
> https://golang.org/ref/spec#Address_operators
>
>> For an operand x of pointer type *T, the pointer indirection *x denotes 
>> the variable of type T pointed to by x.
>
>
> That variable is addressable and contains a `sync.RWMutex`. It's method 
> set contains `Lock`, as methods on a pointer receiver are promoted to 
> value receivers . And "If x is 
> addressable and &x's method set contains m, x.m() is shorthand for (&x).m()" 
> .
>
> Thus, `(*observer).Lock()` is a shorthand for `(&(*observer)).Lock()` 
> which is the same as `observer.Lock()`.
>  
> If, OTOH, you do
> lock := (*observer)
> lock.Lock()
> you *would* create a copy - you'd create a new variable and assign to it 
> the value in the variable pointed at by observer.
>
> Either way, I think that code should be changed. It's pretty messy and 
> obviously not clear, even if it's correct.
>
> On Thu, Apr 22, 2021 at 1:49 PM Jan Mercl <0xj...@gmail.com> wrote:
>
>> On Thu, Apr 22, 2021 at 1:39 PM Mikhail Mazurskiy
>>  wrote:
>>
>> > Thanks for the response, I didn't see this section. However, I'm still 
>> confused as it says the exception in 3. only applies to fields, not to 
>> methods. RLock() is obviously a method, not a field.
>>
>> You're right. And because the playground link seems to work for
>> methods as well, I'm now pretty confused if there's a compiler bug or
>> specs bug or I don't understand what's going on at all.
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/CAA40n-WdkuXq2u1NYfPWL2pJYq6m1pBrhEOA-qsToNUeVkFz2Q%40mail.gmail.com
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/14845b83-4292-4b39-8098-ef914e2b4254n%40googlegroups.com.


Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread 'Axel Wagner' via golang-nuts
I think what is going on here is that it is wrong to say that `(*observer)`
creates a copy:

https://golang.org/ref/spec#Address_operators

> For an operand x of pointer type *T, the pointer indirection *x denotes
> the variable of type T pointed to by x.


That variable is addressable and contains a `sync.RWMutex`. It's method set
contains `Lock`, as methods on a pointer receiver are promoted to value
receivers . And "If x is
addressable and &x's method set contains m, x.m() is shorthand for (&x).m()"
.

Thus, `(*observer).Lock()` is a shorthand for `(&(*observer)).Lock()` which
is the same as `observer.Lock()`.

If, OTOH, you do
lock := (*observer)
lock.Lock()
you *would* create a copy - you'd create a new variable and assign to it
the value in the variable pointed at by observer.

Either way, I think that code should be changed. It's pretty messy and
obviously not clear, even if it's correct.

On Thu, Apr 22, 2021 at 1:49 PM Jan Mercl <0xj...@gmail.com> wrote:

> On Thu, Apr 22, 2021 at 1:39 PM Mikhail Mazurskiy
>  wrote:
>
> > Thanks for the response, I didn't see this section. However, I'm still
> confused as it says the exception in 3. only applies to fields, not to
> methods. RLock() is obviously a method, not a field.
>
> You're right. And because the playground link seems to work for
> methods as well, I'm now pretty confused if there's a compiler bug or
> specs bug or I don't understand what's going on at all.
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/CAA40n-WdkuXq2u1NYfPWL2pJYq6m1pBrhEOA-qsToNUeVkFz2Q%40mail.gmail.com
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEm6%3DuyPhYf%3DZnRpQXYVm2wpTDsSZnmY2_KGM0OKWgW2g%40mail.gmail.com.


Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread Jan Mercl
On Thu, Apr 22, 2021 at 1:39 PM Mikhail Mazurskiy
 wrote:

> Thanks for the response, I didn't see this section. However, I'm still 
> confused as it says the exception in 3. only applies to fields, not to 
> methods. RLock() is obviously a method, not a field.

You're right. And because the playground link seems to work for
methods as well, I'm now pretty confused if there's a compiler bug or
specs bug or I don't understand what's going on at all.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAA40n-WdkuXq2u1NYfPWL2pJYq6m1pBrhEOA-qsToNUeVkFz2Q%40mail.gmail.com.


Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread Mikhail Mazurskiy
On Thu, 22 Apr 2021 at 21:27, Jan Mercl <0xj...@gmail.com> wrote:

> On Thu, Apr 22, 2021 at 1:15 PM Mikhail Mazurskiy
>  wrote:
>
> > I stumbled upon this strange looking piece of code [1]. I thought it
> dereferences the pointer, creating a copy of the mutex, and then calls
> RLock() on the copy (i.e. a nop). But it does not work this way. I
> experimented with it [2] and [3] and it looks like my reading of code is
> wrong. Could someone explain how dereferencing a pointer works in this case
> please? Language spec is not very explicit about it (unless I missed it)
> [4].
>
> See https://golang.org/ref/spec#Selectors
>
> 
> 3. As an exception, if the type of x is a defined pointer type and
> (*x).f is a valid selector expression denoting a field (but not a
> method), x.f is shorthand for (*x).f.
> 
>
> In this case '(*observer).Lock()' and 'observer.Lock()' have the same
> semantics. Like here: https://play.golang.org/p/bPj-ZfPwRWc
>

Thanks for the response, I didn't see this section. However, I'm still
confused as it says the exception in 3. only applies to fields, not to
methods. RLock() is obviously a method, not a field.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CALaYgJUZAxOJ8PSFrZ%3D%2BxBqvaD47UmOGCY_Bmfjk7JTqpYxSXw%40mail.gmail.com.


Re: [go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread Jan Mercl
On Thu, Apr 22, 2021 at 1:15 PM Mikhail Mazurskiy
 wrote:

> I stumbled upon this strange looking piece of code [1]. I thought it 
> dereferences the pointer, creating a copy of the mutex, and then calls 
> RLock() on the copy (i.e. a nop). But it does not work this way. I 
> experimented with it [2] and [3] and it looks like my reading of code is 
> wrong. Could someone explain how dereferencing a pointer works in this case 
> please? Language spec is not very explicit about it (unless I missed it) [4].

See https://golang.org/ref/spec#Selectors


3. As an exception, if the type of x is a defined pointer type and
(*x).f is a valid selector expression denoting a field (but not a
method), x.f is shorthand for (*x).f.


In this case '(*observer).Lock()' and 'observer.Lock()' have the same
semantics. Like here: https://play.golang.org/p/bPj-ZfPwRWc

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAA40n-UYzvz%3Dx%3Dk2gBzz37DHu6b-isXUZFoTpt9A%3DSLvACFiCQ%40mail.gmail.com.


[go-nuts] Unexpected pointer dereference behavior

2021-04-22 Thread Mikhail Mazurskiy
Hi all,

I stumbled upon this strange looking piece of code [1]. I thought it
dereferences the pointer, creating a copy of the mutex, and then calls
RLock() on the copy (i.e. a nop). But it does not work this way. I
experimented with it [2] and [3] and it looks like my reading of code is
wrong. Could someone explain how dereferencing a pointer works in this case
please? Language spec is not very explicit about it (unless I missed it)
[4].

Thank you.
Mikhail.

[1]:
https://github.com/open-telemetry/opentelemetry-go/blob/738ef11e3108955b1a2619fd32b39869f2625919/example/prometheus/main.go#L52-L59
[2]: https://play.golang.org/p/9A9pnD5h-GW
[3]: https://play.golang.org/p/smzQu9_84dZ
[4]: https://golang.org/ref/spec#Address_operators

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CALaYgJXjwO-PSCZ1Jmr%2BHa4wL7dmHRv_i05YQOqvy3BmU4o-HQ%40mail.gmail.com.