@@ -21,6 +21,8 @@ public class SingleThreadEventExecutor : AbstractScheduledEventExecutor
2121 const int ST_TERMINATED = 5 ;
2222 const string DefaultWorkerThreadName = "SingleThreadEventExecutor worker" ;
2323
24+ static readonly IRunnable WAKEUP_TASK = new NoOpRunnable ( ) ;
25+
2426 static readonly IInternalLogger Logger =
2527 InternalLoggerFactory . GetInstance < SingleThreadEventExecutor > ( ) ;
2628
@@ -70,15 +72,12 @@ void Loop()
7072 Task . Factory . StartNew (
7173 ( ) =>
7274 {
73- if ( Interlocked . CompareExchange ( ref this . executionState , ST_STARTED , ST_NOT_STARTED ) == ST_NOT_STARTED )
75+ Interlocked . CompareExchange ( ref this . executionState , ST_STARTED , ST_NOT_STARTED ) ;
76+ while ( ! this . ConfirmShutdown ( ) )
7477 {
75- while ( ! this . ConfirmShutdown ( ) )
76- {
77- this . RunAllTasks ( this . preciseBreakoutInterval ) ;
78- }
79-
80- this . CleanupAndTerminate ( true ) ;
78+ this . RunAllTasks ( this . preciseBreakoutInterval ) ;
8179 }
80+ this . CleanupAndTerminate ( true ) ;
8281 } ,
8382 CancellationToken . None ,
8483 TaskCreationOptions . None ,
@@ -120,6 +119,14 @@ public override void Execute(IRunnable task)
120119 }
121120 }
122121
122+ protected void WakeUp ( bool inEventLoop )
123+ {
124+ if ( ! inEventLoop || this . executionState == ST_SHUTTING_DOWN )
125+ {
126+ this . Execute ( WAKEUP_TASK ) ;
127+ }
128+ }
129+
123130 public override Task ShutdownGracefullyAsync ( TimeSpan quietPeriod , TimeSpan timeout )
124131 {
125132 Contract . Requires ( quietPeriod >= TimeSpan . Zero ) ;
@@ -174,10 +181,10 @@ public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan time
174181 // scheduleExecution();
175182 //}
176183
177- // if (wakeup)
178- // {
179- // wakeup (inEventLoop);
180- // }
184+ if ( wakeup )
185+ {
186+ this . WakeUp ( inEventLoop ) ;
187+ }
181188
182189 return this . TerminationCompletion ;
183190 }
@@ -189,10 +196,7 @@ protected bool ConfirmShutdown()
189196 return false ;
190197 }
191198
192- if ( ! this . InEventLoop )
193- {
194- throw new InvalidOperationException ( "must be invoked from an event loop" ) ;
195- }
199+ Contract . Assert ( this . InEventLoop , "must be invoked from an event loop" ) ;
196200
197201 this . CancelScheduledTasks ( ) ;
198202
@@ -210,8 +214,7 @@ protected bool ConfirmShutdown()
210214 }
211215
212216 // There were tasks in the queue. Wait a little bit more until no tasks are queued for the quiet period.
213- // todo: ???
214- //wakeup(true);
217+ this . WakeUp ( true ) ;
215218 return false ;
216219 }
217220
@@ -227,7 +230,7 @@ protected bool ConfirmShutdown()
227230 // Check if any tasks were added to the queue every 100ms.
228231 // TODO: Change the behavior of takeTask() so that it returns on timeout.
229232 // todo: ???
230- //wakeup (true);
233+ this . WakeUp ( true ) ;
231234 Thread . Sleep ( 100 ) ;
232235
233236 return false ;
@@ -243,7 +246,6 @@ protected void CleanupAndTerminate(bool success)
243246 while ( true )
244247 {
245248 int oldState = this . executionState ;
246- ;
247249 if ( oldState >= ST_SHUTTING_DOWN || Interlocked . CompareExchange ( ref this . executionState , ST_SHUTTING_DOWN , oldState ) == oldState )
248250 {
249251 break ;
@@ -398,7 +400,7 @@ IRunnable PollTask()
398400 if ( task == null )
399401 {
400402 this . emptyEvent . Reset ( ) ;
401- if ( ( task = this . taskQueue . Dequeue ( ) ) == null ) // revisit queue as producer might have put a task in meanwhile
403+ if ( ( task = this . taskQueue . Dequeue ( ) ) == null && ! this . IsShuttingDown ) // revisit queue as producer might have put a task in meanwhile
402404 {
403405 IScheduledRunnable nextScheduledTask = this . ScheduledTaskQueue . Peek ( ) ;
404406 if ( nextScheduledTask != null )
@@ -424,27 +426,11 @@ IRunnable PollTask()
424426 return task ;
425427 }
426428
427- #region IDisposable members
428-
429- public void Dispose ( )
430- {
431- this . Dispose ( true ) ;
432- GC . SuppressFinalize ( this ) ;
433- }
434-
435- public void Dispose ( bool isDisposing )
429+ sealed class NoOpRunnable : IRunnable
436430 {
437- if ( ! this . disposed )
431+ public void Run ( )
438432 {
439- if ( isDisposing )
440- {
441- this . thread = null ;
442- }
443433 }
444-
445- this . disposed = true ;
446434 }
447-
448- #endregion
449435 }
450436}
0 commit comments