@@ -217,8 +217,7 @@ class ThreadSafeFunction {
217217 resource,
218218 node::Utf8Value (env_->isolate, name).ToStringView()),
219219 thread_count(thread_count_),
220- is_closing(false ),
221- is_closed(false ),
220+ state(kOpen ),
222221 dispatch_state(kDispatchIdle ),
223222 context(context_),
224223 max_queue_size(max_queue_size_),
@@ -241,14 +240,14 @@ class ThreadSafeFunction {
241240 node::Mutex::ScopedLock lock (this ->mutex );
242241
243242 while (queue.size () >= max_queue_size && max_queue_size > 0 &&
244- !is_closing ) {
243+ state == kOpen ) {
245244 if (mode == napi_tsfn_nonblocking) {
246245 return napi_queue_full;
247246 }
248247 cond->Wait (lock);
249248 }
250249
251- if (!is_closing ) {
250+ if (state == kOpen ) {
252251 queue.push (data);
253252 Send ();
254253 return napi_ok;
@@ -257,7 +256,7 @@ class ThreadSafeFunction {
257256 return napi_invalid_arg;
258257 }
259258 thread_count--;
260- if (!is_closed || thread_count > 0 ) {
259+ if (!(state == kClosed && thread_count == 0 ) ) {
261260 return napi_closing;
262261 }
263262 }
@@ -269,13 +268,13 @@ class ThreadSafeFunction {
269268 napi_status Acquire () {
270269 node::Mutex::ScopedLock lock (this ->mutex );
271270
272- if (is_closing) {
273- return napi_closing;
274- }
271+ if (state == kOpen ) {
272+ thread_count++;
275273
276- thread_count++;
274+ return napi_ok;
275+ }
277276
278- return napi_ok ;
277+ return napi_closing ;
279278 }
280279
281280 napi_status Release (napi_threadsafe_function_release_mode mode) {
@@ -289,16 +288,18 @@ class ThreadSafeFunction {
289288 thread_count--;
290289
291290 if (thread_count == 0 || mode == napi_tsfn_abort) {
292- if (!is_closing) {
293- is_closing = (mode == napi_tsfn_abort);
294- if (is_closing && max_queue_size > 0 ) {
291+ if (state == kOpen ) {
292+ if (mode == napi_tsfn_abort) {
293+ state = kClosing ;
294+ }
295+ if (state == kClosing && max_queue_size > 0 ) {
295296 cond->Signal (lock);
296297 }
297298 Send ();
298299 }
299300 }
300301
301- if (!is_closed || thread_count > 0 ) {
302+ if (!(state == kClosed && thread_count == 0 ) ) {
302303 return napi_ok;
303304 }
304305 }
@@ -376,8 +377,8 @@ class ThreadSafeFunction {
376377
377378 protected:
378379 void ReleaseResources () {
379- if (!is_closed ) {
380- is_closed = true ;
380+ if (state != kClosed ) {
381+ state = kClosed ;
381382 ref.Reset ();
382383 node::RemoveEnvironmentCleanupHook (env->isolate , Cleanup, this );
383384 env->Unref ();
@@ -413,9 +414,7 @@ class ThreadSafeFunction {
413414
414415 {
415416 node::Mutex::ScopedLock lock (this ->mutex );
416- if (is_closing) {
417- CloseHandlesAndMaybeDelete ();
418- } else {
417+ if (state == kOpen ) {
419418 size_t size = queue.size ();
420419 if (size > 0 ) {
421420 data = queue.front ();
@@ -429,7 +428,7 @@ class ThreadSafeFunction {
429428
430429 if (size == 0 ) {
431430 if (thread_count == 0 ) {
432- is_closing = true ;
431+ state = kClosing ;
433432 if (max_queue_size > 0 ) {
434433 cond->Signal (lock);
435434 }
@@ -438,6 +437,8 @@ class ThreadSafeFunction {
438437 } else {
439438 has_more = true ;
440439 }
440+ } else {
441+ CloseHandlesAndMaybeDelete ();
441442 }
442443 }
443444
@@ -470,7 +471,7 @@ class ThreadSafeFunction {
470471 v8::HandleScope scope (env->isolate );
471472 if (set_closing) {
472473 node::Mutex::ScopedLock lock (this ->mutex );
473- is_closing = true ;
474+ state = kClosing ;
474475 if (max_queue_size > 0 ) {
475476 cond->Signal (lock);
476477 }
@@ -542,6 +543,8 @@ class ThreadSafeFunction {
542543 using node::AsyncResource::CallbackScope;
543544 };
544545
546+ enum State : unsigned char { kOpen , kClosing , kClosed };
547+
545548 static const unsigned char kDispatchIdle = 0 ;
546549 static const unsigned char kDispatchRunning = 1 << 0 ;
547550 static const unsigned char kDispatchPending = 1 << 1 ;
@@ -556,8 +559,7 @@ class ThreadSafeFunction {
556559 std::queue<void *> queue;
557560 uv_async_t async;
558561 size_t thread_count;
559- bool is_closing;
560- bool is_closed;
562+ State state;
561563 std::atomic_uchar dispatch_state;
562564
563565 // These are variables set once, upon creation, and then never again, which
0 commit comments