Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Newbie: thread function in class

0 views
Skip to first unread message

J.R. de Pijper

unread,
May 6, 2003, 7:20:20 AM5/6/03
to
Hi,

I am a newbie when it comes to multithreading, so I hope you will be
able to help me.

I have a class that represents a sound file to be played back through
the sound card. Because I want to be able to play back various sounds
at the same time and change volume settings during playback I have to
do the playback in a separate thread. So I created a Posix thread
function "void Playback(void*)".

My question is, can this playback thread function be a member function
of the sound class? If so, should I make it static? How can I get
access to the current instance's member variables and functions? This
seems to me a problem both if the thread function is global and if it
is a static member function.

Thanks in advance for any help you can gice!
Jan Roelof de Pijper

Tim Veldhuizen

unread,
May 6, 2003, 7:51:28 AM5/6/03
to
Hi..

Yes, you can make the thread function a method of the class. For this, you
probably should make it a static one. I'm still a bit newbie for what this
concirns, but from the example that i have from John Goerzen's book "Linux
Programming - Het Complete Handboek", i've seen that its posible. And its
also the way i create my threads.

For an example, i'm using this (about the same code from the book):
//----------------------------------------------------------
/*
* basethread.H
*
* The mother class of all threads...
*/

#ifndef __BASETHREAD_H__
#define __BASETHREAD_H__

#include <pthread.h>
#include <unistd.h>

class Thread
{
public:
Thread();
int Start(void * arg);
protected:
void Run(void * arg);
static void * EntryPoint(void*); // This is the function one
gives to the pthread_create function.
virtual void Setup();
virtual void Execute(void*)=0; // Abstract: Inherit this
class and use this function for the thread code..
void * getArg() {return Arg_;}
void setArg(void* a) {Arg_ = a;}
private:
pthread_t ThreadId_;
void * Arg_;
};

#endif /* __BASETHREAD_H__ */

//----------------------------------------------------------
And the cpp file that goes with it is this:
//----------------------------------------------------------

/*
* basethread.cpp
*
* the mother class for all thread classes...
*/

#include "basethread.H"
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>

Thread::Thread() {}

int Thread::Start(void * arg)
{
setArg(arg); // store user data
int code = pthread_create(&ThreadId_, NULL, Thread::EntryPoint,
this);
return code;
}

void Thread::Run(void * arg)
{
Setup();
Execute( arg );
}

/*static*/
void * Thread::EntryPoint(void * pthis)
{
Thread * pt = (Thread*)pthis;
pt->Run( pt->getArg() );
return pt;
}

void Thread::Setup()
{
// Do any setup here
}

//----------------------------------------------------------

At the moment i'm not sure how to combine this with mutexes, but if you need
to know, i suppose someone else could give that answer...

Greetz and good luck,
Tim Veldhuizen.

"J.R. de Pijper" <j.r.d....@tue.nl> wrote in message
news:it5fbvglve7rctgm9...@4ax.com...

Alexander Terekhov

unread,
May 6, 2003, 8:49:11 AM5/6/03
to

Tim Veldhuizen wrote:
>
> Hi..
>
> Yes, you can make the thread function a method of the class.

You can't {portably} pass it to pthread_create(). pthread_create()
needs a "C" routine, not C++ one.

[...]
> private:
> pthread_t ThreadId_;
[...]


> int Thread::Start(void * arg)
> {
> setArg(arg); // store user data

> int code = pthread_create(&ThreadId_, ....

Oh, yet another TC2 ``beneficiary.''

http://opengroup.org/austin/mailarchives/austin-group-l/msg05209.html

regards,
alexander.

Tim Veldhuizen

unread,
May 6, 2003, 10:36:47 AM5/6/03
to

"Alexander Terekhov" <tere...@web.de> wrote in message
news:3EB7AF47...@web.de...

>
> Tim Veldhuizen wrote:
> >
> > Hi..
> >
> > Yes, you can make the thread function a method of the class.
>
> You can't {portably} pass it to pthread_create(). pthread_create()
> needs a "C" routine, not C++ one.
Hmm, so i guess the way i'm doing it at the moment, is not the right way..
But i understand that it used to work. And it did.. Well, for me it did (not
sure if my compiler gave some warnings about it or not though).
Why did they change it? Or why is it not allowed? Or could it be a matter
for using this on multiprocessor systems?

And is there some sample code which does it the right way? I found this, but
don't know if its right.. Looks to me like to should work though:

//-----------------------------------------------------------------------
begin code
extern "C" void* threadLauncher( void* ) ;

class Thread {
pthread_t t ;
public:
void start() { pthread_create( &t, NULL, &threadLauncher, this ); }
virtual run(){}
};

extern "C" void* threadLauncher( void* t ) {
((Thread*)t)->run();
return NULL ;
}

//-----------------------------------------------------------------------
code end

Or should i use a sort of c++ "version" of pthread_create? (don't know if
such exist though)

I just tried to compile this, but i get the same error:
[lynx@CyberCity threads]$ g++ -Wall -o thread-test thread-test.cpp
basethread.cpp
/home/lynx/tmp/ccCCsmf4.o: In function `Thread::Start(void *)':
/home/lynx/tmp/ccCCsmf4.o(.text+0x33): undefined reference to
`pthread_create'
collect2: ld returned 1 exit status

However, the manpage tells me i'd have to #include <pthread.h> and thats
exactly what i'm doing.. So i'm a bit lost here.. Should i have added an
option to g++ or have i forgot to #include something else? I remember to
have messed around with the includes in some of that files lately..

Alexander Terekhov

unread,
May 6, 2003, 11:32:19 AM5/6/03
to

Tim Veldhuizen wrote:
>
> "Alexander Terekhov" <tere...@web.de> wrote in message
> news:3EB7AF47...@web.de...
> >
> > Tim Veldhuizen wrote:
> > >
> > > Hi..
> > >
> > > Yes, you can make the thread function a method of the class.
> >
> > You can't {portably} pass it to pthread_create(). pthread_create()
> > needs a "C" routine, not C++ one.
> Hmm, so i guess the way i'm doing it at the moment, is not the right way..
> But i understand that it used to work. And it did.. Well, for me it did (not
> sure if my compiler gave some warnings about it or not though).
> Why did they change it? Or why is it not allowed?

Linkage. It isn't allowed because there's simply no <cthread>
standard C++ header that would replace the function signature
(from <pthread.h>; 'restrict' aside for a moment)

int pthread_create(pthread_t *,
const pthread_attr_t *,
void *(*)(void *),
void *);

by TWO declarations:

extern "C" int pthread_create(pthread_t *,
const pthread_attr_t *,
void *(*)(void *),
void *);

extern "C++" int pthread_create(pthread_t *,
const pthread_attr_t *,
void *(*)(void *),
void *);

just like the <cstdlib> header does it for bsearch() and qsort(),
for example.

[...]


> Or should i use a sort of c++ "version" of pthread_create?

For the REAL C++ "version" of pthread_create(), you'll need the
<thread> header with something ala new_thread() with built-in
'binder'. Unfortunately, it also doesn't exist yet.

regards,
alexander.

P.S. Usually, you must specify the "-pthread" compiler switch.

Tim Veldhuizen

unread,
May 6, 2003, 11:51:33 AM5/6/03
to
"Alexander Terekhov" <tere...@web.de> wrote in message
news:3EB7D583...@web.de...
>
> Tim Veldhuizen wrote:
> >
[...]

> > Why did they change it? Or why is it not allowed?
>
> Linkage. It isn't allowed because there's simply no <cthread>
> standard C++ header that would replace the function signature
> (from <pthread.h>; 'restrict' aside for a moment)
>
> int pthread_create(pthread_t *,
> const pthread_attr_t *,
> void *(*)(void *),
> void *);
>
> by TWO declarations:
>
> extern "C" int pthread_create(pthread_t *,
> const pthread_attr_t *,
> void *(*)(void *),
> void *);
>
> extern "C++" int pthread_create(pthread_t *,
> const pthread_attr_t *,
> void *(*)(void *),
> void *);
>
> just like the <cstdlib> header does it for bsearch() and qsort(),
> for example.
>
> [...]
> > Or should i use a sort of c++ "version" of pthread_create?
>
> For the REAL C++ "version" of pthread_create(), you'll need the
> <thread> header with something ala new_thread() with built-in
> 'binder'. Unfortunately, it also doesn't exist yet.
Ah, so that has to be written yet, i guess.. And in the meanwhile, i guess
it's allowed to use the method i found in an example @ google..

>
> regards,
> alexander.
>
> P.S. Usually, you must specify the "-pthread" compiler switch.

Yes, i've found it.. (Was hiding in a dark corner of my brain, till i
switched it on ;-)
It works now.. tnx for all the info.. (Still reading the pdf (
http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V51_PDF/ARH9RBTE.PDF )
.. Man, is that a long one.. ;D )

Greetz,
Tim Veldhuizen.


David Schwartz

unread,
May 6, 2003, 6:33:51 PM5/6/03
to

"Tim Veldhuizen" <ly...@chatmagix.mine.nu> wrote in message
news:9SQta.1318730$sj7.54661686@Flipper...

> Ah, so that has to be written yet, i guess.. And in the meanwhile, i guess
> it's allowed to use the method i found in an example @ google..

It depends what you mean by allowed. It works on every platform I know
of, but it is not guaranteed to work by any standard. It's not difficult to
make a standalone function with C linkage that's a friend of the class. This
C++ function with C linkage can call a class member. Kind of like this:

extern "C"
{ // this function needs C linkage
void *MyFunc(void *);
}

class MyClass
{
friend void *MyFunc(void *);
protected:
thread_t tid;
void *ThreadFunc(void);
void LaunchThread(void);
};

void *MyFunc(void *a)
{
MyClass *c=(MyClass *) a;
return c->ThreadFunc();
}

void LaunchThread(void)
{
pthread_create(&tid, NULL, MyFunc, (void *) this);
}


Alexander Terekhov

unread,
May 7, 2003, 6:04:37 AM5/7/03
to

David Schwartz wrote:
[...]

> class MyClass
> {
> friend void *MyFunc(void *);
> protected:
> thread_t tid;
^^^^^^^^

pthread_t, I guess. <?>

> void *ThreadFunc(void);
> void LaunchThread(void);
> };
>
> void *MyFunc(void *a)
> {
> MyClass *c=(MyClass *) a;
> return c->ThreadFunc();
> }
>
> void LaunchThread(void)
> {
> pthread_create(&tid, NULL, MyFunc, (void *) this);
> }

David, you surely do know that under the current standard, your
tid member CANNOT be accessed in the context of your ThreadFunc
(without additional synchronization with respect to 'launching'
thread), correct? (rhetorical question, never mind ;-) )

regards,
alexander.

0 new messages