@@ -223,6 +223,7 @@ struct loader_impl_node_type
223223 loader_impl_async_initialize_safe initialize_safe;
224224 napi_threadsafe_function threadsafe_initialize;
225225
226+ /* TODO: Remove all napi_value and arguments from here -> */
226227 napi_value execution_path_safe_ptr;
227228 loader_impl_async_execution_path_safe execution_path_safe;
228229 napi_threadsafe_function threadsafe_execution_path;
@@ -243,8 +244,8 @@ struct loader_impl_node_type
243244 loader_impl_async_discover_safe discover_safe;
244245 napi_threadsafe_function threadsafe_discover;
245246
246- napi_value func_call_safe_ptr;
247- loader_impl_async_func_call_safe func_call_safe;
247+ // napi_value func_call_safe_ptr;
248+ // loader_impl_async_func_call_safe func_call_safe;
248249 napi_threadsafe_function threadsafe_func_call;
249250
250251 napi_value func_await_safe_ptr;
@@ -266,10 +267,12 @@ struct loader_impl_node_type
266267 napi_value destroy_safe_ptr;
267268 loader_impl_async_destroy_safe destroy_safe;
268269 napi_threadsafe_function threadsafe_destroy;
270+ /* TODO: -> To here*/
269271
270272 uv_thread_t thread;
271273 uv_loop_t *thread_loop;
272274
275+ /* TODO: Delete mutex and condition */
273276 uv_mutex_t mutex;
274277 uv_cond_t cond;
275278 std::atomic_bool locked;
@@ -372,6 +375,9 @@ struct loader_impl_async_func_call_safe_type
372375 size_t size;
373376 napi_value recv;
374377 function_return ret;
378+
379+ uv_mutex_t mutex;
380+ uv_cond_t cond;
375381};
376382
377383struct loader_impl_async_func_await_safe_type
@@ -1360,38 +1366,88 @@ int function_node_interface_create(function func, function_impl impl)
13601366 return (node_func->argv == NULL );
13611367}
13621368
1369+ /* TODO: Convert this into a templated lambda */
1370+ void node_loader_impl_function_call_js_func_call_safe (napi_env env, napi_value js_callback, void *context, void *data)
1371+ {
1372+ loader_impl_async_func_call_safe func_call_safe = static_cast <loader_impl_async_func_call_safe>(data);
1373+
1374+ (void )js_callback;
1375+ (void )context;
1376+
1377+ if (env != NULL && js_callback != NULL )
1378+ {
1379+ /* Lock the call safe mutex and get the parameters */
1380+ uv_mutex_lock (&func_call_safe->mutex );
1381+
1382+ /* Store environment for reentrant calls */
1383+ func_call_safe->node_impl ->env = env;
1384+
1385+ /* Call to the implementation function */
1386+ node_loader_impl_func_call_safe (env, func_call_safe);
1387+
1388+ /* Clear environment */
1389+ // func_call_cast.safe->node_impl->env = NULL;
1390+
1391+ /* Signal function call condition */
1392+ uv_cond_signal (&func_call_safe->cond );
1393+
1394+ uv_mutex_unlock (&func_call_safe->mutex );
1395+ }
1396+ }
1397+
13631398function_return function_node_interface_invoke(function func, function_impl impl, function_args args, size_t size)
13641399{
13651400 loader_impl_node_function node_func = (loader_impl_node_function)impl;
13661401
13671402 if (node_func != NULL )
13681403 {
13691404 loader_impl_node node_impl = node_func->node_impl ;
1370- function_return ret = NULL ;
13711405 napi_status status;
13721406
1373- /* Set up call safe arguments */
1374- node_impl->func_call_safe ->node_impl = node_impl;
1375- node_impl->func_call_safe ->func = func;
1376- node_impl->func_call_safe ->node_func = node_func;
1377- node_impl->func_call_safe ->args = static_cast <void **>(args);
1378- node_impl->func_call_safe ->size = size;
1379- node_impl->func_call_safe ->recv = NULL ;
1380- node_impl->func_call_safe ->ret = NULL ;
1381-
13821407 /* Check if we are in the JavaScript thread */
13831408 if (node_impl->js_thread_id == std::this_thread::get_id ())
13841409 {
1410+ loader_impl_async_func_call_safe_type func_call_safe;
1411+
1412+ /* Set up call safe arguments */
1413+ func_call_safe.node_impl = node_impl;
1414+ func_call_safe.func = func;
1415+ func_call_safe.node_func = node_func;
1416+ func_call_safe.args = static_cast <void **>(args);
1417+ func_call_safe.size = size;
1418+ func_call_safe.recv = NULL ;
1419+ func_call_safe.ret = NULL ;
1420+
13851421 /* We are already in the V8 thread, we can call safely */
1386- node_loader_impl_func_call_safe (node_impl->env , node_impl-> func_call_safe );
1422+ node_loader_impl_func_call_safe (node_impl->env , & func_call_safe);
13871423
13881424 /* Set up return of the function call */
1389- ret = node_impl-> func_call_safe -> ret ;
1425+ return func_call_safe. ret ;
13901426 }
1427+
1428+ /* TODO: Refactor this properly */
1429+
13911430 /* Lock the mutex and set the parameters */
1392- else if (node_impl->locked .load () == false && uv_mutex_trylock (&node_impl->mutex ) == 0 )
1431+ // if (node_impl->locked.load() == false && uv_mutex_trylock(&node_impl->mutex) == 0)
13931432 {
1394- node_impl->locked .store (true );
1433+ loader_impl_async_func_call_safe_type func_call_safe;
1434+ function_return ret = NULL ;
1435+
1436+ // node_impl->locked.store(true);
1437+
1438+ /* Set up call safe arguments */
1439+ func_call_safe.node_impl = node_impl;
1440+ func_call_safe.func = func;
1441+ func_call_safe.node_func = node_func;
1442+ func_call_safe.args = static_cast <void **>(args);
1443+ func_call_safe.size = size;
1444+ func_call_safe.recv = NULL ;
1445+ func_call_safe.ret = NULL ;
1446+
1447+ uv_mutex_init (&func_call_safe.mutex );
1448+ uv_cond_init (&func_call_safe.cond );
1449+
1450+ uv_mutex_lock (&func_call_safe.mutex );
13951451
13961452 /* Acquire the thread safe function in order to do the call */
13971453 status = napi_acquire_threadsafe_function (node_impl->threadsafe_func_call );
@@ -1402,13 +1458,24 @@ function_return function_node_interface_invoke(function func, function_impl impl
14021458 }
14031459
14041460 /* Execute the thread safe call in a nonblocking manner */
1405- status = napi_call_threadsafe_function (node_impl->threadsafe_func_call , nullptr , napi_tsfn_nonblocking);
1461+ status = napi_call_threadsafe_function (node_impl->threadsafe_func_call , &func_call_safe , napi_tsfn_nonblocking);
14061462
14071463 if (status != napi_ok)
14081464 {
14091465 log_write (" metacall" , LOG_LEVEL_ERROR, " Invalid to call to thread safe function invoke function in NodeJS loader" );
14101466 }
14111467
1468+ /* Wait for the execution of the safe call */
1469+ uv_cond_wait (&func_call_safe.cond , &func_call_safe.mutex );
1470+
1471+ /* Set up return of the function call */
1472+ ret = func_call_safe.ret ;
1473+
1474+ // node_impl->locked.store(false);
1475+
1476+ /* Unlock the mutex */
1477+ uv_mutex_unlock (&func_call_safe.mutex );
1478+
14121479 /* Release call safe function */
14131480 status = napi_release_threadsafe_function (node_impl->threadsafe_func_call , napi_tsfn_release);
14141481
@@ -1417,23 +1484,11 @@ function_return function_node_interface_invoke(function func, function_impl impl
14171484 log_write (" metacall" , LOG_LEVEL_ERROR, " Invalid to release thread safe function invoke function in NodeJS loader" );
14181485 }
14191486
1420- /* Wait for the execution of the safe call */
1421- uv_cond_wait (&node_impl->cond , &node_impl->mutex );
1422-
1423- /* Set up return of the function call */
1424- ret = node_impl->func_call_safe ->ret ;
1425-
1426- node_impl->locked .store (false );
1487+ uv_mutex_destroy (&func_call_safe.mutex );
1488+ uv_cond_destroy (&func_call_safe.cond );
14271489
1428- /* Unlock the mutex */
1429- uv_mutex_unlock (&node_impl->mutex );
1430- }
1431- else
1432- {
1433- log_write (" metacall" , LOG_LEVEL_ERROR, " Potential deadlock detected in function_node_interface_invoke, the call has not been executed in order to avoid the deadlock" );
1490+ return ret;
14341491 }
1435-
1436- return ret;
14371492 }
14381493
14391494 return NULL ;
@@ -3876,15 +3931,51 @@ void *node_loader_impl_register(void *node_impl_ptr, void *env_ptr, void *functi
38763931
38773932 /* Safe function call */
38783933 {
3934+ /* TODO: Refactor this */
3935+
38793936 static const char threadsafe_func_name_str[] = " node_loader_impl_async_func_call_safe" ;
38803937
3938+ /*
38813939 node_loader_impl_thread_safe_function_initialize<loader_impl_async_func_call_safe_type>(
38823940 env,
38833941 threadsafe_func_name_str, sizeof(threadsafe_func_name_str),
38843942 &node_loader_impl_async_func_call_safe,
38853943 (loader_impl_async_func_call_safe_type **)(&node_impl->func_call_safe),
38863944 &node_impl->func_call_safe_ptr,
38873945 &node_impl->threadsafe_func_call);
3946+ */
3947+
3948+ /*
3949+ void node_loader_impl_thread_safe_function_initialize(napi_env env,
3950+ const char name[], size_t size, napi_value (*callback)(napi_env, napi_callback_info), T **data,
3951+ napi_value *ptr, napi_threadsafe_function *threadsafe_function)
3952+ */
3953+
3954+ napi_value func_call_safe_ptr;
3955+
3956+ /* Initialize call safe function with context */
3957+ status = napi_create_function (env, nullptr , 0 , &node_loader_impl_async_func_call_safe, nullptr , &func_call_safe_ptr);
3958+
3959+ node_loader_impl_exception (env, status);
3960+
3961+ /* Create call safe function */
3962+ napi_value threadsafe_func_name;
3963+
3964+ status = napi_create_string_utf8 (env, threadsafe_func_name_str, sizeof (threadsafe_func_name_str), &threadsafe_func_name);
3965+
3966+ node_loader_impl_exception (env, status);
3967+
3968+ // TODO: Does this number must be equivalent to the number of the threads of NodeJS?
3969+ unsigned int processor_count = std::thread::hardware_concurrency ();
3970+
3971+ status = napi_create_threadsafe_function (env, func_call_safe_ptr,
3972+ nullptr , threadsafe_func_name,
3973+ 0 , processor_count,
3974+ nullptr , nullptr ,
3975+ nullptr , &node_loader_impl_function_call_js_func_call_safe,
3976+ &node_impl->threadsafe_func_call );
3977+
3978+ node_loader_impl_exception (env, status);
38883979 }
38893980
38903981 /* Safe function await */
@@ -5389,7 +5480,7 @@ int node_loader_impl_destroy(loader_impl impl)
53895480 delete node_impl->load_from_memory_safe ;
53905481 delete node_impl->clear_safe ;
53915482 delete node_impl->discover_safe ;
5392- delete node_impl->func_call_safe ;
5483+ // delete node_impl->func_call_safe;
53935484 delete node_impl->func_await_safe ;
53945485 delete node_impl->func_destroy_safe ;
53955486 delete node_impl->future_await_safe ;
0 commit comments