5

i'm trying to create a new thread with a class "CameraManager" but i have the following error:

cannot convert '*void(CameraManager:: * )(void*) to void*( * )(void*) in pthread_create function

i defined in the cameramanager.h file:

public:
void *dequeueLoop(void *ptr);

and in the cameramanager.cpp

void CameraManager::startDequeuing(){
dequeuing = true;
dequeueThreadId = pthread_create(&dequeueThread, NULL, &CameraManager::dequeueLoop, NULL);
}

void *CameraManager::dequeueLoop(void *ptr){
while(dequeuing){
    highSpeedCamera->dequeue();
    highSpeedCamera->enqueue();
}

I don't want to declare dequeueLoop as a static function i also tried to declare dequeueLoop as a class friend function in the following way but then it doesn't have scope on class variables 'highSpeedCamera' and 'dequeuing' and the compiler also tell me that 'dequeueLoop' was not declared in this scope

to make dequeueLoop a friend function i did:

cameramanager.h

public:
friend void *dequeueLoop(void *ptr);

cameramanager.cpp

void CameraManager::startDequeuing(){
    dequeuing = true;
    dequeueThreadId = pthread_create(&dequeueThread, NULL, &CameraManager::dequeueLoop, NULL);
}
void *dequeueLoop(void *ptr){
    while(dequeuing){
        highSpeedCamera->dequeue();
        highSpeedCamera->enqueue();
    }
}

Where i'm doing wrong?

  • 1
    Why don't you want to make it a static member function. You can always pass `this` in as an argument so that you get access to your private member data. – pstrjds Aug 17 '12 at 12:50

3 Answers3

7

I don't want to declare dequeueLoop as a static function

If you want to use pthreads, then you'll need a static or non-member function for the entry point. You can pass a pointer to your object to this function, using it as a trampoline into the non-static member function:

static void * dequeueEntry(void * self) {
    return static_cast<CameraManager*>(self)->dequeueLoop();
}

dequeueThreadId = pthread_create(
    &dequeueThread, NULL, 
    &CameraManager::dequeueEntry, // <-- pointer to trampoline function
    this);                        // <-- pointer to object for member function

Alternatively, if you have a modern compiler, you could use the standard thread library instead:

std::thread thread(&CameraManager::dequeLoop, this);
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • 3
    If you don't have modern compiler, you can consider boost::thread - it will be the same nice syntax – nogard Aug 17 '12 at 13:06
  • thanks, i tried the first implementation you suggested me but when i compile i have the following error: 'In function 'void* dequeEntry(void*)' 'void value not ignored as it ought to be' – Gabriele Gambotto Aug 17 '12 at 13:12
  • @GabrieleGambotto: That sounds like your `dequeueLoop` isn't declared to return anything, unlike the one in your question which is declared to return `void*`, but forgets to return anything. Either get `dequeueLoop` to return the thread's return value, or put a separate `return` statement in `dequeueEntry`. – Mike Seymour Aug 17 '12 at 13:29
3

If you want the function to be a member of the class, it must be static. It's because the thread function will be called directly and will not have a valid this pointer. This can be solved by having a wrapper function, that gets passed the actual object and then calls the proper member function:

void *dequeueLoopWrapper(void *p)
{
    CameraManager *cameraManager = static_cast<CameraManager*>(p);
    camereraManager->dequeueLoop();
    return nullptr;
}

// ...

void CameraManager::startDequeuing()
{
    dequeuing = true;
    dequeueThreadId = pthread_create(&dequeueThread, NULL, dequeueLoopWrapper, this);
}

However, I would recommend you start using the threading support in the new standard library:

void CameraManager::startDequeuing()
{
    dequeuing = true;
    myThread = std::thread(&CameraManager::dequeueLoop, this);
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

You can't use a pointer to member function as a function pointer unless it's static. You'll have to make dequeueLoop a free function, or write a free function as a wrapper to it.

To access the class members in a free function, you should have the function pass it's this pointer as the final argument of pthread_create. Then have the free function cast it's argument to a pointer to the class.

Dirk Holsopple
  • 8,731
  • 1
  • 24
  • 37