Skip to content

Commit

Permalink
Feat: added Compute method for Set
Browse files Browse the repository at this point in the history
  • Loading branch information
hmoog committed Jul 27, 2023
1 parent 3445032 commit 5307f9e
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 24 deletions.
35 changes: 24 additions & 11 deletions ds/reactive/set_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -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()

Expand Down
3 changes: 3 additions & 0 deletions ds/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -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])

Expand Down
39 changes: 26 additions & 13 deletions ds/set_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 //////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 5307f9e

Please sign in to comment.