The following code compiles and runs on standard linux:
#include <iostream>
#include <pthread.h>
using namespace std;
class Foo
{
public:
Foo();
void go_thread();
void stop_thread();
private:
static void* worker( void* param );
pthread_t m_pt;
};
Foo::Foo()
{
m_pt = 0;
}
void Foo::go_thread()
{
int success = pthread_create( &m_pt, NULL, worker, static_cast<void*>(this) );
if( success == 0 )
{
cout << "thread started" << endl;
}
}
void Foo::stop_thread()
{
int success = pthread_join( m_pt, NULL );
if( success == 0 )
{
cout << "thread stopped" << endl;
}
}
void* Foo::worker( void* p )
{
cout << "thread running" << endl;
return 0;
}
int main()
{
Foo f;
f.go_thread();
f.stop_thread();
return 0;
}
and produces the following output:
$ ./a.out
thread started
thread running
thread stopped
$
This code also builds with the Android NDK (r5b). However, when I adb push the resulting executable to a device and run it, I get a SIGSEGV before main() even runs. I've isolated the issue down to pthread_create() It seems the mere existence of this call in my code, never mind execution, causes my prog to seg fault. Any ideas?
It may not be this but try making the function called by pthread create a normal c-function (i.e. declare it as extern "C") not a static member function:
This is because technically the calling convention for static members may be different from the C calling convention that is used by the C-library pthread (though a lot of the times they are the same (which is why it works on your linux box) in my opinion it is not worth the porting risk).
extern "C" void* start_the_thread(void*);
void* start_the_thread(void* data)
{
Foo* theObject = static_cast<Foo*>(data);
// In Java if your Foo had been derived from Runable
// This is s where theObject->run() would have been called.
return Foo::worker(data);
}
int success = pthread_create( &m_pt, NULL, start_the_thread, static_cast<void*>(this)
The issue seems to be combining iostream with pthread. I went through and replaced all couts with printf()s, removed the using clause, and removed the iostream header. The code compiled and ran with no issue on the device. I wonder if this is something Google should be made aware of?
The final (working) code looks like:
#include <pthread.h>
#include <stdio.h>
class Foo
{
public:
Foo();
void go_thread();
void stop_thread();
private:
static void* worker( void* param );
pthread_t m_pt;
};
Foo::Foo()
{
m_pt = 0;
}
void Foo::go_thread()
{
int success = pthread_create( &m_pt, NULL, worker, static_cast<void*>(this) );
if( success == 0 )
{
printf( "thread started\n" );
}
}
void Foo::stop_thread()
{
int success = pthread_join( m_pt, NULL );
if( success == 0 )
{
printf( "thread stopped\n" );
}
}
void* Foo::worker( void* p )
{
printf( "thread running\n" );
return 0;
}
int main()
{
Foo f;
f.go_thread();
f.stop_thread();
return 0;
}
Related
I am doing my first steps in C++ multi threading and ran into a problem.
What I wouyld like to achieve is set out tasks with parameters that will be running in separate threads.
Googling for answers did not bring me the answer.
The system I am using consists of Windows 10 Pro, and Code::Blocks 20.3 with MinGW 17.1
I have created a simple example to get a feeling for it.
The first example (a single cpp file) works just fine.
The second however (in a class) has build errors even though I am using the same code.
I hope someone can explain the reasons why, and hopefully shows me how to solve thsi.
First (working) example:
#include <windows.h>
#include <process.h>
#include <iostream>
#include <chrono>
#include <thread>
struct Param
{
std::string param1;
};
unsigned Counter;
unsigned __stdcall DoSomething( void *ptr )
{
std::cout << "In second thread...\n";
Param *p_tmp = reinterpret_cast<Param*>(ptr);
Param p_param = *p_tmp;
std::string result = p_param.param1;
while ( Counter < 1000 )
{
Counter++;
std::cout << result << Counter << '\r';
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
std::cout << std::endl;
_endthreadex( 0 );
return 0;
}
void CreateThread()
{
HANDLE hThread;
unsigned threadID;
std::string result{"Count: "};
Param param;
param.param1 = "Count: ";
std::cout << "Main thread\nCreating second thread...\n";
// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &DoSomething, (void*)¶m, 0, &threadID );
// Wait until second thread terminates
WaitForSingleObject( hThread, INFINITE );
std::cout << "Returned to Main thread\nCounter should be 1000; it is-> "<< Counter << std::endl;
// Destroy the thread object.
CloseHandle( hThread );
}
int main()
{
CreateThread();
}
The second example (in a class):
struct Param
{
std::string param1;
};
unsigned Counter;
void CthreadFrame::CreateThread()
{
HANDLE hThread;
unsigned threadID;
Param param;
param.param1 = "Count: ";
std::cout << "Main thread\nCreating second thread...\n";
// Create the second thread
hThread = (HANDLE)_beginthreadex( NULL, 0, &DoSomething, (void*)¶m, 0, &threadID );
// Wait for second thread to terminate
WaitForSingleObject( hThread, INFINITE );
std::cout << "Returned to Main thread\nCounter should be 1000; it is-> "<< Counter << std::endl;
// Destroy the thread object.
CloseHandle( hThread );
/* End of void CreateThread */
}
unsigned __stdcall CthreadFrame::DoSomething(void *ptr)
{
std::cout << "In second thread...\n";
Param *p_tmp = reinterpret_cast<Param*>(ptr);
Param p_param = *p_tmp;
std::string result = p_param.param1;
while ( Counter < 1000 )
{
Counter++;
std::cout << result << Counter << '\r';
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
std::cout << std::endl;
_endthreadex( 0 );
return 0;
}
Build Messages:
||=== Build: Debug in Cthread (compiler: GNU GCC Compiler) ===|
F:\Data\__C++\wxApps\Cthread\CthreadMain.cpp||In member function 'void CthreadFrame::CreateThread()':|
F:\Data\__C++\wxApps\Cthread\CthreadMain.cpp|114|error: cannot convert 'unsigned int (CthreadFrame::*)(void*)' to '_beginthreadex_proc_type' {aka 'unsigned int (*)(void*)'}|
f:\sdks\mingw-17.1\x86_64-w64-mingw32\include\process.h|37|note: initializing argument 3 of 'uintptr_t _beginthreadex(void*, unsigned int, _beginthreadex_proc_type, void*, unsigned int, unsigned int*)'|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|
Just declare your thread function as static function:
class CthreadFrame
{
public:
void Start() {
m_hThread = (HANDLE)_beginthreadex(
nullptr, 0, &CthreadFrame::DoSomething,
this /* store params here */, 0, &m_uThreadId
);
}
private:
static unsigned __stdcall DoSomething(void*);
private:
HANDLE m_hThread;
unsigned m_uThreadId;
};
Thank you Georgy Firsov.
I would never have thought searching for std::msm_fn without your help.
I changed my code to:
std::thread th(std::mem_fn(&CthreadFrame::DoSomething), std::ref(*this), (void *)¶m );
th.join();
And that did the trick. Now I can pass all sorts of variables to a thread function.
Below is my code, my problem is that readEvent() function never gets called.
Header file
class MyServer
{
public :
MyServer(MFCPacketWriter *writer_);
~MyServer();
void startReading();
void stopReading();
private :
MFCPacketWriter *writer;
pthread_t serverThread;
bool stopThread;
static void *readEvent(void *);
};
CPP file
MyServer::MyServer(MFCPacketWriter *writer_):writer(writer_)
{
serverThread = NULL;
stopThread = false;
LOGD(">>>>>>>>>>>>> constructed MyServer ");
}
MyServer::~MyServer()
{
writer = NULL;
stopThread = true;
}
void MyServer::startReading()
{
LOGD(">>>>>>>>>>>>> start reading");
if(pthread_create(&serverThread,NULL,&MyServer::readEvent, this) < 0)
{
LOGI(">>>>>>>>>>>>> Error while creating thread");
}
}
void *MyServer::readEvent(void *voidptr)
{
// this log never gets called
LOGD(">>>>>>>>>>>>> readEvent");
while(!MyServer->stopThread){
//loop logic
}
}
Another class
MyServer MyServer(packet_writer);
MyServer.startReading();
Since you are not calling pthread_join, your main thread is terminating without waiting for your worker thread to finish.
Here is a simplified example that reproduces the problem:
#include <iostream>
#include <pthread.h>
class Example {
public:
Example () : thread_() {
int rcode = pthread_create(&thread_, nullptr, Example::task, nullptr);
if (rcode != 0) {
std::cout << "pthread_create failed. Return code: " << rcode << std::endl;
}
}
static void * task (void *) {
std::cout << "Running task." << std::endl;
return nullptr;
}
private:
pthread_t thread_;
};
int main () {
Example example;
}
View Results
No output is produced when running this program, even though pthread_create was successfully called with Example::task as the function parameter.
This can be fixed by calling pthread_join on the thread:
#include <iostream>
#include <pthread.h>
class Example {
public:
Example () : thread_() {
int rcode = pthread_create(&thread_, nullptr, Example::task, nullptr);
if (rcode != 0) {
std::cout << "pthread_create failed. Return code: " << rcode << std::endl;
}
}
/* New code below this point. */
~Example () {
int rcode = pthread_join(thread_, nullptr);
if (rcode != 0) {
std::cout << "pthread_join failed. Return code: " << rcode << std::endl;
}
}
/* New code above this point. */
static void * task (void *) {
std::cout << "Running task." << std::endl;
return nullptr;
}
private:
pthread_t thread_;
};
int main () {
Example example;
}
View Results
Now the program produces the expected output:
Running task.
In your case, you could add a call to pthread_join to the destructor of your MyServer class.
I am new to multithreading.
When I am running the below program it is giving output as
Function1
Function2
1000...1001
but when I am debugging the program it is giving output as expected.
1000...1001
Function1
Function2
So,I think at directly running time (without debugging) mode it is getting some synchronization problem. But one thing confuses me that, I am using mutex then why synchronization problem is happening?
Please help me.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;
pthread_mutex_t myMutex;
void * function1(void * arg);
void * function2(void * arg);
void * function0(void * arg);
int count = 0;
const int COUNT_DONE = 10;
main()
{
pthread_t thread1, thread2, thread0;
pthread_mutex_init(&myMutex, 0);
pthread_create(&thread0, NULL, &function0, NULL );
pthread_create(&thread1, NULL, &function1, NULL );
pthread_create(&thread2, NULL, &function2, NULL );
pthread_join(thread0, NULL );
pthread_join(thread1, NULL );
pthread_join(thread2, NULL );
pthread_mutex_destroy(&myMutex);
return 0;
}
void *function1(void * arg)
{
cout << "Function1\n";
}
void *function0(void *arg)
{
int i, j;
pthread_mutex_lock(&myMutex);
for (i = 0; i <= 1000; i++)
{
for (j = 0; j <= 1000; j++)
{
}
}
cout << i << "..." << j << endl;
pthread_mutex_unlock(&myMutex);
}
void *function2(void * arg)
{
cout << "Function2\n";
}
"... getting some synchronization problem" where do you see a problem?
The threads output could come in any order, as the threads are not synchronised in any case.
The mutex is used only in one thread.
Also
Function1
1000...1001
Function2
might be an expectable and valid result.
As well as:
1000
Function1
...
Function2
1001
Modifying function1() and function2() like so:
void *function1(void * arg)
{
pthread_mutex_lock(&myMutex);
cout << "Function1\n";
pthread_mutex_unlock(&myMutex);
}
void *function2(void * arg)
{
pthread_mutex_lock(&myMutex);
cout << "Function2\n";
pthread_mutex_unlock(&myMutex);
}
would protect the program from producing the 2nd of my example outputs.
Running on:
mehoggan#mehoggan-laptop:~/Code/svn_playground/C++/timer/timer0$ uname -a
Linux mehoggan-laptop 2.6.32-37-generic #81-Ubuntu SMP Fri Dec 2 20:32:42 UTC 2011 x86_64 GNU/Linux
mehoggan#mehoggan-laptop:~/Code/svn_playground/C++/timer/timer0$ cat /etc/*release*
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.04
DISTRIB_CODENAME=lucid
DISTRIB_DESCRIPTION="Ubuntu 10.04.3 LTS"
mehoggan#mehoggan-laptop:~/Code/svn_playground/C++/timer/timer0$ g++ --version
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
mehoggan#mehoggan-laptop:~/Code/svn_playground/C++/timer/timer0$
I am trying to write a timer class that runs on a background thread and uses gettimeofday(3) function plus a user specified callback function. The usage of this will be in a OpenGL app I am in the process of porting from Windows to Linux.
When I run this code (see below). My threads get hung up when running in release mode. However, when I step through the code with a debugger everything seems to work just fine. This indicates a timing issue to me. I might be wrong about this since I am just now learning how to use threads. Could someone help me understand why my threaded application is getting this signal from the OS?
There are two place you can get the code, you can download it from my trac site:
Trac Site
Or you can just copy and paste:
MAIN.CPP
#include "TimerManager.h"
#include <iostream>
#include <fstream>
#include <sys/time.h>
std::ofstream out;
void func1(int id)
{
struct timeval l_tv;
gettimeofday(&l_tv, NULL);
std::cout << "I was called (1) # " << l_tv.tv_usec << std::endl;
out.flush();
}
void func2(int id)
{
struct timeval l_tv;
gettimeofday(&l_tv, NULL);
std::cout << "I was called (2) # " << l_tv.tv_usec << std::endl;
out.flush();
}
int main(int, char *[])
{
out.open("/home/mehoggan/Desktop/log.log");
TimerManager t;
t.addTimer(1000000 * 10, func1);
t.addTimer(1000000 * 20, func2);
t.start();
while(true) {
sleep(1);
}
return 0;
}
#ifndef TIMERMANAGER_H_
#define TIMERMANAGER_H_
#include <stdlib.h>
#include <iostream>
#include <pthread.h>
#include <list>
extern "C" {
void *create_pthread(void *data);
}
class TimerManager {
public:
TimerManager();
~TimerManager();
void start();
void stop();
void addTimer(long usec, void (*callback)(int id));
private:
class Timer
{
public:
Timer(long usec, void (*callback)(int)) :
duration(usec),
callback(callback),
start(0)
{
}
bool operator ==(Timer other)
{
if ((this->callback == other.callback) && (this->duration == other.duration)) {
return true;
}
return false;
}
void operator =(Timer other)
{
duration = other.duration;
callback = other.callback;
start = other.start;
}
suseconds_t duration;
void (*callback)(int);
suseconds_t start;
};
std::list<Timer> m_timers;
Timer setUpTimer(long micro_duration, void (*callback)(int id));
friend void *create_pthread(void *data);
void run();
bool m_bRunning;
bool m_bGo;
long m_lMinSleep;
pthread_t m_tTimerThread;
pthread_cond_t m_tGoLockCondition;
pthread_mutex_t m_tGoLock;
};
#endif
#include <algorithm>
#include <iterator>
#include <sys/time.h>
#include "TimerManager.h"
extern "C" void *create_pthread(void *data)
{
TimerManager *thread_timer_manager = static_cast<TimerManager *>(data);
thread_timer_manager->run();
return data;
}
TimerManager::TimerManager() :
m_bRunning(false),
m_bGo(false),
m_lMinSleep(0)
{
int mutex_creation = pthread_mutex_init(&m_tGoLock, NULL);
if(mutex_creation != 0) {
std::cerr << "Failed to create mutex" << std::endl;
return;
}
int mutex_cond_creation = pthread_cond_init(&m_tGoLockCondition, NULL);
if(mutex_cond_creation != 0) {
std::cerr << "Failed to create condition mutex" << std::endl;
return;
}
int thread_creation = pthread_create(&m_tTimerThread, NULL, create_pthread, this);
if(thread_creation != 0) {
std::cerr << "Failed to create thread" << std::endl;
return;
}
m_bRunning = true;
}
TimerManager::~TimerManager()
{
m_bRunning = false;
pthread_mutex_destroy(&m_tGoLock);
void *result;
pthread_join(m_tTimerThread, &result);
}
void TimerManager::run()
{
pthread_mutex_lock(&m_tGoLock);
while(m_bRunning) {
while (!m_bGo) {
pthread_cond_wait(&m_tGoLockCondition, &m_tGoLock);
}
pthread_mutex_unlock(&m_tGoLock);
if (!m_bRunning) {
break;
}
pthread_detach(m_tTimerThread);
struct timeval l_tv;
sleep(std::max(0l, m_lMinSleep));
gettimeofday(&l_tv, NULL);
m_lMinSleep = 0;
long l_lMin = 0;
for(std::list<Timer>::iterator it = m_timers.begin(); it != m_timers.end(); ++it) {
TimerManager::Timer l_oTimer = *it;
long elapsed_time = ((l_tv.tv_sec * 1000000 + l_tv.tv_usec) - (l_oTimer.start));
l_lMin = elapsed_time - l_oTimer.duration;
if (elapsed_time >= l_oTimer.duration) {
l_lMin = l_oTimer.duration;
l_oTimer.callback(0);
gettimeofday(&l_tv, NULL);
it->start = (l_tv.tv_sec * 1000000) + l_tv.tv_usec;
}
m_lMinSleep = std::min(m_lMinSleep, l_lMin);
}
}
}
void TimerManager::start()
{
pthread_mutex_lock(&m_tGoLock);
m_bGo = true;
pthread_cond_signal(&m_tGoLockCondition);
pthread_mutex_unlock(&m_tGoLock);
}
void TimerManager::stop()
{
pthread_mutex_lock(&m_tGoLock);
m_bGo = false;
pthread_mutex_unlock(&m_tGoLock);
}
TimerManager::Timer TimerManager::setUpTimer(long micro_duration, void (*callback)(int id))
{
struct timeval l_tv;
gettimeofday(&l_tv, NULL);
Timer l_oTimer(micro_duration, callback);
l_oTimer.start = (l_tv.tv_sec * 1000000) + l_tv.tv_usec;
return l_oTimer;
}
void TimerManager::addTimer(long usec, void (*callback)(int id))
{
Timer insert = setUpTimer(usec, callback);
typedef std::list<Timer>::iterator li;
m_timers.push_back(insert);
}
Well, your destructor is definitely broken. You can't destroy a mutex while another thread might be using it. And you can't modify m_bRunning while another thread might be accessing it. You want:
TimerManager::~TimerManager()
{
pthread_mutex_lock(&m_tGoLock);
m_bRunning = false;
pthread_mutex_unlock(&m_tGoLock);
void *result;
pthread_join(m_tTimerThread, &result);
pthread_mutex_destroy(&m_tGoLock);
}
You have a lot of concurrency bugs. For example, your addTimer function modifies the shared m_timers structure without holding a mutex.
Hey everyone, considering the following code (compiled with g++ -lpthread thread_test.cpp) how can I know what number thread I am in from inside "thread_function"? And let me know if you have any other suggestions.
Thanks!
thread_test.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
class A {
public:
A();
void run();
private:
static void* thread_function( void *ptr );
pthread_t m_thread1, m_thread2;
static int m_global;
};
int A::m_global = 0;
A::A() {
int ret1 = pthread_create( &m_thread1, NULL, &A::thread_function, this );
int ret2 = pthread_create( &m_thread2, NULL, &A::thread_function, this );
}
void A::run() {
while ( 1 ) {
printf( "parent incrementing...\n" );
m_global++;
sleep( 2 );
}
}
void* A::thread_function( void *ptr ) {
printf( "I'm thread ?\n" );
while ( 1 ) {
printf("thread global: %d\n", m_global );
sleep( 1 );
}
}
int main() {
A a;
a.run();
return 0;
}
You can use pthread_self() function.
Well i figured out I could do this, but I'm not sure if making the pthread_t variables static is the best thing to do. Opinions?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
class A {
public:
A();
void run();
private:
static void* thread_function( void *ptr );
static pthread_t m_thread1, m_thread2;
static int m_global;
};
int A::m_global = 0;
pthread_t A::m_thread1 = 0;
pthread_t A::m_thread2 = 0;
A::A() {
int ret1 = pthread_create( &m_thread1, NULL, &A::thread_function, this );
int ret2 = pthread_create( &m_thread2, NULL, &A::thread_function, this );
}
void A::run() {
while ( 1 ) {
printf( "parent incrementing...\n" );
m_global++;
sleep( 2 );
}
}
void* A::thread_function( void *ptr ) {
int thread_num = 0;
if ( pthread_self() == m_thread1 ) {
thread_num = 1;
} else {
thread_num = 2;
}
printf( "I'm thread %d\n", thread_num );
while ( 1 ) {
printf("thread %d global: %d\n", thread_num, m_global );
sleep( 1 );
}
}
int main() {
A a;
a.run();
return 0;
}
The correct answer depends heavily on why you need this information. If the two threads are doing different things, why do they have the same start function?
One simple fix is this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
class A {
public:
A();
void run();
private:
static void* thread_function( void *ptr, int which );
static void* thread_function_1( void *ptr );
static void* thread_function_2( void *ptr );
pthread_t m_thread1, m_thread2;
static int m_global;
};
int A::m_global = 0;
A::A() {
int ret1 = pthread_create( &m_thread1, NULL, &A::thread_function_1, this );
int ret2 = pthread_create( &m_thread2, NULL, &A::thread_function_2, this );
}
void A::run() {
while ( 1 ) {
printf( "parent incrementing...\n" );
m_global++;
sleep( 2 );
}
}
void* A::thread_function_1( void *ptr ) { thread_function(ptr, 1); }
void* A::thread_function_2( void *ptr ) { thread_function(ptr, 2); }
void* A::thread_function( void *ptr, int which ) {
printf( "I'm thread %d\n", which );
while ( 1 ) {
printf("thread global: %d\n", m_global );
sleep( 1 );
}
}
int main() {
A a;
a.run();
return 0;
}
If you have more than 2 threads, you can use another approach. Create a structure that holds all the information the thread needs, including the this pointer and which thread it is. Allocate a structure of that type, stuff it with everything the thread needs and pass that to the thread through the pthread_create function instead of just the this pointer.