5

I have a Functor which I need to send to a function which receives a function pointer as a parameter (such as CreateThread).

Can I convert it to a static method address somehow? And if not, how can I do it?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Idov
  • 5,006
  • 17
  • 69
  • 106

1 Answers1

8

No, you can't convert a class-type object to a function pointer.

However, you can write a non-member wrapper function that calls the member function on the right instance. Many APIs, including CreateThread, allow you to provide a pointer that it will give back to you when it calls your callback (for CreateThread, this is the lpParameter parameter). For example:

DWORD WINAPI FunctorWrapper(LPVOID p)
{
    // Call operator() on the functor pointed to by p:
    return (*static_cast<FunctorType*>(p))();
}

// Used as:
FunctorType f;
CreateThread(0, 0, &FunctorWrapper, &f, 0, 0);
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Yes, this is what I do now, but If I have 2 instances of the class which uses "CreateThread", I'll have to use mutexes so it won't cause a mess and it will slow me down. I'm not talking only about createthread but in general. – Idov Aug 21 '11 at 18:09
  • Why do you need a mutex? You tell `CreateThread` what pointer to give back to you... – James McNellis Aug 21 '11 at 18:11
  • But if I call it from 2 different threads at the same time, the pointer from the second thread might "overrun" the one from the first thread... :/ – Idov Aug 21 '11 at 18:14
  • Not to mention that you could use a sane C++ API for threading, and you could replace `CreateThread` with something that accepts a functor in the first place. :) – jalf Aug 21 '11 at 18:15
  • 1
    @jalf: Well, right: if possible, one should just use Boost.Thread or just::thread. It took me three tries to get the right signature for my ThreadProc :-O – James McNellis Aug 21 '11 at 18:18
  • 1
    @Idov: no, each call to the function gets its own set of parameters. They're not shared with other invocations of the function. – jalf Aug 21 '11 at 18:18
  • 2
    @ldov: I don't understand: do you want each thread to have its own instance of the functor? If so, create a different instance for each thread. Do you want all the threads to share access to the same functor? If so, create one and synchronize access to it using a mutex or some other synchronization method... – James McNellis Aug 21 '11 at 18:19
  • @James McNellis: Ok, each thread has its own instance (so no syncronization needed). thanks :) – Idov Aug 22 '11 at 17:28
  • I don't quite understand what is `FunctorType` - a function-pointer? Or a class? If it is function-pointer then why are you passing it via address? And if it class, how can you pass the address of local? – Ajay Aug 24 '11 at 19:10
  • @AJay: It is a class type with an `operator()` overload. There is nothing wrong with taking the address of a local variable. The caller of `CreateThread()` is responsible for ensuring that `f` exists for at least as long as the thread may use it. – James McNellis Aug 24 '11 at 20:03
  • That means launching a different thread and waiting for it till it completes (results in synchrounous operation). – Ajay Aug 25 '11 at 02:50
  • @Ajay: How is that in any way synchronous? The caller of `CreateThread()` is free to continue execution after making the call. That said, there's no reason it has to be a local variable; it could just as well be dynamically allocated or static. – James McNellis Aug 25 '11 at 02:53
  • @James: "it could just as well be dynamically allocated or static" - Exactly! But shouldn't be a local, otherwise WFSO, WFMO, SleepEx or other API would be called to ensure that stack allocated variable (if more than sizeof(viod*)) remain. You may create many threads, and then finally call WFMO on all of them to reduce synchronous-ness, but essentially that has to be syncronous! – Ajay Aug 25 '11 at 05:15