enum RuntimeSessionState { created, loading, active, disposing, disposed } class RuntimeSession { RuntimeSession({required this.gameId}) : id = _nextId++; static int _nextId = 1; final int id; final String gameId; RuntimeSessionState _state = RuntimeSessionState.created; RuntimeSessionState get state => _state; bool get isLoading => _state == RuntimeSessionState.loading; bool get isActive => _state == RuntimeSessionState.active; bool get isDisposing => _state == RuntimeSessionState.disposing; bool get isDisposed => _state == RuntimeSessionState.disposed; bool get acceptsWork => _state != RuntimeSessionState.disposing && _state != RuntimeSessionState.disposed; void beginLoading() { _transition( RuntimeSessionState.loading, allowedFrom: const {RuntimeSessionState.created}, ); } void activate() { _transition( RuntimeSessionState.active, allowedFrom: const { RuntimeSessionState.created, RuntimeSessionState.loading, }, ); } void beginDisposing() { if (_state == RuntimeSessionState.disposed || _state == RuntimeSessionState.disposing) { return; } _state = RuntimeSessionState.disposing; } void dispose() { _state = RuntimeSessionState.disposed; } bool accepts(int sessionId) => isActive && id == sessionId; bool acceptsWorkFor(int sessionId) => acceptsWork && id == sessionId; void _transition( RuntimeSessionState next, { required Set allowedFrom, }) { if (_state == next) { return; } if (!allowedFrom.contains(_state)) { throw StateError('Invalid runtime session transition: $_state -> $next'); } _state = next; } }