@@ -326,8 +326,9 @@ template <typename T>
326326struct loader_impl_threadsafe_type
327327{
328328 napi_threadsafe_function threadsafe_function;
329+ std::atomic<bool > threadsafe_function_released;
329330
330- void initialize (napi_env env, std::string name, void (*safe_func_ptr)(napi_env, T *))
331+ void initialize (napi_env env, std::string name, void (*safe_func_ptr)(napi_env, T *), bool release_safe = false )
331332 {
332333 napi_value func_safe_ptr;
333334
@@ -346,13 +347,23 @@ struct loader_impl_threadsafe_type
346347 /* Use the amoun of available threads as initial thread count */
347348 unsigned int processor_count = std::thread::hardware_concurrency ();
348349
350+ /* Register safety function for controlling release of thread safe function */
351+ threadsafe_function_released.store (false );
352+
353+ auto finalize_callback = [](napi_env, void *finalize_data, void *) {
354+ loader_impl_threadsafe_type *threadsafe_function = static_cast <loader_impl_threadsafe_type *>(finalize_data);
355+ threadsafe_function->threadsafe_function_released .store (true );
356+ };
357+
358+ auto finalize_cb_null = static_cast <void (*)(napi_env, void *, void *)>(nullptr );
359+
349360 /* Cast the safe function */
350361 node_loader_impl_func_call_js_safe_cast<T> safe_cast (safe_func_ptr);
351362
352363 status = napi_create_threadsafe_function (env, func_safe_ptr,
353364 nullptr , threadsafe_func_name,
354365 0 , processor_count,
355- nullptr , nullptr ,
366+ this , release_safe ? finalize_callback : finalize_cb_null ,
356367 safe_cast.context , &node_loader_impl_func_call_js_safe<T>,
357368 &threadsafe_function);
358369
@@ -398,6 +409,23 @@ struct loader_impl_threadsafe_type
398409 }
399410 }
400411
412+ void release_safe (loader_impl_async_safe_type<T> &async_safe)
413+ {
414+ /* Unlock the mutex */
415+ async_safe.unlock ();
416+
417+ if (!threadsafe_function_released.load ())
418+ {
419+ /* Release call safe function */
420+ napi_status status = napi_release_threadsafe_function (threadsafe_function, napi_tsfn_release);
421+
422+ if (status != napi_ok)
423+ {
424+ log_write (" metacall" , LOG_LEVEL_ERROR, " Invalid to release thread safe function invoke function in NodeJS loader" );
425+ }
426+ }
427+ }
428+
401429 void abort (napi_env env)
402430 {
403431 napi_status status = napi_release_threadsafe_function (threadsafe_function, napi_tsfn_abort);
@@ -1776,6 +1804,24 @@ struct loader_impl_threadsafe_invoke_type
17761804 }
17771805};
17781806
1807+ template <typename T>
1808+ struct loader_impl_threadsafe_invoke_safe_type
1809+ {
1810+ loader_impl_threadsafe_type<T> &threadsafe_func;
1811+ loader_impl_async_safe_type<T> async_safe;
1812+
1813+ loader_impl_threadsafe_invoke_safe_type (loader_impl_threadsafe_type<T> &threadsafe_func, T &func_safe) :
1814+ threadsafe_func (threadsafe_func), async_safe(func_safe)
1815+ {
1816+ threadsafe_func.invoke (async_safe);
1817+ }
1818+
1819+ ~loader_impl_threadsafe_invoke_safe_type ()
1820+ {
1821+ threadsafe_func.release_safe (async_safe);
1822+ }
1823+ };
1824+
17791825function_return function_node_interface_invoke(function func, function_impl impl, function_args args, size_t size)
17801826{
17811827 loader_impl_node_function node_func = static_cast <loader_impl_node_function>(impl);
@@ -3634,7 +3680,7 @@ void *node_loader_impl_register(void *node_impl_ptr, void *env_ptr, void *functi
36343680 node_impl->threadsafe_func_destroy .initialize (env, " node_loader_impl_async_func_destroy_safe" , &node_loader_impl_func_destroy_safe);
36353681 node_impl->threadsafe_future_await .initialize (env, " node_loader_impl_async_future_await_safe" , &node_loader_impl_future_await_safe);
36363682 node_impl->threadsafe_future_delete .initialize (env, " node_loader_impl_async_future_delete_safe" , &node_loader_impl_future_delete_safe);
3637- node_impl->threadsafe_destroy .initialize (env, " node_loader_impl_async_destroy_safe" , &node_loader_impl_destroy_safe);
3683+ node_impl->threadsafe_destroy .initialize (env, " node_loader_impl_async_destroy_safe" , &node_loader_impl_destroy_safe, true );
36383684 }
36393685
36403686/* Run test function, this one can be called without thread safe mechanism */
@@ -4645,7 +4691,7 @@ void node_loader_impl_try_destroy(loader_impl_node node_impl)
46454691 else
46464692 {
46474693 /* Submit the task to the async queue */
4648- loader_impl_threadsafe_invoke_type <loader_impl_async_destroy_safe_type> invoke (node_impl->threadsafe_destroy , destroy_safe);
4694+ loader_impl_threadsafe_invoke_safe_type <loader_impl_async_destroy_safe_type> invoke (node_impl->threadsafe_destroy , destroy_safe);
46494695 }
46504696
46514697 if (loader_impl_get_option_host (node_impl->impl ) == 0 )
0 commit comments