From 5307f9e3b8ab2b4bb5b70fc6acd86bb210b1761b Mon Sep 17 00:00:00 2001 From: Hans Moog <3293976+hmoog@users.noreply.github.com> Date: Thu, 27 Jul 2023 13:21:42 +0200 Subject: [PATCH] Feat: added Compute method for Set --- ds/reactive/set_impl.go | 35 ++++++++++++++++++++++++----------- ds/set.go | 3 +++ ds/set_impl.go | 39 ++++++++++++++++++++++++++------------- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/ds/reactive/set_impl.go b/ds/reactive/set_impl.go index dd1f55350..fc5668b1a 100644 --- a/ds/reactive/set_impl.go +++ b/ds/reactive/set_impl.go @@ -67,6 +67,23 @@ func (s *set[ElementType]) Apply(mutations ds.SetMutations[ElementType]) (applie return appliedMutations } +// Compute tries to compute the mutations for the set atomically and returns the applied mutations. +func (s *set[ElementType]) Compute(mutationFactory func(set ds.ReadableSet[ElementType]) ds.SetMutations[ElementType]) (appliedMutations ds.SetMutations[ElementType]) { + s.mutex.Lock() + defer s.mutex.Unlock() + + appliedMutations, updateID, registeredCallbacks := s.apply(mutationFactory(s.readableSet)) + + for _, registeredCallback := range registeredCallbacks { + if registeredCallback.LockExecution(updateID) { + registeredCallback.Invoke(appliedMutations) + registeredCallback.UnlockExecution() + } + } + + return appliedMutations +} + // Replace replaces the current value of the set with the given elements. func (s *set[ElementType]) Replace(elements ds.ReadableSet[ElementType]) (removedElements ds.Set[ElementType]) { s.mutex.Lock() @@ -205,11 +222,11 @@ func (s *derivedSet[ElementType]) InheritFrom(sources ...ReadableSet[ElementType sourceElements := ds.NewSet[ElementType]() unsubscribeFromSource := source.OnUpdate(func(appliedMutations ds.SetMutations[ElementType]) { - s.Apply(sourceElements.Apply(appliedMutations)) + s.inheritMutations(sourceElements.Apply(appliedMutations)) }) removeSourceElements := func() { - s.Apply(ds.NewSetMutations[ElementType]().WithDeletedElements(sourceElements)) + s.inheritMutations(ds.NewSetMutations[ElementType]().WithDeletedElements(sourceElements)) } unsubscribeCallbacks = append(unsubscribeCallbacks, unsubscribeFromSource, removeSourceElements) @@ -218,16 +235,12 @@ func (s *derivedSet[ElementType]) InheritFrom(sources ...ReadableSet[ElementType return lo.Batch(unsubscribeCallbacks...) } -// Apply triggers the update of the set with the given mutations. -func (s *derivedSet[ElementType]) Apply(mutations ds.SetMutations[ElementType]) (appliedMutations ds.SetMutations[ElementType]) { - if mutations.IsEmpty() { - return - } - +// inheritMutations triggers the update of the set with the given mutations. +func (s *derivedSet[ElementType]) inheritMutations(mutations ds.SetMutations[ElementType]) (appliedMutations ds.SetMutations[ElementType]) { s.mutex.Lock() defer s.mutex.Unlock() - appliedMutations, updateID, registeredCallbacks := s.apply(mutations) + appliedMutations, updateID, registeredCallbacks := s.applyInheritedMutations(mutations) for _, registeredCallback := range registeredCallbacks { if registeredCallback.LockExecution(updateID) { @@ -239,9 +252,9 @@ func (s *derivedSet[ElementType]) Apply(mutations ds.SetMutations[ElementType]) return appliedMutations } -// apply prepares the trigger by applying the given mutations to the set and returning the applied +// applyInheritedMutations prepares the trigger by applying the given mutations to the set and returning the applied // mutations, the trigger ID and the callbacks to trigger. -func (s *derivedSet[ElementType]) apply(mutations ds.SetMutations[ElementType]) (inheritedMutations ds.SetMutations[ElementType], triggerID uniqueID, callbacksToTrigger []*callback[func(ds.SetMutations[ElementType])]) { +func (s *derivedSet[ElementType]) applyInheritedMutations(mutations ds.SetMutations[ElementType]) (inheritedMutations ds.SetMutations[ElementType], triggerID uniqueID, callbacksToTrigger []*callback[func(ds.SetMutations[ElementType])]) { s.readableSet.mutex.Lock() defer s.readableSet.mutex.Unlock() diff --git a/ds/set.go b/ds/set.go index 26e697080..859c29934 100644 --- a/ds/set.go +++ b/ds/set.go @@ -101,6 +101,9 @@ type WriteableSet[ElementType comparable] interface { // Apply tries to apply the given mutations to the set atomically and returns the applied mutations. Apply(mutations SetMutations[ElementType]) (appliedMutations SetMutations[ElementType]) + // Compute tries to compute the mutations for the set atomically and returns the applied mutations. + Compute(mutationFactory func(set ReadableSet[ElementType]) SetMutations[ElementType]) (appliedMutations SetMutations[ElementType]) + // Replace replaces the elements of the set with the given elements and returns the removed elements. Replace(elements ReadableSet[ElementType]) (removedElements Set[ElementType]) diff --git a/ds/set_impl.go b/ds/set_impl.go index 59b79edf2..1cbfb4216 100644 --- a/ds/set_impl.go +++ b/ds/set_impl.go @@ -86,21 +86,15 @@ func (s *set[ElementType]) Apply(mutations SetMutations[ElementType]) (appliedMu s.applyMutex.Lock() defer s.applyMutex.Unlock() - addedElements := NewSet[ElementType]() - mutations.AddedElements().Range(func(element ElementType) { - if !lo.Return2(s.Set(element, types.Void)) { - addedElements.Add(element) - } - }) + return s.apply(mutations) +} - removedElements := NewSet[ElementType]() - mutations.DeletedElements().Range(func(element ElementType) { - if s.OrderedMap.Delete(element) { - removedElements.Add(element) - } - }) +// Compute tries to compute the mutations for the set atomically and returns the applied mutations. +func (s *set[ElementType]) Compute(mutationFactory func(set ReadableSet[ElementType]) SetMutations[ElementType]) (appliedMutations SetMutations[ElementType]) { + s.applyMutex.Lock() + defer s.applyMutex.Unlock() - return NewSetMutations[ElementType]().WithAddedElements(addedElements).WithDeletedElements(removedElements) + return s.apply(mutationFactory(s.readableSet)) } // Replace replaces the elements of the set with the given elements and returns the previous elements of the set. @@ -123,6 +117,25 @@ func (s *set[ElementType]) ReadOnly() ReadableSet[ElementType] { return s.readableSet } +// apply tries to apply the given mutations to the set atomically and returns the mutations that have been applied. +func (s *set[ElementType]) apply(mutations SetMutations[ElementType]) (appliedMutations SetMutations[ElementType]) { + addedElements := NewSet[ElementType]() + mutations.AddedElements().Range(func(element ElementType) { + if !lo.Return2(s.Set(element, types.Void)) { + addedElements.Add(element) + } + }) + + removedElements := NewSet[ElementType]() + mutations.DeletedElements().Range(func(element ElementType) { + if s.OrderedMap.Delete(element) { + removedElements.Add(element) + } + }) + + return NewSetMutations[ElementType]().WithAddedElements(addedElements).WithDeletedElements(removedElements) +} + // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// // region readableSet //////////////////////////////////////////////////////////////////////////////////////////////////