type Locked[T any] struct { mu sync.Mutex val T } func (l *Locked[T]) Do(f func(T) T) { l.mu.Lock() defer l.mu.Unlock() l.val = f(l.val) }
Could you elaborate how 'Save/Store' , 'Load' and 'Tick / Increase ' get applied to the code above? Thanks. On Mon, May 23, 2022 at 3:24 PM 'Axel Wagner' via golang-nuts < golang-nuts@googlegroups.com> wrote: > FWIW a compromise is to have > > type Locked[T any] struct { > mu sync.Mutex > val T > } > > func (l *Locked[T]) Do(f func(T) T) { > l.mu.Lock() > defer l.mu.Unlock() > l.val = f(l.val) > } > > This forces modifications to be under the protection of a mutex while also > allowing those modifications to do arbitrary things. > > The downside is that this might do more locking than is strictly needed. > So, under contention, it might perform significantly worse than "manually" > managing the critical section. > > On Mon, May 23, 2022 at 9:11 AM Brian Candler <b.cand...@pobox.com> wrote: > >> > It's best to be intentional about it and explicitly acquire and release >> a mutex around the critical sections of your code - because ultimately, >> only your code knows which sections are critical. >> >> That's really essential. For example, using your library, the following >> code is most definitely *not* race-free: >> >> tmp := v.Load() >> tmp = tmp + 1 >> v.Save(tmp) >> >> The mutex has to protect the entire sequence, not the individual load and >> save operations. >> >> On Monday, 23 May 2022 at 07:57:02 UTC+1 axel.wa...@googlemail.com wrote: >> >>> Just to be clear, are you aware of the sync/atomic package? >>> https://pkg.go.dev/sync/atomic >>> There are also some changes in there for Go 1.18, specifically the >>> addition of some types, so that only atomic operations can be done: >>> https://pkg.go.dev/sync/atomic@master >>> I mention this because atomic.Value and atomic.Pointer[T] are >>> essentially what you are suggesting here. >>> >>> On Mon, May 23, 2022 at 8:04 AM Zhaoxun Yan <yan.z...@gmail.com> wrote: >>> >>>> However, as I want to narrow the scope of this type down to generate >>>> integer types (as in the commented code), it encountered two obstacles: >>>> >>>> 1) It is not legal to embed a generic inside a struct, nor can it make >>>> generalized computation =+1 >>>> >>>> 2) Inheritance is not available in golang, so type "Counter" cannot >>>> inherit type "Global" and get its methods automatically. I need to repeat >>>> Save and Load methods to "Counter". >>>> >>>> Am I correct? Or can you improve it? >>>> >>> >>> You are correct that there is no way in Go to write a type which gets >>> all methods from an embedded field using generics. However, that is a good >>> thing. For example, say you could write >>> >>> type Locked[T any] struct { >>> sync.Mutex >>> T >>> } >>> >>> And this would get the methods of T and the methods of sync.Mutex. Then >>> a user could do >>> >>> type Counter int64 >>> func (c *Counter) Increment() { *c += 1 } >>> >>> func main() { >>> var c Locked[Counter] >>> go c.Increment() >>> go c.Increment() >>> } >>> >>> And get a data race. That is, a method can modify a value in a way that >>> is incompatible with what your wrapper type is trying to do. >>> >>> That's really the crux of both of the obstacles you mention. You can't >>> run arbitrary computations and you can't promote methods, because *not all >>> computation and not all methods can be made concurrency safe this way*. >>> >>> It's best to be intentional about it and explicitly acquire and release >>> a mutex around the critical sections of your code - because ultimately, >>> only your code knows which sections are critical. >>> >>> >>>> >>> -- >>>> 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/baa74bff-6688-4d39-843b-c99a4fea2d1an%40googlegroups.com >>>> <https://groups.google.com/d/msgid/golang-nuts/baa74bff-6688-4d39-843b-c99a4fea2d1an%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >> 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/50d6ab3d-46d0-4357-b5fa-d99b73ef2adan%40googlegroups.com >> <https://groups.google.com/d/msgid/golang-nuts/50d6ab3d-46d0-4357-b5fa-d99b73ef2adan%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- > You received this message because you are subscribed to a topic in the > Google Groups "golang-nuts" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/golang-nuts/3javezRHm98/unsubscribe. > To unsubscribe from this group and all its topics, 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/CAEkBMfG63G2%2BCk5VVmAhT1UMxpVsxy88C4gOPH%3DxV%3DZnXXUjmA%40mail.gmail.com > <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfG63G2%2BCk5VVmAhT1UMxpVsxy88C4gOPH%3DxV%3DZnXXUjmA%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- 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/CADEX6_Vpb%3Dqz5y%3Dvrs1ACn9jF9XfwUOoko65%3DL9TmfOkz2iC_Q%40mail.gmail.com.