So I'm making an addon for node.js as in: http://nodejs.org/api/addons.html#addons_wrapping_c_objects.
However: my class has a pthread that loops forever and performs callbacks via uv_async_send() as suggested in http://nikhilm.github.io/uvbook/threads.html.
This callback function needs to access non-static class variables, I do that by setting: async.data = (void*) this; and in the callback function: MyClass* obj = (MyClass*)(handle->data);, so that i can access the data via: obj->myvar.
What happens though, is that the callback function is called after the object has been destructed already. I'm wondering how to prevent this from happening, preferably without the need for extra javascript code.
In case you wonder why the callback needs to access member variables: it's a buffer that is filled by the seperate thread, which passed as argument to the javascript callback.
Thanks in advance.
Related
My problem is, that I have a callback which gets called after my mainthread deleted the object that contained the memberfunction the callback wants to call. Therefore, my program crashes. Is there any way, to pretend the crash? I am not able to change the flow of my mainthread.
My main thread starts a new thread for a specific task and waits in an dialog. If the user presses cancel before the task (bluetooth scan) is done, the mainthread continues and deletes the object that is needed for the callback, to call.
typedef std::tr1::function<void __cdecl ()>* callback_function;
callback_function m_bluetoothScan = //Some function in native C++
// The c++/cli callback
void Connection::BluetoothScanCallback(IAsyncResult^ ar)
{
if (m_bluetoothScan != nullptr)
{
(*m_bluetoothScan)(); // The native c++ member function
}
}
UPDATE:
Like #xMRi pointed out, I had to unregister my callback inside my destructor. What I did was, setting my callback_function to nullptr and inside my BluetoothScanCallback function on the CLI side, I check if m_bluetoothScan is nullptr and thus don't try to call my callback. Thanks a lot!
When the object is deleted it should be obvious that you have to take care about all references that uses the object. So from my point of view you have also remove any reference to it.
This means: Deleting the object requires unregistering the callback.
A good way would be using smart pointers to the object, so was long as there is a object reference, the object will not be deleted.
You can also use strong and weak pointer. So storing a weak pointer for the callback function and a strong pointer for the object. So the C++/CLI part ist capable to distinguish that there is no longer need to call the callback function.
I wanted to show a problem I’m having while invoking functions of an instantiated class in C++.
I’m using a separate thread to listen to a TCP socket, so when data comes, I want to call a function to start doing tasks. I’m using process.h library and _beginthread(socket_init,0,NULL); to start the thread with socket_init() function, which starts the listener.
To put you into situation, right before the thread initialization call, I have this:
CPhoneDlg dlg = new CPhoneDlg;
m_pMainWnd = &dlg;
This class has this function declared:
CTapiLine* CPhoneDlg::GetActiveLine() {...}
So the point of all this, is to be able to call GetActiveLine() from the function that is being executed in the separate thread.
For that I tried to do this:
CTapiLine* line = dlg.GetActiveLine();
But it just doesn’t know what dlg is, showing "identifier not declared" when I try to compile the code.
Is there any way to make dlg object visible so its methods become "invokable" by the separate thread?
I had to figure out almost this exact issue just the other day, so I think I can help. You need to pass an object to your class into the thread function. See the following code:
DWORD WINAPI PhoneThread(LPVOID lpParam)
{
CPhoneDlg *phoneDlg = reinterpret_cast<CPhoneDlg *>(lpParam);
CTapiLine* line = phoneDlg.GetActiveLine();
}
And instantiate the thread like this (from within your class!):
CreateThread(NULL, 0, PhoneThread, this, 0, NULL);
As long as GetActiveLine() is public, you should be able to make it work like this.
What I am doing is passing in a pointer to the main class as an LPVOID. When you get into the thread, you can use reinterpret_cast to cast it back to the type of the main class. Now, you have a pointer to the class from within your thread and you can access public functions and variables.
I’m trying to store an object passed from JavaScript to a Node.js Addon in a void *. I can’t seem to get this to compile; building with node-gyp produces error: no matching function for call to 'Cast'.
The long version of what I’m trying to do is write a Node.js Addon that runs Csound. Csound works, from a bird’s-eye view, with C functions that take a pointer to an opaque Csound struct as (usually) the first argument. This struct contains a void * to “hostData”, arbitrary data set by a program hosting Csound. Some things that Csound does, like posting messages, are modified with callbacks—function pointers in this case. I need a place to store callbacks for each instance of Csound, so I’m trying to let someone set hostData to an object from JavaScript, but I also want to set the callbacks for a Csound instance as hidden properties on this hostData object.
I think the code will need to look something like
#include "csound.h"
#include <node.h>
static void CsoundMessageCallback(CSOUND *Csound, int attributes,
const char *format, va_list valist)
{
// Call the JavaScript function we stored in the hostData of Csound.
}
static void _wrap_csoundSetMessageCallback(
const v8::FunctionCallbackInfo<v8::Value>& args)
{
v8::HandleScope scope(v8::Isolate::GetCurrent());
CSOUND *Csound;
// Pretend we get the Csound instance from args[0] here. This is actually done
// by SWIG <http://www.swig.org>.
// This does not compile. csoundGetHostData() returns a void *, but I’m assuming
// hostData was set to an object from JavaScript.
v8::Persistent<v8::Object> hostData =
v8::Persistent<v8::Object>::Cast(csoundGetHostData(Csound));
hostData.SetHiddenValue(
v8::String::New("CsoundMessageCallback"),
v8::Persistent<v8::Function>::Cast(args[1])
);
csoundSetMessageCallback(Csound, CsoundMessageCallback);
}
I’m guessing I need to take a close look at V8’s internal fields, but I’m really not sure.
Typically what I've done in situations like this is I write a wrapper C++ class (inheriting from node's ObjectWrap class) that stores a pointer to the instance of whatever C/C++ class I'm wrapping and has various public methods to interact with that instance.
When new is called from JS land, a new instance of the wrapper C++ class gets created and associated with the new JS object. Then you have JS functions that kick off whatever async tasks that utilize the wrapped library's callbacks.
From there it's just a matter of calling uv_async_send() from the wrapped library's callbacks to signal the main thread and then calling the JS callback from the uv_async callback.
You can see an example of all of this here (especially in the Windows-specific parts):
The Pcap class holds a pcap_t pointer (would be a CSOUND pointer for you).
When a new Pcap is created from JS land, I wrap a new C++ class instance.
Initialize a uv_async_t which sets up the callback to fire on uv_async_send() and also associates the user data pointer to the class instance for easy access. You could do this initialization during the call to new if you wanted, instead of a separate prototype function (open()) like I have done since initialization just happens once.
Then from the wrapped library's callback, I signal the main thread.
From the uv_async callback, I can then access the wrapper class instance and use V8 functions safely. Although in my particular case, I have another callback which uses V8 functions. However you can use them safely inside your uv_async callback.
As far as storing JS callbacks goes, there are different ways to handle that. One solution might be to create a baton object that stores a Persistent copy of the JS callback and the wrapper class instance and store that baton in uv_async_t's user data pointer. This would mean creating a new uv_async_t for every request (which is different than the example I gave above).
My code calls a function from 3rd party library. Let's call this function SomeFunc
void SomeFunc(void (*callBack) (int));
As you can see SomeFunc takes a callback function parameter. Once SomeFunc is called, the calling thread will progress, and the library will execute the callback several time on a different thread -- passing it different status code.
My requirement is the thread that calls SomeFunc (aka main thread) should wait until certain status code is passed to the callback. So far I have something like this
CEvent *pEvt = NULL;
void myCallBack(int code) {
if(code == SOME_MAGIC_NUM) pEvt->SetEvent(); // signal thread waiting for this event obj they can continue
}
int main (int argc, char** argv) {
pEvt = new CEvent(FALSE, TRUE);
SomeFunc(myCallBack); // This doesn't block, main thread will progress to next line
WaitForSingleObject(pEvt, 5000); // wait here until 3rd party library call myCallBack with code SOME_MAGIC_NUM -- or if it doesn't after 5 seconds, continue
// do interesting stuff here..
return EXIT_SUCCESS;
}
Now this seem fine if I only do this on the main thread / main function like above. However if multiple thread can execute the code block in main above, my problem is they will share reference to the global pEvt variable, and it will mess up
What's the best code design approach I should take here? Ideally I would like to change the callback function signature to accept reference to the CEvent object, but since it's a 3rd party library I'm unable to do that.
You really want the equivalent of a closure in javascript. You can accomplish something similar by binding the function call to a new CEvent object every time. Take a look at std::bind1st or boost::bind.
See also this stackoverflow thread
You can only achieve this is the 3rd party provides a way to pass back a 'custom' argument to the callback. Well designed APIs allow to set up a callback and a void* value and the callback receives this argument when invoked. From this void* you can expand to anything you like, including objects and method calls, via unsafe casting. All solutions based on binding or member function address or whatever else ultimately boil down to the same issue: somehow the this* has to be passed back to the callback.
For an example, see BIO_set_callback: it allows you to set the callback and a callback arbitrary argument. Note that the callabck argument can be indirect, like for example in gnutls: the argument can be set as arbitrary data on the session via gnutls_session_set_ptr and then in the callback(s) it can be retrieved using gnutls_session_get_ptr. Your 3rd party may provide such an indirect method.
If the library does not offer such feature then you're stranded into hacks. For example you can have a collection of callbacks 'available', each one associated with a specific event (ie. different functions as address, although same code). You pick one callback and remove it from collection and place it, then wait for the event associated with that callback. When done, place the callback back into the available list. The size of the 'available' list is hard coided at compile time as you really need separate functions, one for each callback.
I've been playing around with Windows' (new?) thread pool API. I've been following through with the example in the Using the Thread Pool Functions and I've been taking a good hard look at the API on MSDN. There's something I don't get about cleanup groups.
When invoking the SetThreadpoolCallbackCleanupGroup(), the third parameter is described as
The cleanup callback to be called if the cleanup group is canceled before the associated object is released. The function is called when you call CloseThreadpoolCleanupGroupMembers().
If my understanding is correct, the means that you can cancel pending work/io/timer items and ask it to invoke the cleanup callback function on each of these objects instead of the originally queue work/io/timer item's callback. This sounds cool, and I'd like to use it.
Unfortunately, the PTP_CLEANUP_GROUP_CANCEL_CALLBACK type used for the callback in question is not documented on MSDN and the example in question does not use this feature.
Taking the law into my own hands, I've traced back the definition to WinNT.h and found the following.
typedef VOID (NTAPI *PTP_CLEANUP_GROUP_CANCEL_CALLBACK)(
__inout_opt PVOID ObjectContext,
__inout_opt PVOID CleanupContext
);
Removing the cruft on this funny looking declaration gets you:
typedef void ( __stdcall * PTP_CLEANUP_GROUP_CANCEL_CALLBACK )
( void* ObjectContext, void* CleanupContext );
Question: If you would have to take an educated guess, what do you think ObjectContext and CleanupContext refer to?
My 1st guess is that CleanupContext is what you specify at the moment you initiate cleanup: thus the 3rd parameter to CloseThreadpoolCleanupGroupMembers(). I'm pretty confident this guess is correct because the API calls are so directly related.
My 2nd guess is that ObjectContext is what you specify at the moment you submit the work/io/timer item: this the 2nd parameter to CreateThreadpoolWork() et al. I'm totally unsure that this is the case.
Can someone confim that these guesses are correct? Has anyone used this feature before?
The optional cleanup callback you specify using the SetThreadpoolCallbackCleanupGroup function is called for each object that is associated with the same callback environment that has not already been closed by the time CloseThreadpoolCleanupGroupMembers is called. The callback’s first parameter, the object context, is the value of the void* parameter you specify when using the TrySubmitThreadpoolCallback, CreateThreadpoolWork, etc. functions. The callback’s second parameter, the cleanup context, is the value of the void* parameter you specify when using the CloseThreadpoolCleanupGroupMembers function.
The important thing to remember is that whether the cleanup callback is called for a particular object is not dependent on whether or not that object has outstanding callbacks. It is only called for objects that have not yet been closed. In other words it’s entirely possible that the object’s callback is called and then the cleanup callback is called for that same object.
If for example you create a work object using the CreateThreadpoolWork function and fail to call the CloseThreadpoolWork function prior to calling CloseThreadpoolCleanupGroupMembers then the cleanup callback will be called for that object even if the object’s callback has already executed. Failing to call CloseThreadpoolWork is not a bug as CloseThreadpoolCleanupGroupMembers will close any objects associated with the cleanup group.
Another twist to watch out for is when using the TrySubmitThreadpoolCallback function. This is a simpler version of CreateThreadpoolWork in that you don’t have to think about creating, submitting, and closing the work object. The trick is that the thread pool with automatically close the work object once its callback has executed. This means that the cleanup callback will only be called for this object if its callback is still pending and you specify TRUE when calling CloseThreadpoolCleanupGroupMembers to cancel any pending callbacks.