Skip to content

Commit

Permalink
Add synchronized access to EventEngine's state variable
Browse files Browse the repository at this point in the history
fix(subscribe): fix the crash issue caused by multiple accesses to the state property in multithreaded scenarios
  • Loading branch information
jguz-pubnub committed Jan 15, 2025
1 parent 2e3e028 commit c0f76dc
Showing 1 changed file with 12 additions and 7 deletions.
19 changes: 12 additions & 7 deletions Sources/PubNub/EventEngine/Core/EventEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ struct EventEngineDependencies<Dependencies> {
class EventEngine<State, Event, Invocation: AnyEffectInvocation, Input> {
private let transition: any TransitionProtocol<State, Event, Invocation>
private let dispatcher: any Dispatcher<Invocation, Event, Input>
private(set) var state: State
private let stateContainer: Atomic<State>
private let recursiveLock = NSRecursiveLock()

var state: State { stateContainer.lockedRead { $0 } }
var dependencies: EventEngineDependencies<Input>
var onStateUpdated: ((State) -> Void)?

Expand All @@ -29,30 +31,33 @@ class EventEngine<State, Event, Invocation: AnyEffectInvocation, Input> {
dispatcher: some Dispatcher<Invocation, Event, Input>,
dependencies: EventEngineDependencies<Input>
) {
self.state = state
self.stateContainer = Atomic(state)
self.onStateUpdated = onStateUpdated
self.transition = transition
self.dispatcher = dispatcher
self.dependencies = dependencies
}

func send(event: Event) {
objc_sync_enter(self)
recursiveLock.lock()

defer {
objc_sync_exit(self)
recursiveLock.unlock()
}

let currentState = state

guard transition.canTransition(
from: state,
from: currentState,
dueTo: event
) else {
return
}

let transitionResult = transition.transition(from: state, event: event)
let transitionResult = transition.transition(from: currentState, event: event)
let invocations = transitionResult.invocations

state = transitionResult.state
stateContainer.lockedWrite { $0 = transitionResult.state }
onStateUpdated?(state)

let listener = DispatcherListener<Event>(
Expand Down

0 comments on commit c0f76dc

Please sign in to comment.