/* Ċ Ġ* ĠCopyright Ġ 2 0 1 6 - 2 0 1 8 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense . Ċ Ġ*/ Ċ Ċ package Ġkotlinx . coroutines Ċ Ċ import Ġkotlinx . atomic fu .* Ċ import Ġkotlinx . coroutines . channels .* Ċ import Ġorg . junit . Test Ċ import Ġjava . util . concurrent . locks .* Ċ import Ġkotlin . concurrent .* Ċ import Ġkotlin . test .* Ċ Ċ /** Ċ Ġ* ĠTests Ġevent Ġloops Ġintegration . Ċ Ġ* ĠSee Ġ[ https :// github . com / Kotlin / kotlin x . coroutines / issues / 8 6 0 ]. Ċ Ġ*/ Ċ class ĠEvent Lo ops Test Ġ: ĠTest Base () Ġ{ ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Nested Run Blocking () Ġ{ ĊĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ Ġ// Ġouter Ġevent Ġloop ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠPro duce Ġstring Ġ" OK " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġch Ġ= Ġproduce Ġ{ Ġsend (" OK ") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġtry Ġreceive Ġthis Ġstring Ġin Ġa Ġblocking Ġway : ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" OK ", Ġrun Blocking Ġ{ Ġch . receive () Ġ}) Ġ// Ġit Ġshould Ġnot Ġhang Ġhere ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Un conf ined In Run Blocking () Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġcompleted Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch ( Dispatch ers . Un conf ined ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompleted Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġshould Ġnot Ġgo Ġinto Ġrun Blocking Ġloop , Ġbut Ġcomplete Ġhere ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( completed ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Nested Un conf ined () Ġ{ ĊĠĠĠĠĠĠĠ Ġexpect ( 1 ) ĊĠĠĠĠĠĠĠ ĠGlobal Scope . launch ( Dispatch ers . Un conf ined ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠGlobal Scope . launch ( Dispatch ers . Un conf ined ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthis Ġgets Ġscheduled Ġinto Ġouter Ġun conf ined Ġloop ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 4 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 3 ) Ġ// Ġ ^^ Ġexecuted Ġbefore Ġthe Ġabove Ġun conf ined ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfinish ( 5 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest EventLoop In Default Executor () Ġ= Ġrun Test Ġ{ ĊĠĠĠĠĠĠĠ Ġexpect ( 1 ) ĊĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . Un conf ined ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdelay ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( Thread . currentThread (). name . startsWith ( Default Executor . THREAD _ NAME )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnow Ġrun Blocking Ġinside Ġdefault Ġexecutor Ġthread Ġ--> Ġshould Ġuse Ġouter Ġevent Ġloop ĊĠĠĠĠĠĠĠĠĠĠĠ ĠDefault Executor . enqueue ( Runnable Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 4 ) Ġ// Ġwill Ġexecute Ġwhen Ġrun Blocking Ġruns Ġloop ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 3 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 5 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfinish ( 6 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSimple Ġtest Ġfor Ġ[ process Next Event In Current Thread ] ĠAPI Ġuse - case . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Process Next Event In Current Thread Simple () Ġ= Ġrun Test Ġ{ ĊĠĠĠĠĠĠĠ Ġexpect ( 1 ) ĊĠĠĠĠĠĠĠ Ġval Ġevent Ġ= ĠEvent Sync () ĊĠĠĠĠĠĠĠ Ġ// Ġthis Ġcoroutine Ġfires Ġevent ĊĠĠĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 3 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevent . fire Event () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// Ġmain Ġcoroutine Ġwaits Ġfor Ġevent Ġ( same Ġthread !) ĊĠĠĠĠĠĠĠ Ġexpect ( 2 ) ĊĠĠĠĠĠĠĠ Ġevent . blocking Await () ĊĠĠĠĠĠĠĠ Ġfinish ( 4 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Second Thread Run Blocking () Ġ= Ġrun Test Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtest Thread Ġ= ĠThread . currentThread () ĊĠĠĠĠĠĠĠ Ġval Ġtest Context Ġ= Ġcoroutine Context ĊĠĠĠĠĠĠĠ Ġval Ġevent Ġ= ĠEvent Sync () Ġ// Ġwill Ġsignal Ġcompletion ĊĠĠĠĠĠĠĠ Ġvar Ġthread Ġ= Ġthread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ Ġ// Ġouter Ġevent Ġloop ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠPro duce Ġstring Ġ" OK " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġch Ġ= Ġproduce Ġ{ Ġsend (" OK ") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġtry Ġreceive Ġthis Ġstring Ġin Ġa Ġblocking Ġway Ġusing Ġtest Ġcontext Ġ( another Ġthread ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" OK ", Ġrun Blocking ( test Context ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( test Thread , ĠThread . currentThread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġch . receive () Ġ// Ġit Ġshould Ġnot Ġhang Ġhere ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevent . fire Event () Ġ// Ġdone Ġthread ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġevent . blocking Await () Ġ// Ġwait Ġfor Ġthread Ġto Ġcomplete ĊĠĠĠĠĠĠĠ Ġthread . join () Ġ// Ġit Ġis Ġsafe Ġto Ġjoin Ġthread Ġnow ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTest Ġfor Ġ[ process Next Event In Current Thread ] ĠAPI Ġuse - case Ġwith Ġdelay . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Process Next Event In Current Thread Delay () Ġ= Ġrun Test Ġ{ ĊĠĠĠĠĠĠĠ Ġexpect ( 1 ) ĊĠĠĠĠĠĠĠ Ġval Ġevent Ġ= ĠEvent Sync () ĊĠĠĠĠĠĠĠ Ġ// Ġthis Ġcoroutine Ġfires Ġevent ĊĠĠĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpect ( 3 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdelay ( 1 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevent . fire Event () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// Ġmain Ġcoroutine Ġwaits Ġfor Ġevent Ġ( same Ġthread !) ĊĠĠĠĠĠĠĠ Ġexpect ( 2 ) ĊĠĠĠĠĠĠĠ Ġevent . blocking Await () ĊĠĠĠĠĠĠĠ Ġfinish ( 4 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġclass ĠEvent Sync Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġwaiting Thread Ġ= Ġatomic < Thread ? >( null ) ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġfired Ġ= Ġatomic ( false ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġfire Event () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfired . value Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwaiting Thread . value ?. let Ġ{ ĠLock Support . un park ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġblocking Await () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( waiting Thread . get AndSet ( Thread . currentThread ()) Ġ== Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! f ired . get AndSet ( false )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtime Ġ= Ġprocess Next Event In Current Thread () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLock Support . park Nan os ( time ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwaiting Thread . value Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }