@@ -43,38 +43,39 @@ internal object DefaultExecutor : EventLoopBase(), Runnable {
43
43
@Volatile
44
44
private var debugStatus: Int = FRESH
45
45
46
+ private val isShutdownRequested: Boolean get() {
47
+ val debugStatus = debugStatus
48
+ return debugStatus == SHUTDOWN_REQ || debugStatus == SHUTDOWN_ACK
49
+ }
50
+
46
51
override fun run () {
47
52
timeSource.registerTimeLoopThread()
48
53
try {
49
54
var shutdownNanos = Long .MAX_VALUE
50
- if (notifyStartup()) {
51
- runLoop@ while (true ) {
52
- Thread .interrupted() // just reset interruption flag
53
- var parkNanos = processNextEvent()
54
- if (parkNanos == Long .MAX_VALUE ) {
55
- // nothing to do, initialize shutdown timeout
56
- if (shutdownNanos == Long .MAX_VALUE ) {
57
- val now = timeSource.nanoTime()
58
- if (shutdownNanos == Long .MAX_VALUE ) shutdownNanos = now + KEEP_ALIVE_NANOS
59
- val tillShutdown = shutdownNanos - now
60
- if (tillShutdown <= 0 ) break @runLoop // shut thread down
61
- parkNanos = parkNanos.coerceAtMost(tillShutdown)
62
- } else
63
- parkNanos = parkNanos.coerceAtMost(KEEP_ALIVE_NANOS ) // limit wait time anyway
64
- }
65
- if (parkNanos > 0 ) {
66
- // check if shutdown was requested and bail out in this case
67
- if (debugStatus == SHUTDOWN_REQ ) {
68
- acknowledgeShutdown()
69
- break @runLoop
70
- } else {
71
- timeSource.parkNanos(this , parkNanos)
72
- }
73
- }
55
+ if (! notifyStartup()) return
56
+ while (true ) {
57
+ Thread .interrupted() // just reset interruption flag
58
+ var parkNanos = processNextEvent()
59
+ if (parkNanos == Long .MAX_VALUE ) {
60
+ // nothing to do, initialize shutdown timeout
61
+ if (shutdownNanos == Long .MAX_VALUE ) {
62
+ val now = timeSource.nanoTime()
63
+ if (shutdownNanos == Long .MAX_VALUE ) shutdownNanos = now + KEEP_ALIVE_NANOS
64
+ val tillShutdown = shutdownNanos - now
65
+ if (tillShutdown <= 0 ) return // shut thread down
66
+ parkNanos = parkNanos.coerceAtMost(tillShutdown)
67
+ } else
68
+ parkNanos = parkNanos.coerceAtMost(KEEP_ALIVE_NANOS ) // limit wait time anyway
69
+ }
70
+ if (parkNanos > 0 ) {
71
+ // check if shutdown was requested and bail out in this case
72
+ if (isShutdownRequested) return
73
+ timeSource.parkNanos(this , parkNanos)
74
74
}
75
75
}
76
76
} finally {
77
77
_thread = null // this thread is dead
78
+ acknowledgeShutdownIfNeeded()
78
79
timeSource.unregisterTimeLoopThread()
79
80
// recheck if queues are empty after _thread reference was set to null (!!!)
80
81
if (! isEmpty) thread() // recreate thread if it is needed
@@ -110,32 +111,31 @@ internal object DefaultExecutor : EventLoopBase(), Runnable {
110
111
111
112
@Synchronized
112
113
private fun notifyStartup (): Boolean {
113
- if (debugStatus == SHUTDOWN_REQ ) return false
114
+ if (isShutdownRequested ) return false
114
115
debugStatus = ACTIVE
115
116
(this as Object ).notifyAll()
116
117
return true
117
118
}
118
119
119
120
// used for tests
120
121
@Synchronized
121
- internal fun shutdown (timeout : Long ) {
122
- if (_thread != null ) {
123
- val deadline = System .currentTimeMillis() + timeout
124
- if (debugStatus == ACTIVE || debugStatus == FRESH ) debugStatus = SHUTDOWN_REQ
125
- unpark()
126
- // loop while there is anything to do immediately or deadline passes
127
- while (debugStatus != SHUTDOWN_ACK && _thread != null ) {
128
- val remaining = deadline - System .currentTimeMillis()
129
- if (remaining <= 0 ) break
130
- (this as Object ).wait(timeout)
131
- }
122
+ fun shutdown (timeout : Long ) {
123
+ val deadline = System .currentTimeMillis() + timeout
124
+ if (! isShutdownRequested) debugStatus = SHUTDOWN_REQ
125
+ // loop while there is anything to do immediately or deadline passes
126
+ while (debugStatus != SHUTDOWN_ACK && _thread != null ) {
127
+ _thread ?.let { timeSource.unpark(it) } // wake up thread if present
128
+ val remaining = deadline - System .currentTimeMillis()
129
+ if (remaining <= 0 ) break
130
+ (this as Object ).wait(timeout)
132
131
}
133
132
// restore fresh status
134
133
debugStatus = FRESH
135
134
}
136
135
137
136
@Synchronized
138
- private fun acknowledgeShutdown () {
137
+ private fun acknowledgeShutdownIfNeeded () {
138
+ if (! isShutdownRequested) return
139
139
debugStatus = SHUTDOWN_ACK
140
140
resetAll() // clear queues
141
141
(this as Object ).notifyAll()
0 commit comments