473,394 Members | 1,761 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Basic Question on POSIX Threads

Hi,

I am trying to get posix threads working from within an object, heres
some code:

int NConnection::TheadControl()
{
int thread_id;
pthread_t new_connection;
pthread_create(&new_connection, NULL, PriC, (void *)thread_id);

return 0;
}
void *NConnection::PriC(void *threadid)
{

}

However it that pthread_create() doesnt match void* (*)(void*)

Any ideas on how i can correct this?

Also assuming that is fixable from within a class, is it possible
once thread is running to send custom signals to it? i.e if i have 4
threads open, is there anyway to send data to the thread function once
its running if that makes any sense? I'm using Linux if its relevant.

Thanks for any advice,

Jack

Oct 14 '07 #1
8 4378
JackC wrote:
Hi,

I am trying to get posix threads working from within an object, heres
some code:

int NConnection::TheadControl()
{
int thread_id;
pthread_t new_connection;
pthread_create(&new_connection, NULL, PriC, (void *)thread_id);

return 0;
}
void *NConnection::PriC(void *threadid)
{

}

However it that pthread_create() doesnt match void* (*)(void*)

Any ideas on how i can correct this?
An FAQ, nothing to do with threads, you can't pass a C++ member function
to a C library function, the linkage is wrong and there is a hidden this
parameter which makes the signature wrong.

You should pass a free function declared as extern "C".
Also assuming that is fixable from within a class, is it possible
once thread is running to send custom signals to it? i.e if i have 4
threads open, is there anyway to send data to the thread function once
its running if that makes any sense? I'm using Linux if its relevant.
Yes, but the details are platform specific and best discussed on a
platform specific group. General threading questions can be asked on
comp.programming.threads.

--
Ian Collins.
Oct 14 '07 #2
On Oct 14, 8:52 pm, JackC <jeche...@gmail.comwrote:
I am trying to get posix threads working from within an object, heres
some code:
int NConnection::TheadControl()
{
int thread_id;
pthread_t new_connection;
pthread_create(&new_connection, NULL, PriC, (void *)thread_id);

return 0;
}
void *NConnection::PriC(void *threadid)
{
}
However it that pthread_create() doesnt match void* (*)(void*)
Any ideas on how i can correct this?
By giving pthread_create the type of function that it requires:
an `extern "C" void* (*)( void* )'. Member functions, even
static member functions, cannot be extern "C", so can't be used.
Also assuming that is fixable from within a class, is it possible
once thread is running to send custom signals to it? i.e if i have 4
threads open, is there anyway to send data to the thread function once
its running if that makes any sense?
It doesn't, really. The classical way of sending data to
another thread is to use some sort of message queue, but of
course, there's nothing standard. (On the other hand, it's
pretty easy to implement using conditions and std::deque.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 14 '07 #3
Here is a skeleton of how I handle pthreads (the same pattern works with
win32 threads) in C++; Ther is of course a lot more to write for the
thread management itself but the importants things are there. I use it
by writting a derived class that overload the run() method.

Hope it helps.

class Thread
{
static void* glue( void* );

private:
pthread_t tid;
pthread_attr_t attr;

public:
Thread();

virtual void* run() = 0;
};

void* Thread::glue( void* t )
{
return ((Thread*)t)->run();
}

Thread::Thread()
{
// ...
pthread_create( &this->tid, &this->attr, Thread::glue, (void*)this );
// ...
}
Oct 14 '07 #4
Laurent D.A.M. MENTEN wrote:
Here is a skeleton of how I handle pthreads (the same pattern works with
win32 threads) in C++; Ther is of course a lot more to write for the
thread management itself but the importants things are there. I use it
by writting a derived class that overload the run() method.

Hope it helps.

class Thread
{
static void* glue( void* );

private:
pthread_t tid;
pthread_attr_t attr;

public:
Thread();

virtual void* run() = 0;
};

void* Thread::glue( void* t )
{
return ((Thread*)t)->run();
}

Thread::Thread()
{
// ...
pthread_create( &this->tid, &this->attr, Thread::glue, (void*)this );
// ...
}
That code has a major race condition issue. Never invoke the thread on
a virtual function until you can guarantee the the object is fully
constructed. Some argue that it's sufficient to "unleash" the thread at
the most derived constructor and wait for it's termination at the most
derived destructor, some argue that you can't unleash the thread until
the constructor has returned and that you can't even call delete until
the thread has been terminated.

The code below shows how to create a thread object (in this case called
Task). This is similar to the Austria C++ code however the Austria C++
code is portable across Win32 and Pthreads. Use Austria or boost
threads. You'll see that it's similar to your code but the virtual
method is not called until after the the "start" method is called.
#include <ctime>
#include <algorithm>
#include <cmath>
#include <pthread.h>

namespace tc
{
// All the posix thread stuff goes here - API conforms to Austria C++

// ======== MutexAttr =================================================
class MutexAttr
{
public:

MutexAttr( int i_kind )
{
pthread_mutexattr_init( m_attr );
if ( pthread_mutexattr_settype( m_attr, i_kind ) != 0 )
{
abort();
}
}

~MutexAttr()
{
pthread_mutexattr_destroy( m_attr );
}

pthread_mutexattr_t * GetAttr()
{
return m_attr;
}

pthread_mutexattr_t m_attr[ 1 ];

};

MutexAttr g_MA_Fast( PTHREAD_MUTEX_FAST_NP );
MutexAttr g_MA_Recursive( PTHREAD_MUTEX_RECURSIVE_NP );
MutexAttr g_MA_Check( PTHREAD_MUTEX_ERRORCHECK_NP );

// ======== Mutex ================================================== ===

class Conditional;
class Mutex
{

public:
friend class Conditional;

// ======== MutexType =============================================

enum MutexType
{
NonRecursive,

Recursive,

Checking
};
// ======== Mutex =================================================

Mutex( MutexType i_type = NonRecursive )
{
pthread_mutex_t * l_mutex = m_mutex_context.m_data;

switch ( i_type )
{
case NonRecursive :
{
int l_result = pthread_mutex_init( l_mutex,
g_MA_Fast.GetAttr() );

if ( l_result != 0 )
{
abort();
}

break;
}
case Recursive :
{
int l_result = pthread_mutex_init( l_mutex,
g_MA_Recursive.GetAttr() );

if ( l_result != 0 )
{
abort();
}

break;
}
case Checking :
{
int l_result = pthread_mutex_init( l_mutex,
g_MA_Check.GetAttr() );

if ( l_result != 0 )
{
abort();
}

break;
}
default :
{
abort();
}
}
}

// ======== Mutex =================================================

virtual ~Mutex()
{
pthread_mutex_t * l_mutex = m_mutex_context.m_data;

int l_result = pthread_mutex_destroy( l_mutex );

if ( l_result != 0 )
{
// trying to destroy a mutex that is locked
abort();
}
}
// ======== Lock ==================================================

void Lock()
{
pthread_mutex_t * l_mutex = m_mutex_context.m_data;

int l_result = pthread_mutex_lock( l_mutex );

if ( l_result != 0 )
{
if ( l_result == EINVAL )
{
abort();
}

if ( l_result == EDEADLK )
{
abort();
}

abort();
}
}
// ======== TryLock ===============================================

bool TryLock()
{
pthread_mutex_t * l_mutex = m_mutex_context.m_data;

int l_result = pthread_mutex_trylock( l_mutex );

if ( EBUSY == l_result )
{
return false;
}

if ( l_result != 0 )
{
if ( l_result == EINVAL )
{
abort();
}

abort();
}

return true;
}
// ======== Unlock ================================================

void Unlock()
{
pthread_mutex_t * l_mutex = m_mutex_context.m_data;

int l_result = pthread_mutex_unlock( l_mutex );

if ( l_result != 0 )
{
if ( l_result == EINVAL )
{
abort();
}

if ( l_result == EPERM )
{
abort();
}

abort();
}
}

struct MutexContext
{
pthread_mutex_t m_data[1];
};

private:

/**
* m_mutex_context is a system dependant context variable.
*/

MutexContext m_mutex_context;

// copy constructor and assignment operator are private and
// unimplemented. It is illegal to copy a mutex.
Mutex( const Mutex & );
Mutex & operator= ( const Mutex & );
};

// ======== Conditional ===============================================
// condition variable wrapper

class Conditional
{
public:

// ======== Conditional ===========================================

Conditional( Mutex & i_mutex )
: m_mutex( i_mutex.m_mutex_context.m_data )
{
int l_result = pthread_cond_init(
m_cond,
static_cast<const pthread_condattr_t *>( 0 )
);

if ( l_result != 0 )
{
abort();
}

}

// destructor
virtual ~Conditional()
{
int l_result = pthread_cond_destroy(
m_cond
);

if ( l_result != 0 )
{
abort();
}
}

// ======== Wait ==================================================
void Wait()
{
int l_result = pthread_cond_wait( m_cond, m_mutex );

if ( l_result != 0 )
{
abort();
}
}

// ======== Post ==================================================
void Post()
{
int l_result = pthread_cond_signal( m_cond );

if ( l_result != 0 )
{
abort();
}
}
// ======== PostAll ===============================================
void PostAll()
{
int l_result = pthread_cond_broadcast( m_cond );

if ( l_result != 0 )
{
abort();
}
}
private:

pthread_mutex_t * m_mutex;
pthread_cond_t m_cond[ 1 ];

// copy constructor and assignment operator are private and
// unimplemented. It is illegal to copy a Conditional.
Conditional( const Conditional & );
Conditional & operator= ( const Conditional & );

};

// ======== ConditionalMutex ==========================================

class ConditionalMutex
: public Mutex,
public Conditional
{
public:
// ======== ConditionalMutex ======================================

ConditionalMutex( MutexType i_type = NonRecursive )
: Mutex( i_type ),
Conditional( * static_cast< Mutex * >( this ) )
{
}
virtual ~ConditionalMutex() {}

private:
ConditionalMutex( const ConditionalMutex & );
ConditionalMutex & operator= ( const ConditionalMutex & );
};
// ======== Lock ================================================

template <typename w_MutexType>
class Lock
{
public:

w_MutexType & m_mutex;

Lock( w_MutexType & io_mutex )
: m_mutex( io_mutex )
{
m_mutex.Lock();
}

~Lock()
{
m_mutex.Unlock();
}

void Wait()
{
return m_mutex.Wait();
}

void Post()
{
m_mutex.Post();
}

void PostAll()
{
m_mutex.PostAll();
}

private:

// must not allow copy or assignment so make
// these methods private.
Lock( const Lock & );
Lock & operator=( const Lock & );
};

// ======== Unlock =============================================

template <typename w_MutexType>
class Unlock
{
public:

w_MutexType & m_mutex;

Unlock( w_MutexType & io_mutex )
: m_mutex( io_mutex )
{
m_mutex.Unlock();
}

~Unlock()
{
m_mutex.Lock();
}

private:

// must not allow copy or assignment so make
// these methods private.
Unlock( const Unlock & );
Unlock & operator=( const Unlock & );
};

// ======== TryLock ================================================== =
template< typename w_MutexType >
class TryLock
{
w_MutexType & m_mutex;

bool m_is_acquired;

public:

TryLock( w_MutexType & io_mutex )
: m_mutex( io_mutex ),
m_is_acquired( false )
{

m_is_acquired = m_mutex.TryLock();
}

inline ~TryLock()
{
if ( m_is_acquired )
{
m_mutex.Unlock();
}
}

void SetAquired( bool i_is_acquired )
{
m_is_acquired = i_is_acquired;
}

bool IsAcquired() const
{
return m_is_acquired;
}

private:

/* Unimplemented. */
TryLock( const TryLock & );
TryLock & operator=( const TryLock & );

};
// ======== Task ================================================== ====

class Task
{
public:

typedef int TaskID;
// ======== Task ==================================================

Task()
: m_started( false ),
m_completed( false ),
m_is_joined( false )
{
int l_result = pthread_create(
& m_thread_id,
static_cast<const pthread_attr_t *>( 0 ),
& start_routine,
static_cast<void *>( this )
);

if ( 0 != l_result )
{
abort();
}
}

// ======== ~Task =================================================

virtual ~Task()
{
Wait();
}
// ======== Work ==================================================

virtual void Work() = 0;

// ======== Start =================================================

void Start()
{
if ( ! m_started )
{
// Wake this thread
Lock<ConditionalMutex l_lock( m_thread_cond_mutex );

m_started = true;
l_lock.Post();
}
}

// ======== Wait ==================================================

void Wait()
{
if ( ! m_is_joined )
{
// Wait here to be started
Lock<ConditionalMutex l_lock( m_wait_cond_mutex );

while ( ! m_completed )
{
l_lock.Wait();
}

// Need to call join here ...

if ( ! m_is_joined )
{
m_is_joined = true;

void * l_return_value;

int l_result = pthread_join(
m_thread_id,
& l_return_value
);

if ( 0 != l_result )
{
abort();
}
}

} // l_lock is unlocked here

}

// ======== GetThisId =============================================

TaskID GetThisId()
{
return m_thread_id;
}
// ======== GetSelfId =============================================

static TaskID GetSelfId()
{
return ::pthread_self();
}

private:

//
// Can't copy a task.
Task( const Task & );
Task & operator= ( const Task & );

pthread_t m_thread_id;

volatile bool m_started;

volatile bool m_completed;

volatile bool m_is_joined;

ConditionalMutex m_thread_cond_mutex;

ConditionalMutex m_wait_cond_mutex;
static void * start_routine( void * i_task )
{
Task * l_this_task = static_cast<Task *>( i_task );

{
// Wait here to be started
Lock<ConditionalMutex l_lock(
l_this_task->m_thread_cond_mutex );

while ( ! l_this_task->m_started )
{
l_lock.Wait();
}
}

// do the work ...
l_this_task->Work();

{
// Wake all the waiters.
Lock<ConditionalMutex l_lock(
l_this_task->m_wait_cond_mutex );

l_this_task->m_completed = true;
l_lock.PostAll();
}

return 0;
}
};
// ======== Barrier ================================================== =

class Barrier
{
public:

Barrier(
unsigned i_thread_count,
ConditionalMutex & i_cond_mutex
)
: m_thread_count( i_thread_count ),
m_cond_mutex( i_cond_mutex ),
m_count()
{
}

unsigned Enter()
{
unsigned l_num;
Lock<ConditionalMutex l_lock( m_cond_mutex );
l_num = m_count ++;

if ( ( m_thread_count - 1 ) == l_num )
{
l_lock.PostAll();
}
else
{
l_lock.Wait();
}
return l_num;
}

unsigned m_thread_count;
ConditionalMutex & m_cond_mutex;
volatile unsigned m_count;
};

} // namespace tc
Oct 14 '07 #5
Laurent D.A.M. MENTEN wrote:
Here is a skeleton of how I handle pthreads (the same pattern works with
win32 threads) in C++; Ther is of course a lot more to write for the
thread management itself but the importants things are there. I use it
by writting a derived class that overload the run() method.

Hope it helps.

class Thread
{
static void* glue( void* );

private:
pthread_t tid;
pthread_attr_t attr;

public:
Thread();

virtual void* run() = 0;
};

void* Thread::glue( void* t )
{
return ((Thread*)t)->run();
}

Thread::Thread()
{
// ...
pthread_create( &this->tid, &this->attr, Thread::glue, (void*)this );
// ...
}
This is wrong, Thread::glue is not an extern "C" function, so it
shouldn't be passed to pthread_create. You might get away with it (I'd
expect at least a complier warning), but it isn't portable.

I don't see why people are so hung up about passing a free function to
pthread_create in C++.

--
Ian Collins.
Oct 15 '07 #6
It's more a case of it being a dangerous solution. There is every
chance the thread will run before the object is constructed on a
multi-core system, or even a single code one if the new thread gets to
run first.
I will repeat myself once more, the code I posted is in NO WAY complete,
so do not assume it to be useable as-is. I just took the essence of the
way I do things so that Mr. JackC can use with ease.
Oct 15 '07 #7
This is a known bug in g++, which will presumably be fixed in a
future release. At which point, your code will stop compiling.
Checked this morning, still not fixed in 4.2.2...
Oct 16 '07 #8
On Oct 16, 8:23 pm, "Laurent D.A.M. MENTEN"
<laurent.men...@teledisnet.bewrote:
This is a known bug in g++, which will presumably be fixed in a
future release. At which point, your code will stop compiling.
Checked this morning, still not fixed in 4.2.2...
So what's your point? Since it doesn't affect correct code, I
doubt it's their highest priority, but I presume it will get
fixed sooner or later, especially as they're not the only ones
with this bug. But knowing the people at g++, it will get fixed
sooner or later---they take conformance seriously. And other
compilers reject the code now.

The fact remains that you posted code which was illegal, and
only compiles because of a compiler bug, and which doesn't work
correctly when it does compile. Both of your errors are
frequent ones, of course, but a competent programmer would learn
from them, instead of trying to defend something which is
blatently wrong.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 16 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Dima | last post by:
This is my simple code #!/usr/local/bin/perl use threads; use threads::shared; use POSIX::RT::Semaphore; $sem = POSIX::RT::Semaphore->init(0, 0); my $pid = fork;
6
by: Evan David Light | last post by:
After agonizing over this problem for a few days, I've decided to seek help. No, not the variety that involes a jacket that zips up the back but this august body of intrepid individuals. I've...
6
by: Chaman Singh | last post by:
Hello, I wanted to use Threads on Sun 4 node SMP. In my program I use STL map and I noticed that I don't get any speedup from using threads and I suspect that it has something to do STL map. Can...
6
by: Christian Buckl | last post by:
Hi, I try to implement my own thread class based on POSIX threads. I want my class to manage everything (creation of threads, exception handling...). This includes also some functions that need to...
2
by: raxitsheth | last post by:
Hello All... I am using Posix Thread. class Parent { public: virtual void* func(void *)=0;
12
by: Winbatch | last post by:
Hi, I'm trying to learn multithreading and it doesn't seem to be working for me. I have a feeling it has to do with the fact that I'm writing to files rather than to printf, but maybe not. ...
11
by: FiLH | last post by:
Hello, I would like to know if posix semaphores are inter processes or just semaphores for threads inside the same process. I have not seen it defined in the posix specification I have found,...
2
by: dariophoenix | last post by:
Hi, I am trying to encapsulate Linux sockets and POSIX threads in C++ classes (I work in Knoppix, using KDevelop). Since sockets and threads are new to me, I searched for example code and found...
23
by: Boltar | last post by:
Hi I'm writing a threading class using posix threads on unix with each thread being run by an object instance. One thing I'm not sure about is , if I do the following: myclass::~myclass() {...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.