Pthread problem.

Hi everyone, my first post here so bear with me.

I am looking for some help with my progrm using pthread.
Basically, here's my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A
{
	public:
		void EntryPoint();
	
	private:
		void DoTask(Task* task);
};

void A::Entrypoint()
{
	Task* t;
	//Assign something to t
	pthread_create(ID, NULL, &A::DoTask, t);
}

void A::DoTask(Task* task)
{
	//Do stuff
}


Obviously, the '&A::DoTask' parameter wont work and I'm really not sure of how to run DoTask from the thread creation. All of the tutorials I've looked at so far are for functions that dont take any parameters.

I didn't put this thread in the unix catagory because I plan on extending this program to windows, and I'm pretty sure that windows's CreateThread takes the same sort of thing as pthread_create.

Thanks in advance for any help.
Does the thread function need to be part of a class? If not, remove from the class and make it a plain old function.

If you want your thread to function in the context of a class there are ways to do that.
It really needs to be inside the class. The class is part of a bigger program.
This is a boost example I had lying around:
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
#include <boost/thread.hpp>
#include <iostream>
#include <string>

boost::mutex cout_mtx;

class counter
{
        size_t _mx;
        std::string _prefix;
public:

        counter(size_t mx, const char* prefix)
                :       _mx(mx), _prefix(prefix)
        {
        }

        void operator()()
        {
                for (size_t i = 0; i != _mx; ++i)
                {
                        boost::mutex::scoped_lock lock(cout_mtx);
                        std::cout << _prefix.c_str() << i << std::endl;
                }
        }
};

int main()
{
        boost::thread thd1(counter(1000, "A"));
        boost::thread thd2(counter(1000, "B"));
        thd1.join();
        thd2.join();

        return 0;
}

The idea is the thread function is operator()(). The example uses a mutex.

Using boost is the recomended portable method. But if you want to understand how it hangs together or to role your own, I can do that too.
Hmm,
Boost does seem like an easier option, but I feel like including a lib like boost instead of just figuring out how to reference my threads starting points is a little silly (i also dont have much experience with using libs).
Will it be much more difficult to do it without boost?
Thanks for your help so far though kbw
As it happens, much of boost is template code which allows you to get away with just using header files.

Many years ago Pete Becker, back in his Borland days, suggested this method in C++ Report I think.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Thread
{
    HANDLE _handle;  // Windows thread handle
    static void ThreadFunc(void*);
    virtual void run() = 0;
    void start();
public:
    virtual ~Thread();
    HANDLE handle() { return _handle; }
};

void Thread::start()
{
    // Windows/MSVC create function
    unsigned idThread = 0;
    _handle = (HANDLE)_beginthreadex(0, 0, ThreadFunc, this, 0, &threadid);
}

void Thread::ThreadFunc(void* p)
{
    if (Thread* pThread = reinterpret_cast<Thread*>(p))
        p->run();
}

This is a thread base class that you derive from. How does it work? start() creates the thread using the local static ThreadFunc(). ThreadFunc() then calls the derived class' run().

1
2
3
4
5
6
7
8
9
10
11
12
13
class Counter : public Thread
{
    size_t _mx;
    std::string _prefix;

    void run()
    {
        for (size_t i = 0; i != _mx; ++i)
            std::cout << _prefix.c_str() << i << std::endl;
    }
public:
    Counter(size_t mx, const char* prefix) : _mx(mx), _prefix(prefix) {}
};


You use it like this.
1
2
3
4
5
6
int main()
{
    Counter c1(10, 'A');
    c1.start();
    WaitForSingleObject(c1.handle(), INFINITE);
}
Last edited on
kbw, That looks great! (from what I can understand)
Can you please give me a quick explanation of what each line in your example usage does? I'm having a little trouble understanding.
main.
Line 3: Instantiate Counter object.
Line 4: Start its thread
Line 5: Wait for it to complete.
I missed the return 0, but I just wrote this in the forum without compiling it.

Counter:
Line 1: Inherit from Thread so we can do thread things.
Line 3, 4: Declare class members.
Line 6: run() is the thread function. We just write some text to cout without synching with anything.
Line 12: Constructor initialised classes members.

Thread:
Line 1: Declare the thread class.
Line 3: _handle is the thread handle used by the OS.
Line 4: ThreadFunc is the static function passed to the thread create function.
Line 5: Declare run() as pure virtual. This is the concurrent function that derived classes override.
Line 6: start() starts the thread running.
Line 8: Virtual destructor because we're a base class.

I forgot the constructor and copy stuff, but like I said, the code was never compiled.

Line 11: start() calls the stuff to create and start a thread using ThreadFunc passing in this as the parameter.

Line 19: ThreadFunc is passed the object that is to be run, so it calls run() on that object. It checks for null.


I hope this helps. I don't know how to be more explicit.
Last edited on
Ok.. Can you please explain what mx is if it's not just an example?
Also, how is threadfunc specified? Does that need to be set between the counter initialisation and c1.start();?
Also, does HANDLE have a pthread equivilent? As this needs to compile on unix too =\
_mx and _prefix are just member variables that the thread uses. It's no big deal, you can put anything in your thread class.

The WIN32 thread handle is HANDLE.

The pthread handle is pthread_t.

If you're even contemplating portability, use boost threads. There's more to threading than a thread class. You also have to sync occasionally. If you're from a Windows background and used to using events, spend a bit of extra time trying to understand conditions before you begin.
So I can just include some headers from boost.. Will this create any dependancies for the end user? I remember using boost in the past and having to have boost libs installed, but if im using headers that wont happen?

I'm relatively new to c++, sorry >_<
If you are using header-only libraries, it won't create any dependencies for the end user. I believe the thread library is a library however. You can statically link it, which would increase the size of your executable but it would prevent the user from needing to acquire the library.
Will statically linking boost create much of a performance hit for the program?
It looks like that might be the best option.
Will statically linking boost create much of a performance hit for the program?
No.

These are the methods exported in boost_thread-vc90-mt-1_43.dll:
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
43
boost::this_thread::disable_interruption::disable_interruption(void)
boost::this_thread::restore_interruption::restore_interruption(class boost::this_thread::disable_interruption &)
boost::thread::thread(class boost::intrusive_ptr<struct boost::detail::thread_data_base>)
boost::thread::thread(struct boost::detail::thread_move_t<class boost::thread>)
boost::thread::thread(void)
boost::this_thread::disable_interruption::~disable_interruption(void)
boost::this_thread::restore_interruption::~restore_interruption(void)
boost::thread::~thread(void)
class boost::thread & boost::thread::operator=(struct boost::detail::thread_move_t<class boost::thread>)
bool boost::thread::operator==(class boost::thread const &)
bool boost::thread::operator!=(class boost::thread const &)
boost::thread::operator struct boost::detail::thread_move_t<class boost::thread>(void)
void boost::detail::add_thread_exit_function(struct boost::detail::thread_exit_function_base *)
void * boost::detail::allocate_raw_heap_memory(unsigned int)
void boost::thread::detach(void)
void boost::detail::free_raw_heap_memory(void *)
class boost::thread::id boost::this_thread::get_id(void)
class boost::thread::id boost::thread::get_id(void)
class boost::intrusive_ptr<struct boost::detail::thread_data_base> boost::thread::get_thread_info(void)
void * boost::detail::get_tss_data(void const *)
unsigned int boost::thread::hardware_concurrency(void)
void boost::thread::interrupt(void)
bool boost::this_thread::interruptible_wait(void *,struct boost::detail::timeout)
bool boost::this_thread::interruption_enabled(void)
void boost::this_thread::interruption_point(void)
bool boost::this_thread::interruption_requested(void)
bool boost::thread::interruption_requested(void)
void boost::thread::join(void)
bool boost::thread::joinable(void)
struct boost::detail::thread_move_t<class boost::thread> boost::thread::move(void)
void * boost::thread::native_handle(void)
void boost::thread::release_handle(void)
void boost::detail::set_tss_data(void const *,class boost::shared_ptr<struct boost::detail::tss_cleanup_function>,void *,bool)
void boost::thread::sleep(class boost::posix_time::ptime const &)
void boost::thread::start_thread(void)
void boost::thread::swap(class boost::thread &)
bool boost::thread::timed_join(class boost::posix_time::ptime const &)
void boost::this_thread::yield(void)
void boost::thread::yield(void)
on_process_enter
on_process_exit
on_thread_enter
on_thread_exit
Last edited on
Ok I have switched to boost threads and all it's working well, except I am having problems with reentrance.

I have a routine that is run from multiple threads at the same time, that basically reads a variable, creates another and stores a value in it.

Do I need a mutex for purely reading values? I have used thread_specific_ptr for creating the vars, but still get weird things happening.
Are you using thread functions or is your stuff in a thread class?
Err..
All of this is contained in the same class and is run in the same instance.
Ok, I overlooked the noobest mistake of them all.
My routine that created all of these threads was exiting before the threads themselves.
All is well now and I thank everyone again for their help.
Topic archived. No new replies allowed.