@@ -19,6 +19,9 @@ import ru.nsk.kstatemachine.state.*
1919import ru.nsk.kstatemachine.statemachine.*
2020import ru.nsk.kstatemachine.transition.TransitionBuilder
2121import ru.nsk.kstatemachine.transition.onTriggered
22+ import kotlin.contracts.ExperimentalContracts
23+ import kotlin.contracts.InvocationKind
24+ import kotlin.contracts.contract
2225import kotlin.coroutines.EmptyCoroutineContext
2326
2427typealias Callback <T > = (T ) -> Unit
@@ -81,54 +84,61 @@ enum class CoroutineStarterType {
8184
8285@OptIn(ExperimentalCoroutinesApi ::class )
8386private val singleThreadContext = newSingleThreadContext(" test single thread context" ) // context leaks
87+
8488/* *
8589 * Wraps [createStdLibStateMachine] so it can be easily switched to [createStdLibStateMachine]
8690 */
91+ @OptIn(ExperimentalContracts ::class )
8792suspend fun createTestStateMachine (
8893 coroutineStarterType : CoroutineStarterType ,
8994 name : String? = null,
9095 childMode : ChildMode = ChildMode .EXCLUSIVE ,
9196 start : Boolean = true,
9297 creationArguments : CreationArguments = buildCreationArguments {},
9398 init : suspend BuildingStateMachine .() -> Unit
94- ) = when (coroutineStarterType) {
95- CoroutineStarterType .STD_LIB -> createStdLibStateMachine(
96- name,
97- childMode,
98- start,
99- creationArguments,
100- init = init
101- )
102- CoroutineStarterType .COROUTINES_LIB_EMPTY_CONTEXT -> createStateMachine(
103- CoroutineScope (EmptyCoroutineContext ), // does not perform internal context switching
104- name,
105- childMode,
106- start,
107- creationArguments,
108- init = init
109- )
110- CoroutineStarterType .COROUTINES_LIB_UNCONFINED_DISPATCHER -> createStateMachine(
111- CoroutineScope (Dispatchers .Unconfined ),
112- name,
113- childMode,
114- start,
115- creationArguments,
116- init = init
117- )
118- CoroutineStarterType .COROUTINES_LIB_SINGLE_THREAD_DISPATCHER -> createStateMachine(
119- CoroutineScope (singleThreadContext),
120- name,
121- childMode,
122- start,
123- creationArguments,
124- init = init
125- )
126- CoroutineStarterType .COROUTINES_LIB_DEFAULT_LIMITED_DISPATCHER -> createStateMachine(
127- CoroutineScope (Dispatchers .Default .limitedParallelism(1 )), // does not guarantee same thread for each task
128- name,
129- childMode,
130- start,
131- creationArguments,
132- init = init
133- )
99+ ): StateMachine {
100+ contract {
101+ callsInPlace(init , InvocationKind .EXACTLY_ONCE )
102+ }
103+ return when (coroutineStarterType) {
104+ CoroutineStarterType .STD_LIB -> createStdLibStateMachine(
105+ name,
106+ childMode,
107+ start,
108+ creationArguments,
109+ init = init
110+ )
111+ CoroutineStarterType .COROUTINES_LIB_EMPTY_CONTEXT -> createStateMachine(
112+ CoroutineScope (EmptyCoroutineContext ), // does not perform internal context switching
113+ name,
114+ childMode,
115+ start,
116+ creationArguments,
117+ init = init
118+ )
119+ CoroutineStarterType .COROUTINES_LIB_UNCONFINED_DISPATCHER -> createStateMachine(
120+ CoroutineScope (Dispatchers .Unconfined ),
121+ name,
122+ childMode,
123+ start,
124+ creationArguments,
125+ init = init
126+ )
127+ CoroutineStarterType .COROUTINES_LIB_SINGLE_THREAD_DISPATCHER -> createStateMachine(
128+ CoroutineScope (singleThreadContext),
129+ name,
130+ childMode,
131+ start,
132+ creationArguments,
133+ init = init
134+ )
135+ CoroutineStarterType .COROUTINES_LIB_DEFAULT_LIMITED_DISPATCHER -> createStateMachine(
136+ CoroutineScope (Dispatchers .Default .limitedParallelism(1 )), // does not guarantee same thread for each task
137+ name,
138+ childMode,
139+ start,
140+ creationArguments,
141+ init = init
142+ )
143+ }
134144}
0 commit comments