Confused with threading in classes

Hello,

I'm quite new to c++, but not to programming. I recently wrote a small program demonstrating the use of multithreading in c++, but as I ported it into a class (the result is shown below), I get an error also shown below (and idk how to fix it).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <thread>
#include <unistd.h>

class Foo {
private:
	bool run = false;
public:
	void* task1(void*);
	void* task2(void*);
	void foo();
};

void* Foo::task1(void* arg) {
	usleep(1000 * 1000);
	run = false;
	std::cout << "Task 1" << std::endl;
	return NULL;
}

void* Foo::task2(void* arg) {
	while(run) {
		usleep(1000 * 100);
		std::cout << "Task 2" << std::endl;
	}
	return NULL;
}

void Foo::foo() {
	pthread_t thread1, thread2;
	run = true;
	pthread_create(&thread1, NULL, task1, NULL);
	pthread_create(&thread2, NULL, task2, NULL);
	pthread_join(thread1, NULL);
}

int main() {
	std::cout << "Hello World!" << std::endl;
	Foo f;
	f.foo();
	return 0;
}


make all 
Building file: ../src/ThreadExample.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -pthread -MMD -MP -MF"src/ThreadExample.d" -MT"src/ThreadExample.d" -o "src/ThreadExample.o" "../src/ThreadExample.cpp"
../src/ThreadExample.cpp: In member function ‘void Foo::foo()’:
../src/ThreadExample.cpp:32:44: error: cannot convert ‘Foo::task1’ from type ‘void* (Foo::)(void*)’ to type ‘void* (*)(void*)’
  pthread_create(&thread1, NULL, task1, NULL);
                                            ^
../src/ThreadExample.cpp:33:44: error: cannot convert ‘Foo::task2’ from type ‘void* (Foo::)(void*)’ to type ‘void* (*)(void*)’
  pthread_create(&thread2, NULL, task2, NULL);
                                            ^
make: *** [src/ThreadExample.o] Fehler 1


The error seems to be about casting Foo:: to (*), but idk why it can't do that. So I'm also asking for an explanation and not just a 'magic fix'.
Thank you in advance,
Turakar
Firstly... even if this "worked" your code would be broken because run is being accessed by multiple threads and accesses are not guarded. You will need to either make it atomic, or put accesses to it behind a mutex or else you will have race conditions.

That said...



pthread_create requires you give it a function with exactly 1 parameter: a void*.

The problem is... member functions require a hidden "this" parameter to indicate which object the function operates on. Therefore Foo::task1 actually requires 2 parameters... this and void*. Therefore you can't pass it to pthread_create because the parameters don't match what is required.

Static members do not require a this parameter, so you could make task1 and task2 static... which will fix the problem. The side-effect being, of course, that the functions will now be static and will not have a this parameter, and therefore will be unable to access non-static members (like 'run').


Typically what is done here... is the void* parameter you give pthread_create is used to pass a pointer to the object to use as 'this'. So you could do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Foo
{
  //...

    void* task1()
    {
        // ...
    }

    static void* task1_launch(void* object)
    {
        Foo* obj = reinterpret_cast<Foo*>(object);
        return obj->task1();
    }

        //...
        //    when creating the thread:
        pthread_create(&thread1, NULL, &Foo::task1_launch, this);  // <- pass 'this' as the object
};






Of course... its probably easier to use C++ standard lib threads rather than pthreads anyway.
Thanks for your answer.
Topic archived. No new replies allowed.