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.
Related
I am currently creating my own GUI-Library based on SFML.
At the moment i am working on a Button. So when creating a button you also have to specify a callback which is a function, executed on the button click.
Now, I'm answering me what the disadvantages are of using just a pointer to a function as a button-callback, because I don't know any popular GUI-Library doing it so simply, too.
If the callback function is a long process, I would execute it in a new thread, but i'm not sure about that in the moment.
So, what would be reasons, not to use such simple solution and especially, what would be a better way?
It's a tricky problem!
Function pointers are simple to implement on the sender side, but they are difficult to use on the receiver side because they they don't have any context.
One issue is that a function pointer cannot point to a member function. That's why you often see (C-style) frameworks pass an arbitrary void *userData to their callbacks, so you can cast your this pointer and retrieve it in that way. This still needs you to write a static wrapper function to cast the pointer back and call the member function.
A more modern solution would be to use std::function. This can contain a regular function pointer, a member function pointer, but also a lambda or a functor.
However, when you add context like this (or in some other way), you quickly run into difficulties with lifetimes. When the receiving class is destroyed before the sender, what is supposed to happen? If you don't do anything, this situation will result in undefined behaviour. A solution is to track on the receiver side to which events the receiver is subscribed, and unbind them before the receiver is destroyed. And this needs to be done in both directions: when the sender is destroyed, it also needs to notify the receiver that it should forget about the sender, otherwise the receiver would later try to unbind an event that no longer exists.
And I haven't even begun to think about multithreading yet...
There are libraries that solve these problems in various ways, for example eventpp (just found through a web search, this is not an endorsement).
Another one to mention would be the Qt toolkit, which went so far as to write their own small signals and slots extension to the C++ language (implemented as a code generator and a pile of macros) to solve this problem in a very ergonomical way.
what the disadvantages are of using just a pointer to a function as a button-callback
Passing some context argument to that function would come handy.
I mean, the UI may have a lot of buttons performing the same action on various objects. Think maybe of "send message" button next to each nick in a friend list.
So you may want your buttom to pass some context arguments to the call.
But since we're talking C++, this'd better be abstracted as
struct IButtonAction
{
virtual void OnAttached() = 0;
virtual void OnDetached() = 0;
virtual void OnClick() = 0;
};
And let the client code implement this interface storing whichever Arg1, Arg2, etc in each instance object.
The button class would call OnAttached/OnDetached when it begins/ends using the pointer to an instance of this callback interface. These calls must be paired. Client implementation of these methods may perform lifetime management and synchronization with OnClick, if required.
OnClick method performs the action.
I don't think the button should bother with threads. It's the responsibility of the client code to decide whether to spawn a thread for a lengthy action.
We have a code that registers a callback. So the flow that registers the callback has no knowledge of when the callback will be called.
Now the callback will called by another flow in a thread - hence the main flow that has registered the callback needs to wait for callback to complete.
I am having no idea to implement the same as I cannot modify anything in the other thread that will call the callback. How can I make my main thread to responds synchronously - after the callback is called by other thread?
You will need to share some state between the two that can be used to communicate this.
As a corollary, if the callback is stateless, this cannot be done (or only within certain restrictions, such as limiting the number of callbacks that can be active at the same time).
Since the access to that shared state potentially happens concurrently from different threads, all access needs to be synchronized, ie. made thread-safe.
Here is a simple example using std::future:
#include <future>
// [...]
std::promise<void> p;
do_work_async([&p]() { p.set_value(); });
std::future<void> f = p.get_future();
f.get(); // this line will block until the callback is executed
Note that this has potential lifetime issues: The promise needs to be kept alive until the callback has executed. Depending on your program, this might make it necessary to put the promise on the heap.
If stateless callbacks are not supported (eg. the callback parameter must be a plain C-function pointer and no injection point for user state is provided) you need to put your shared state into static storage instead, with the usual resulting limitations.
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 want to make a simple worker thread inside a same class. However, there are 3 major problems that I am facing, which are:
Definition of a thread function in class header.
Thread function call.
Called thread function format.
I am also confused to use either AfxBeginThread or CreateThread function call to pass multiple thread parameters. Can anyone please provide me a simple worker thread to run in MFC based on the 3 things that I have provided above?
Definition of a thread function in class header: It has to be a static member because the usual way of putting "this" in a hidden parameter doesn't work. Since you only get one parameter, you want the parameter to be a pointer to a struct, and one member of the struct can be "this" of the class instance that your static member can call.
Thread function call: Since the function that gets called is going to use MFC, it is easiest to have the caller call AfxBeginThread. Since you say the thread will be a worker thread, call the version of AfxBeginThread that is designed for worker threads (even if it doesn't matter much).
Called thread function format. MSDN describes AfxBeginThread and says what prototype must be used for the first parameter.
Ideally, you should never be using CreateThred. And if you're using MFC, you MUST use AfxBeginThread to for creating threads.
I've given some explanation here in this discussion: http://www.daniweb.com/forums/thread249210.html
CreateThread is mainly for UI Threads but is still preferred to use the second method for AfxBeginThread. Store a reference to the threads handle in the header not the thread.
HANDLE hThread;
then in source start your thread pointing to your proc:
CWinThread *pThread;
if(!(pThread = AfxBeginThread(ThreadProc, NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED))) {
delete arr;
}
::DuplicateHandle(GetCurrentProcess(), pThread->m_hThread, GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
pThread->ResumeThread();
You start it suspended so you can copy the handle to the one you have stored in header. this way you can use the stored handle to check on exitcode.
Newbie question: I have a forms application. It has a separate thread which makes a web services call, and then posts the results of the call to the main form.
In my thread, after X seconds have passed (using a TTimer), I call:
procedure TPollingThread.OnTimer(Sender: TObject);
var
SystemProbeValues : TCWProbeValues;
begin
SystemProbeValues := Remote.Run.GetSystemProbeValues;
PostMessage( ParentHandle, WM_APIEVENT ,Integer(apiMultiCellStatus), Integer(SystemProbeValues) );
end;
The function Remote.Run.GetSystemProbeValues has the following prototype:
function GetSystemProbeValues : TCWProbeValues; stdcall;
And TCWProbeValues is a dynamic array of TCWProbeValue objects (which all descend from TRemotable).
In my main form, I receive the message just fine and cast the LParam back to TCWProbeValues:
procedure TFrmCWMain.OnAPIEvent(var msg: TMessage);
begin
ProbeValues := TCWProbeValues(msg.LParam);
end;
My question is, given that the dynamic array and its objects were created by the Delphi HTTORIO system, who is responsible for freeing them? Did Delphi consider that memory re-usable after my OnTimer function returned? (And in which case, its pure good luck that my main form message handler can actually read the memory referenced by the LParam of the message?) Or rather, is it my responsibility to free the object auto-instantiated by the HTTPRIO request?
Many thanks, please shout if the above needs more detail / code and I'll add to it!
Cheers, Duncan
TRemotable provides lifetime management via its DataContext property, so the SOAP runtime will free the object itself. As long as the data-context object exists, everything it allocated will exist, too. If you want to claim ownership of and responsibility for an object, simply clear its DataContext property. (That's probably what you'll want to do in this case because your API-event message may get handled after the SOAP event has terminated.)
A problem in your code is that you're passing a dynamic array via a posted message. When your OnTimer procedure returns to its caller, the dynamic array referenced by SystemProbeValues will have its reference count decremented. If the other thread hasn't processed the message yet (and it probably hasn't), then the dynamic array might already be destroyed by the time it does get around to processing that message.
The easy way around that is to clear the reference in the timer's event handler without reducing the reference count, and then do the opposite in the message handler. After you post the message, clear the variable:
LParam(SystemProbeValues) := 0;
In your message handler, clear the old value of the global ProbeValues variable and assign the new value like this:
ProbeValues := nil;
LParam(ProbeValues) := Msg.LParam;
Another problem lurking in your code may be the use of TTimer in a non-VCL thread. That class creates a window handle to share among all instances of the class. Unless your timer thread is the only thread in the program that uses TTimer, you will probably have problems, either with functions running in the wrong thread, or functions not running at all. Instead of TTimer, you can use SetTimer to create an OS timer manually, or you could create a waitable timer, which may be more suitable for use in a thread that doesn't need to remain responsive to user actions.