@@ -215,8 +215,7 @@ class ThreadSafeFunction {
215215 resource,
216216 *v8::String::Utf8Value (env_->isolate, name)),
217217 thread_count(thread_count_),
218- is_closing(false ),
219- is_closed(false ),
218+ state(kOpen ),
220219 dispatch_state(kDispatchIdle ),
221220 context(context_),
222221 max_queue_size(max_queue_size_),
@@ -239,14 +238,14 @@ class ThreadSafeFunction {
239238 node::Mutex::ScopedLock lock (this ->mutex );
240239
241240 while (queue.size () >= max_queue_size && max_queue_size > 0 &&
242- !is_closing ) {
241+ state == kOpen ) {
243242 if (mode == napi_tsfn_nonblocking) {
244243 return napi_queue_full;
245244 }
246245 cond->Wait (lock);
247246 }
248247
249- if (!is_closing ) {
248+ if (state == kOpen ) {
250249 queue.push (data);
251250 Send ();
252251 return napi_ok;
@@ -255,7 +254,7 @@ class ThreadSafeFunction {
255254 return napi_invalid_arg;
256255 }
257256 thread_count--;
258- if (!is_closed || thread_count > 0 ) {
257+ if (!(state == kClosed && thread_count == 0 ) ) {
259258 return napi_closing;
260259 }
261260 }
@@ -267,13 +266,13 @@ class ThreadSafeFunction {
267266 napi_status Acquire () {
268267 node::Mutex::ScopedLock lock (this ->mutex );
269268
270- if (is_closing) {
271- return napi_closing;
272- }
269+ if (state == kOpen ) {
270+ thread_count++;
273271
274- thread_count++;
272+ return napi_ok;
273+ }
275274
276- return napi_ok ;
275+ return napi_closing ;
277276 }
278277
279278 napi_status Release (napi_threadsafe_function_release_mode mode) {
@@ -287,16 +286,18 @@ class ThreadSafeFunction {
287286 thread_count--;
288287
289288 if (thread_count == 0 || mode == napi_tsfn_abort) {
290- if (!is_closing) {
291- is_closing = (mode == napi_tsfn_abort);
292- if (is_closing && max_queue_size > 0 ) {
289+ if (state == kOpen ) {
290+ if (mode == napi_tsfn_abort) {
291+ state = kClosing ;
292+ }
293+ if (state == kClosing && max_queue_size > 0 ) {
293294 cond->Signal (lock);
294295 }
295296 Send ();
296297 }
297298 }
298299
299- if (!is_closed || thread_count > 0 ) {
300+ if (!(state == kClosed && thread_count == 0 ) ) {
300301 return napi_ok;
301302 }
302303 }
@@ -374,8 +375,8 @@ class ThreadSafeFunction {
374375
375376 protected:
376377 void ReleaseResources () {
377- if (!is_closed ) {
378- is_closed = true ;
378+ if (state != kClosed ) {
379+ state = kClosed ;
379380 ref.Reset ();
380381 node::RemoveEnvironmentCleanupHook (env->isolate , Cleanup, this );
381382 env->Unref ();
@@ -411,9 +412,7 @@ class ThreadSafeFunction {
411412
412413 {
413414 node::Mutex::ScopedLock lock (this ->mutex );
414- if (is_closing) {
415- CloseHandlesAndMaybeDelete ();
416- } else {
415+ if (state == kOpen ) {
417416 size_t size = queue.size ();
418417 if (size > 0 ) {
419418 data = queue.front ();
@@ -427,7 +426,7 @@ class ThreadSafeFunction {
427426
428427 if (size == 0 ) {
429428 if (thread_count == 0 ) {
430- is_closing = true ;
429+ state = kClosing ;
431430 if (max_queue_size > 0 ) {
432431 cond->Signal (lock);
433432 }
@@ -436,6 +435,8 @@ class ThreadSafeFunction {
436435 } else {
437436 has_more = true ;
438437 }
438+ } else {
439+ CloseHandlesAndMaybeDelete ();
439440 }
440441 }
441442
@@ -468,7 +469,7 @@ class ThreadSafeFunction {
468469 v8::HandleScope scope (env->isolate );
469470 if (set_closing) {
470471 node::Mutex::ScopedLock lock (this ->mutex );
471- is_closing = true ;
472+ state = kClosing ;
472473 if (max_queue_size > 0 ) {
473474 cond->Signal (lock);
474475 }
@@ -540,6 +541,8 @@ class ThreadSafeFunction {
540541 using node::AsyncResource::CallbackScope;
541542 };
542543
544+ enum State : unsigned char { kOpen , kClosing , kClosed };
545+
543546 static const unsigned char kDispatchIdle = 0 ;
544547 static const unsigned char kDispatchRunning = 1 << 0 ;
545548 static const unsigned char kDispatchPending = 1 << 1 ;
@@ -554,8 +557,7 @@ class ThreadSafeFunction {
554557 std::queue<void *> queue;
555558 uv_async_t async;
556559 size_t thread_count;
557- bool is_closing;
558- bool is_closed;
560+ State state;
559561 std::atomic_uchar dispatch_state;
560562
561563 // These are variables set once, upon creation, and then never again, which
0 commit comments