Lua C API - attaching data to a coroutine - c

Is there a way to attach data to a coroutine, or at least to somehow identify different coroutines?
I am trying to implement a timer API where the timers are controlled by the host, that looks something like the following on the Lua side:
function callback()
local timer = ElapsedTimer()
...
end
function main()
local timer = CreateTimer(...)
StartTimer(timer, callback, ...)
end
The StartTimer() call sends the timer and callback to the C side, and the C side will eventually call the callback in a new coroutine.
The call to ElapsedTimer() needs to return data that is specific to this coroutine/thread, i.e. in this case the timer.
In pseudo code:
int StartTimer(lua_State* L) {
auto timer = ...;
auto coroutine = ???
coroutine.userdata = &timer; // But probably store an actual structure with more pointers
return 0;
}
int ElapsedTimer(lua_State* L) {
auto coroutine = ???
auto timer = (Timer*)coroutine.userdata;
lua_pushlightuserdata(L, timer)
return 1;
}

This is what userdata is for:
int StartTimer(lua_State* L) {
TimerStruct timer = (TimerStruct*)lua_newuserdata(L, sizeof(TimerStruct));
//allocates some memory and returns pointer to it
timer->//...
// lua_setuservalue will let you bind the callback to the timer
return 1; //actually return it
}
Also it is going to be easier to pass the timer along
function callback(timer)
...
end
That way the lua code doesn't need to query that value. It already got it.

I just now realized I need to use lua_newthread to create the coroutine, which means I have a separate lua_State object.
This means I can always create a mapping between the coroutine's state and whatever data I want in the host language (e.g. in a map data structure)

Related

How to use napi_threadsafe_function for NodeJS Native Addon

I've been looking through the NAPI documentation to try and understand how it deals with multithreading. According to the documentation napi_create_threadsafe_function() and napi_call_threadsafe_function() are used to create and call js functions from multiple threads. The issue is that the documentation is not that straight forward, and there are no examples and I can't find any anywhere else.
If anyone has any experience using napi_create_threadsafe_function() and napi_call_threadsafe_function() or know where to find examples of them being used. Please if you could help out with a a basic example so I can just understand how to use them correctly.
I'm writting a C addon not C++ and need to use these functions. I am not using the wrapper node-addon-api, but napi directly
As a summery tag we may say, the N-API ThreadSafeFunctions acts as a safe tunnel between the asynchronous C/C++ code executing on a worker thread and the JavaScript layer for information exchange.
Before going technical let us consider a scenario that we have a very long running process heavy task to be completed. We all know putting this task on node.js main thread is not a good choice, it will chock the event loop and block all other task in the queue. So a good choice could be to consider this task in a separate thread (let us call this thread as a worker thread). JavaScript asynchronous callback and Promise are doing exactly this approach.
Let us say we have deployed the task on a worker thread and we are ready with a portion of result and we would like it to be send to JavaScript layer. Then the process involve are, converting the result into napi_value and then call the Callback JavaScript function from C/C++. Unfortunately neither of the operation can be performed from a worker thread; these operations should be exclusively done from the main thread. The JavaScript Promise and Callback, wait till the task completion and then switch over to main thread along with the task result in a normal C/C++ storage facility such as structure etc. Then do the napi_value conversion and call the JavaScript callback function from the main thread.
Since our task is extremely long running probably we don't want to wait till the end of the task before exchanging the result with JavaScript layer.
Let us consider a scenario where we are searching objects in a very large video where we prefer to get the detected objects send to JavaScript layer as on when it is found.
In such a scenario we will have to start sending task result while the task is still in progress. This is the scenario where Asynchronous Thread-safe Function Calls come for our help. It acts as a safe tunnel between the worker thread and the JavaScript layer for information exchange. Let us consider the following function snippet
napi_value CAsyncStreamSearch(napi_env env, napi_callback_info info)
{
// The native addon function exposed to JavaScript
// This will be the funciton a node.js application calling.
}
void ExecuteWork(napi_env env, void* data)
{
// We will use this function to get the task done.
// This code will be executed on a worker thread.
}
void OnWorkComplete(napi_env env, napi_status status, void* data)
{
// after the `ExecuteWork` function exits, this
// callback function will be called on the main thread
}
void ThreadSafeCFunction4CallingJS(napi_env env, napi_value js_cb,
void* context, void* data)
{
// This funcion acts as a safe tunnel between the asynchronous C/C++ code
// executing the worker thread and the JavaScript layer for information exchange.
}
In this first three functions are nearly same as JavaScript Promise and Callback that we are familiar with. The fourth one is specifically for the Asynchronous Thread-safe Function Calls. In this, our long running task is being executed by ExecuteWork() function on a worker thread. Let us say it has instructed us not to call JavaScript (and also any napi_value conversion of result) from ExecuteWork() but permitted to do so from ThreadSafeCFunction4CallingJS as long as we are calling ThreadSafeCFunction4CallingJS with an napi equivalent of C/C++ function pointer. Then we could pack the JavaScript calls inside this ThreadSafeCFunction4CallingJS() function. Then when ExecuteWork() function could pass the result to ThreadSafeCFunction4CallingJS() while it is being invoked in a plain C/C++ storage units such as structure etc. The ThreadSafeCFunction4CallingJS() convert this result to napi_value and call JavaScript function.
Under the cover the ThreadSafeCFunction4CallingJS() function is being queue to the event loop, and eventually it get executed by main thread.
The following code snippet packed inside CAsyncStreamSearch() is responsible for creating a C/C++ function pointer equivalent of N-API by usng napi_create_threadsafe_function() and it is being done from the native addon's main thread itself. Similarly the request for creation of worker thread by using napi_create_async_work() function then placing the work int the event queue by using napi_queue_async_work() so that a worker thread will pickup this item in the future.
napi_value CAsyncStreamSearch(napi_env env, napi_callback_info info)
{
-- -- -- --
-- -- -- --
// Create a thread-safe N-API callback function correspond to the C/C++ callback function
napi_create_threadsafe_function(env,
js_cb, NULL, work_name, 0, 1, NULL, NULL, NULL,
ThreadSafeCFunction4CallingJS, // the C/C++ callback function
// out: the asynchronous thread-safe JavaScript function
&(async_stream_data_ex->tsfn_StreamSearch));
// Create an async work item, that can be deployed in the node.js event queue
napi_create_async_work( env, NULL,
work_name,
ExecuteWork,
OnWorkComplete,
async_stream_data_ex,
// OUT: THE handle to the async work item
&(async_stream_data_ex->work_StreamSearch);)
// Queue the work item for execution.
napi_queue_async_work(env, async_stream_data_ex->work_StreamSearch);
return NULL;
}
Then during the asynchronous execution of task (ExecuteWork() function) invokes ThreadSafeCFunction4CallingJS() by calling napi_call_threadsafe_function() function as shown bellow.
static void ExecuteWork(napi_env env, void *data)
{
// tsfn is napi equivalent of point to ThreadSafeCFunction4CallingJS
// function that we created at CAsyncStreamSearch function
napi_acquire_threadsafe_function( tsfn )
Loop
{
// this will eventually invoke ThreadSafeCFunction4CallingJS()
// we may call any number of time (in fact it can be called from any thread)
napi_call_threadsafe_function( tsfn, WorkResult, );
}
napi_release_threadsafe_function( tsfn,);
}
The example you pointed out is one of the best source of information and it is directly form node.js team itself. When I was learning this concept I too was referring the same example, during my study the example has been recreated by extracting original idea from it, hope you may find this much simplified. and it is available at
https://github.com/msatyan/MyNodeC/blob/master/src/mync1/ThreadSafeAsyncStream.cpp
https://github.com/msatyan/MyNodeC/blob/master/test/ThreadSafeAsyncStream.js
If anyone else gets stuck with this issue. I finally managed to hunt down an example here.
Once I understand it better and have gotten a working sample, I will update here. Hopefully someone needing this in the future will have an easier time than me.
See Satyan's answer
The solution from this site worked for me here
struct ThreadCtx {
ThreadCtx(Napi::Env env) {};
std::thread nativeThread;
Napi::ThreadSafeFunction tsfn;
};
void Target::Connect(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
threadCtx = new ThreadCtx(env);
// Create a ThreadSafeFunction
threadCtx->tsfn = Napi::ThreadSafeFunction::New(env, info[0].As<Napi::Function>(), "Resource Name", 0 /* Unlimited queue */, 1 /* Only 1 thread */, threadCtx,
[&]( Napi::Env, void *finalizeData, ThreadCtx *context ) {
printf("Thread cleanup\n");
threadCtx->nativeThread.join();
},
(void*)nullptr
);
// Create a native thread
threadCtx->nativeThread = std::thread([&] {
auto callback = [](Napi::Env env, Napi::Function cb, char* buffer) {
cb.Call({Napi::String::New(env, buffer)});
};
char reply[1024];
memset(reply, 0, sizeof(reply));
while(true)
{
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, sizeof(reply)));
if(reply_length <= 0) {
printf("Bad read from boost asio\n");
break;
}
// Callback (blocking) to JS
napi_status status = threadCtx->tsfn.BlockingCall(reply, callback);
if (status != napi_ok)
{
// Handle error
break;
}
}
// Release the thread-safe function
threadCtx->tsfn.Release();
});
}
addon.cc - (tested and 100% working)
#include <napi.h>
Napi::Value SAFE_THREAD(const Napi::CallbackInfo& info) {
std::thread([](Napi::ThreadSafeFunction tsfn){
struct output_data{
int arg1;
std::string arg2;
};
auto data = new output_data();
///---------------
///fill output data
data->arg1=1;
data->arg2="string data";
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
///---------------
///output thread result to nodejs
napi_status status = tsfn.BlockingCall(data,[](Napi::Env env, Napi::Function jsCallback,output_data* data){
jsCallback.Call({Napi::Number::New(env, data->arg1), String::New(env, data->arg2)});
delete data;
});
if(status != napi_ok) { std::cout << "error!" << "\n"; }
tsfn.Release();
},Napi::ThreadSafeFunction::New(info.Env(), info[0].As<Function>(), "TSFN", 0, 1,[](Napi::Env env, void *finalizeData){},(void *)nullptr)).detach();
return info.Env().Null();
}
index.js
const ADDON = require('./THREAD/build/Release/addon');
function time_sec(){return (new Date()).getTime()/1000;}
var t = time_sec();
ADDON.SAFE_THREAD((arg1,arg2)=>{
console.log(time_sec()-t, 'arg1 = '+arg1)
console.log(time_sec()-t, 'arg2 = '+arg2)
});
console.log(time_sec()-t, 'fin')
output:
0.00099992752075 fin
2.00499987602233 arg1 = 1
2.00600004196167 arg2 = string data
see also how to emit data from thread

Alternative to blocking code

Attempting to use mbed OS scheduler for a small project.
As mbed os is Asynchronous I need to avoid blocking code.
However the library for my wireless receiver uses a blocking line of:
while (!(wireless.isRxData()));
Is there an alternative way to do this that won't block all the code until a message is received?
static void listen(void) {
wireless.quickRxSetup(channel, addr1);
sprintf(ackData,"Ack data \r\n");
wireless.acknowledgeData(ackData, strlen(ackData), 1);
while (!(wireless.isRxData()));
len = wireless.getRxData(msg);
}
static void motor(void) {
pc.printf("Motor\n");
m.speed(1);
n.speed(1);
led1 = 1;
wait(0.5);
m.speed(0);
n.speed(0);
}
static void sendData() {
wireless.quickTxSetup(channel, addr1);
strcpy(accelData, "Robot");
wireless.transmitData(accelData ,strlen(accelData));
}
void app_start(int, char**) {
minar::Scheduler::postCallback(listen).period(minar::milliseconds(500)).tolerance(minar::milliseconds(1000));
minar::Scheduler::postCallback(motor).period(minar::milliseconds(500));
minar::Scheduler::postCallback(sendData).period(minar::milliseconds(500)).delay(minar::milliseconds(3000));
}
You should remove the while (!(wireless.isRxData())); loop in your listen function. Replace it with:
if (wireless.isRxData()) {
len = wireless.getRxData(msg);
// Process data
}
Then, you can process your data in that if statement, or you can call postCallback on another function that will do your processing.
Instead of looping until data is available, you'll want to poll for data. If RX data is not available, exit the function and set a timer to go off after a short interval. When the timer goes off, check for data again. Repeat until data is available. I'm not familiar with your OS so I can't offer any specific code. This may be as simple as adding a short "sleep" call inside the while loop, or may involve creating another callback from the scheduler.

How to implement separate static variables for a given function called with different parameters

I am currently working on a microcontroller project in C that requires several timed functions to take place. I am a using a hardware timer to produce an interrupt every millisecond, and variables as counters to produce the appropriate time intervals. The hardware details are not important.
As an example, for a particular function, the following code would be executed on every tick of the 1ms counter, resulting in Function() being called every 10ms.
if (count < 10)
{
count++;
}
else
{
Function();
count = 0;
}
I would like to implement a wrapper function to avoid rewriting the counter code for every different interval, i.e:
TimerWrapper(required interval 1, Function 1 pointer)
TimerWrapper(required interval 2, Function 2 pointer)
and call it on every tick of the timer. For this to work, each different function called by the wrapper needs to have a separate count variable that needs to persist between calls of TimerWrapper(). I would like to keep all of the implementation details separate from my main program and introduce as few variables into my main program as possible.
Is it possible to do what I am asking, or is there a simpler/better way to achieve the same effect? I know how I would do this with an object oriented language but my skills are lacking in plain C.
I would think in terms of a structure along the lines of:
struct interrupt_responder
{
int count;
int rep_count;
void (*handler)(void);
};
You then create as many such structures as you have different counters, appropriately initialized:
static struct interrupt_responder c1 = { 0, 10, Function };
You arrange to call a function with the responder:
void time_wrapper(struct interrupt_responder *r)
{
if (++r->count >= r->max_count)
{
r->count = 0;
(*r->handler)();
}
}
The function called in response to an interrupt then simply needs to know how to dispatch calls to time_wrapper with the appropriate argument each time.
void millisecond_interrupt_handler(void)
{
time_wrapper(&c1);
…
}
Or you can have an array of the interrupt responders, and the millisecond interrupt handler can loop over the array, calling the time wrapper function.
You would have a set of file scope variables for the interrupt responders, but they'd not need to be visible outside the file. If you need different argument lists for the handler functions, life is trickier — avoid that if you possibly can. However, it seems from a comment that it won't be a problem — the embedded functions pointers will always be void (*handler)(void).

calling IO Operations from thread in ruby c extension will cause ruby to hang

I have a problem with using threads in a C Extension to run ruby code async.
I have the following C code:
struct DATA {
VALUE callback;
pthread_t watchThread;
void *ptr;
};
void *executer(void *ptr) {
struct DATA *data = (struct DATA *) ptr;
char oldVal[20] = "1";
char newVal[20] = "1";
pthread_cleanup_push(&threadGarbageCollector, data);
while(1) {
if(triggerReceived) {
rb_funcall(data->callback, rb_intern("call"), 0);
}
}
pthread_cleanup_pop(1);
return NULL;
}
VALUE spawn_thread(VALUE self) {
VALUE block;
struct DATA *data;
Data_Get_Struct(self, struct DATA, data);
block = rb_block_proc();
data->callback = block;
pthread_create(&data->watchThread, NULL, &executer, data);
return self;
}
I am using this because I want to provide ruby-code as a callback, which will be executed, once the Thread receives a signal.
In general this is working fine, if the callback is something like this ruby-code:
1 + 1
But, if the callbacks ruby-code looks like this:
puts "test"
than the main ruby process will stop responding, once the callback is getting executed.
The thread is still running and able to react to signals and puts the "test" everytime, the thread receives a message.
Can somebody maybe tell me, how to fix this?
Thanks a lot
From the Ruby C API docs:
As of Ruby 1.9, Ruby supports native 1:1 threading with one kernel
thread per Ruby Thread object. Currently, there is a GVL (Global VM
Lock) which prevents simultaneous execution of Ruby code which may be
released by the rb_thread_call_without_gvl and
rb_thread_call_without_gvl2 functions. These functions are
tricky-to-use and documented in thread.c; do not use them before
reading comments in thread.c.
TLDR; the Ruby VM is not currently (at the time of writing) thread safe. Check out this nice write-up on Ruby Threading for a better overall understanding of how to work within these confines.
You can use Ruby's native_thread_create(rb_thread_t *th) which will use pthread_create behind the scenes. There are some drawbacks that you can read about in the documentation above the method definition. You can then run your callback with Ruby's rb_thread_call_with_gvl method. Also, I haven't done it here, but it might be a good idea to create a wrapper method so you can use rb_protect to handle exceptions your callback may raise (otherwise they will be swallowed by the VM).
VALUE execute_callback(VALUE callback)
{
return rb_funcall(callback, rb_intern("call"), 0);
}
// execute your callback when the thread receives signal
rb_thread_call_with_gvl(execute_callback, data->callback);

Store extra data in a c function pointer

Suppose there is a library function (can not modify) that accept a callback (function pointer) as its argument which will be called at some point in the future. My question: is there a way to store extra data along with the function pointer, so that when the callback is called, the extra data can be retrieved. The program is in c.
For example:
// callback's type, no argument
typedef void (*callback_t)();
// the library function
void regist_callback(callback_t cb);
// store data with the function pointer
callback_t store_data(callback_t cb, int data);
// retrieve data within the callback
int retrieve_data();
void my_callback() {
int a;
a = retrieve_data();
// do something with a ...
}
int my_func(...) {
// some variables that i want to pass to my_callback
int a;
// ... regist_callback may be called multiple times
regist_callback(store_data(my_callback, a));
// ...
}
The problem is because callback_t accept no argument. My idea is to generate a small piece of asm code each time to fill into regist_callback, when it is called, it can find the real callback and its data and store it on the stack (or some unused register), then jump to the real callback, and inside the callback, the data can be found.
pseudocode:
typedef struct {
// some asm code knows the following is the real callback
char trampoline_code[X];
callback_t real_callback;
int data;
} func_ptr_t;
callback_t store_data(callback_t cb, int data) {
// ... malloc a func_ptr_t
func_ptr_t * fpt = malloc(...);
// fill the trampoline_code, different machine and
// different calling conversion are different
// ...
fpt->real_callback = cb;
fpt->data = data;
return (callback_t)fpt;
}
int retrieve_data() {
// ... some asm code to retrive data on stack (or some register)
// and return
}
Is it reasonable? Is there any previous work done for such problem?
Unfortunately you're likely to be prohibited from executing your trampoline in more and more systems as time goes on, as executing data is a pretty common way of exploiting security vulnerabilities.
I'd start by reporting the bug to the author of the library. Everybody should know better than to offer a callback interface with no private data parameter.
Having such a limitation would make me think twice about how whether or not the library is reentrant. I would suggest ensuring you can only have one call outstanding at a time, and store the callback parameter in a global variable.
If you believe that the library is fit for use, then you could extend this by writing n different callback trampolines, each referring to their own global data, and wrap that up in some management API.

Resources