This is a recipe for bad bugs. Use defensive programming - grab the lock in the top-level functions, have private functions like ‘doXXXXWithLock()’ as a signal to the developer that they must be holding the lock.
Allowing callbacks to call back into a concurrent safe structure is very difficult - because the callbacks can easily be made async as well. I would just re-entrant locks. And ensure that no locks are held when the callback is made - or if it is - it needs to be heavily documented on what the callee can do. Still, in your case without detailing api design available I am guessing you are going to run in deadlocks very quickly. > On Jul 5, 2022, at 9:31 AM, Marvin Renich <m...@renich.org> wrote: > > * atd...@gmail.com <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. -- 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/D5D0492E-F34E-4A71-8ACB-157A8DA7F688%40ix.netcom.com.