Skip to content

Commit 2ed5fbb

Browse files
committed
Trying to improve nodejs destruction.
1 parent 3b0f405 commit 2ed5fbb

File tree

1 file changed

+50
-4
lines changed

1 file changed

+50
-4
lines changed

source/loaders/node_loader/source/node_loader_impl.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,9 @@ template <typename T>
326326
struct 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+
17791825
function_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

Comments
 (0)