Re: [go-nuts] Re: Do I need a reentrant locks?
You're absolutely right. (I wrote the simplified example a bit too fast and missed that in a few places https://go.dev/play/p/9fk_yt0vkHD) To add the general motivation, I have a reactive UI tree and need to introduce concurrency (for when async data fetching is done and the data is reintroduced,, essentially mutating the tree). On Tuesday, July 5, 2022 at 4:13:01 PM UTC+2 Marvin Renich wrote: > * Brian Candler [220705 09:48]: > > Have a public Set() that does the lock and then calls a private internal > > function, which assumes it's already running under the lock. > > https://go.dev/play/p/M1XuC8bxCxL > > > > On Tuesday, 5 July 2022 at 13:32:26 UTC+1 atd...@gmail.com wrote: > > > > > Hi, > > > > > > I have a tree datastructure where mutating some nodes *may *trigger a > > > mutation on some other tree nodes. > > > > > > This tree should be accessible by multiple goroutines but mutated by > only > > > one at a time. > > > > > > As such, I wanted to have a global lock on the tree such that > mutatiing > > > node methods should acquire this lock beforehand. > > > > > > But it seems to require for the mutex to be reentrant? > > > > > > I have tried to create a very simplified*** model to illustrate > > > https://go.dev/play/p/v37cbYQ1jSY > > > > > > (***) I know people might want to suggest for the Set method to use a > > > lockless variant when iterating over the linked nodes but in the real > code, > > > it iterates over user created callbacks instead and I don't think I > can > > > expect callbacks writers to juggle between the two kind of methods to > avoid > > > deadlocks. > > > > > > Any suggestion? > > > > > > > > Note also that for referencing a Node to be safe, you must do one of two > things: either use sync/atomic for all reads and writes of Num > (assuming the data in the tree is of a type that can be handled by > sync/atomic), or use sync.RWMutex instead of sync.Mutex, and use RLock > on reads and Lock on writes. > > If Node has more than one data field, e.g. {Name string; Age int; ...}, > you will have to go with the RWMutex option. > > ...Marvin > > -- 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/94b3ef70-9431-4a8a-916d-034dd5822d01n%40googlegroups.com.
Re: [go-nuts] Re: Do I need a reentrant locks?
* atd...@gmail.com [220705 10:03]: > :) That's what the asterisked note was for in the original question. I > don't think I can do that in the real code because the real code is much > more complex. Each node actually triggers a callback that may modify > another node. That callback is user-created, not framework created so I > have no way of knowing if the lock has already been taken. > > And I wouldn't want for library users to have to make that distinction > themselves. Have the Set method always take some type of context, which is a pointer type. If the context is nil, assume a top-level call to Set, otherwise use the context to decide what to do. All the callbacks will be required to accept a context and pass it to the Set method. If you have multiple goroutines that can be making top-level Set calls, I see no way around using something to distinguish top-level calls from Set within callbacks. ...Marvin > On Tuesday, July 5, 2022 at 3:48:16 PM UTC+2 Brian Candler wrote: > > > Have a public Set() that does the lock and then calls a private internal > > function, which assumes it's already running under the lock. > > https://go.dev/play/p/M1XuC8bxCxL > > > > On Tuesday, 5 July 2022 at 13:32:26 UTC+1 atd...@gmail.com wrote: > > > >> Hi, > >> > >> I have a tree datastructure where mutating some nodes *may *trigger a > >> mutation on some other tree nodes. > >> > >> This tree should be accessible by multiple goroutines but mutated by only > >> one at a time. > >> > >> As such, I wanted to have a global lock on the tree such that mutatiing > >> node methods should acquire this lock beforehand. > >> > >> But it seems to require for the mutex to be reentrant? > >> > >> I have tried to create a very simplified*** model to illustrate > >> https://go.dev/play/p/v37cbYQ1jSY > >> > >> (***) I know people might want to suggest for the Set method to use a > >> lockless variant when iterating over the linked nodes but in the real > >> code, > >> it iterates over user created callbacks instead and I don't think I can > >> expect callbacks writers to juggle between the two kind of methods to > >> avoid > >> deadlocks. > >> > >> Any suggestion? > >> > >> -- 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/YsRLSsBPXIbN0Nob%40basil.wdw.
Re: [go-nuts] Re: Do I need a reentrant locks?
* Brian Candler [220705 09:48]: > Have a public Set() that does the lock and then calls a private internal > function, which assumes it's already running under the lock. > https://go.dev/play/p/M1XuC8bxCxL > > On Tuesday, 5 July 2022 at 13:32:26 UTC+1 atd...@gmail.com wrote: > > > Hi, > > > > I have a tree datastructure where mutating some nodes *may *trigger a > > mutation on some other tree nodes. > > > > This tree should be accessible by multiple goroutines but mutated by only > > one at a time. > > > > As such, I wanted to have a global lock on the tree such that mutatiing > > node methods should acquire this lock beforehand. > > > > But it seems to require for the mutex to be reentrant? > > > > I have tried to create a very simplified*** model to illustrate > > https://go.dev/play/p/v37cbYQ1jSY > > > > (***) I know people might want to suggest for the Set method to use a > > lockless variant when iterating over the linked nodes but in the real code, > > it iterates over user created callbacks instead and I don't think I can > > expect callbacks writers to juggle between the two kind of methods to avoid > > deadlocks. > > > > Any suggestion? > > > > Note also that for referencing a Node to be safe, you must do one of two things: either use sync/atomic for all reads and writes of Num (assuming the data in the tree is of a type that can be handled by sync/atomic), or use sync.RWMutex instead of sync.Mutex, and use RLock on reads and Lock on writes. If Node has more than one data field, e.g. {Name string; Age int; ...}, you will have to go with the RWMutex option. ...Marvin -- 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/YsRGy7EdSxvtPoj3%40basil.wdw.
[go-nuts] Re: Do I need a reentrant locks?
:) That's what the asterisked note was for in the original question. I don't think I can do that in the real code because the real code is much more complex. Each node actually triggers a callback that may modify another node. That callback is user-created, not framework created so I have no way of knowing if the lock has already been taken. And I wouldn't want for library users to have to make that distinction themselves. On Tuesday, July 5, 2022 at 3:48:16 PM UTC+2 Brian Candler wrote: > Have a public Set() that does the lock and then calls a private internal > function, which assumes it's already running under the lock. > https://go.dev/play/p/M1XuC8bxCxL > > On Tuesday, 5 July 2022 at 13:32:26 UTC+1 atd...@gmail.com wrote: > >> Hi, >> >> I have a tree datastructure where mutating some nodes *may *trigger a >> mutation on some other tree nodes. >> >> This tree should be accessible by multiple goroutines but mutated by only >> one at a time. >> >> As such, I wanted to have a global lock on the tree such that mutatiing >> node methods should acquire this lock beforehand. >> >> But it seems to require for the mutex to be reentrant? >> >> I have tried to create a very simplified*** model to illustrate >> https://go.dev/play/p/v37cbYQ1jSY >> >> (***) I know people might want to suggest for the Set method to use a >> lockless variant when iterating over the linked nodes but in the real code, >> it iterates over user created callbacks instead and I don't think I can >> expect callbacks writers to juggle between the two kind of methods to avoid >> deadlocks. >> >> Any suggestion? >> >> -- 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/db0206a8-b113-47ba-9aa5-b3d3680870e2n%40googlegroups.com.
[go-nuts] Re: Do I need a reentrant locks?
Have a public Set() that does the lock and then calls a private internal function, which assumes it's already running under the lock. https://go.dev/play/p/M1XuC8bxCxL On Tuesday, 5 July 2022 at 13:32:26 UTC+1 atd...@gmail.com wrote: > Hi, > > I have a tree datastructure where mutating some nodes *may *trigger a > mutation on some other tree nodes. > > This tree should be accessible by multiple goroutines but mutated by only > one at a time. > > As such, I wanted to have a global lock on the tree such that mutatiing > node methods should acquire this lock beforehand. > > But it seems to require for the mutex to be reentrant? > > I have tried to create a very simplified*** model to illustrate > https://go.dev/play/p/v37cbYQ1jSY > > (***) I know people might want to suggest for the Set method to use a > lockless variant when iterating over the linked nodes but in the real code, > it iterates over user created callbacks instead and I don't think I can > expect callbacks writers to juggle between the two kind of methods to avoid > deadlocks. > > Any suggestion? > > -- 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/42e71458-8d9c-4b80-9c46-d6d0a96b71abn%40googlegroups.com.