Home // Blog
Home // Notice
Home // Tag Log
Home // Location Log
Home // Media Log
Home // GuestBook
Inter-thread communication in C++ #1
Posted at 2008. 10. 23. 02:08 //
in S/W개발/C++ 이야기 //
by
아래 코드는 독립된 쓰레드로 동작하는 Class의 member function을 그 쓰레드 context에서 실행시키는 예제 코드. 이걸 좀더 일반적으로 작성할 순 없을까요? 예를 들어, member function 인자가 몇 개가 있더라도 호출할 수 있도록 한다던지... ITCThread에서 상속받는 클래스에서 공개 인터페이스를 쉽게 작성할 수 있도록 해준다던지...(지금은 memfun()를 public으로 하고 doMemfunc()라는 걸 private으로 선언한 다음에 memfun()를 구현해 줘야 한다.)
좋은 아이디어 있으신 독자분께서는 댓글 부탁드려용~
참고로 말씀드리면 thread, mutex, unique_lock, condition_variable, bind, mem_fn 등은 모두 boost에 있는 것들을 사용한 것입니다.
#include <iostream>
#include <string>
#include <functional>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/signal.hpp>
using namespace std;
using namespace boost;
using namespace boost::posix_time;
template <class ThreadType>
class ITCThread : public thread
{
public:
typedef void (ThreadType::*MemFunType)();
ITCThread(const string& name = "thr"):
thread(bind(mem_fn(&ITCThread::run), this)),
m_name(name),
m_mutex(), m_cond(),
m_req(false), m_fn(&ITCThread::noop), m_run(true) {}
const string& getName()
{
return m_name;
}
void quit()
{
doIt(&ITCThread::doQuit);
}
protected:
void doIt(MemFunType mf)
{
unique_lock<mutex> lock(m_mutex);
cout << m_name << ": calling..." << endl;
m_fn = mem_fun(mf);
m_req = true;
m_cond.notify_one();
}
private:
void run()
{
cout << m_name << ": starting..." << endl;
while (m_run)
{
unique_lock<mutex> lock(m_mutex);
while (!m_req)
{
cout << m_name << ": waiting a call..." << endl;
m_cond.wait(lock);
}
cout << m_name << ": I've got a call" << endl;
m_fn((ThreadType*)(this));
m_req = false;
}
cout << m_name << ": bye bye" << endl;
}
void doQuit()
{
cout << m_name << ": exiting..." << endl;
m_run = 0;
}
void noop()
{
cout << m_name << ": noop() called" << endl;
}
string m_name;
mutex m_mutex;
condition_variable m_cond;
bool m_req;
mem_fun_t<void,ThreadType> m_fn;
bool m_run;
};
class HelloThread : public ITCThread<HelloThread>
{
public:
HelloThread(const string& name = "hello") :
ITCThread<HelloThread>(name)
{}
void hello()
{
doIt(&HelloThread::doHello);
}
private:
void doHello()
{
cout << getName() << ": Hello~ body!" << endl;
}
};
int
main()
{
HelloThread itc1("H1"), itc2("H2");
for (int i = 0; i < 10; ++i)
{
this_thread::sleep(millisec(1000));
itc1.hello();
itc2.hello();
}
this_thread::sleep(millisec(1000));
itc1.quit();
itc2.quit();
itc1.join();
itc2.join();
return 0;
}
좋은 아이디어 있으신 독자분께서는 댓글 부탁드려용~
참고로 말씀드리면 thread, mutex, unique_lock, condition_variable, bind, mem_fn 등은 모두 boost에 있는 것들을 사용한 것입니다.
#include <iostream>
#include <string>
#include <functional>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/signal.hpp>
using namespace std;
using namespace boost;
using namespace boost::posix_time;
template <class ThreadType>
class ITCThread : public thread
{
public:
typedef void (ThreadType::*MemFunType)();
ITCThread(const string& name = "thr"):
thread(bind(mem_fn(&ITCThread::run), this)),
m_name(name),
m_mutex(), m_cond(),
m_req(false), m_fn(&ITCThread::noop), m_run(true) {}
const string& getName()
{
return m_name;
}
void quit()
{
doIt(&ITCThread::doQuit);
}
protected:
void doIt(MemFunType mf)
{
unique_lock<mutex> lock(m_mutex);
cout << m_name << ": calling..." << endl;
m_fn = mem_fun(mf);
m_req = true;
m_cond.notify_one();
}
private:
void run()
{
cout << m_name << ": starting..." << endl;
while (m_run)
{
unique_lock<mutex> lock(m_mutex);
while (!m_req)
{
cout << m_name << ": waiting a call..." << endl;
m_cond.wait(lock);
}
cout << m_name << ": I've got a call" << endl;
m_fn((ThreadType*)(this));
m_req = false;
}
cout << m_name << ": bye bye" << endl;
}
void doQuit()
{
cout << m_name << ": exiting..." << endl;
m_run = 0;
}
void noop()
{
cout << m_name << ": noop() called" << endl;
}
string m_name;
mutex m_mutex;
condition_variable m_cond;
bool m_req;
mem_fun_t<void,ThreadType> m_fn;
bool m_run;
};
class HelloThread : public ITCThread<HelloThread>
{
public:
HelloThread(const string& name = "hello") :
ITCThread<HelloThread>(name)
{}
void hello()
{
doIt(&HelloThread::doHello);
}
private:
void doHello()
{
cout << getName() << ": Hello~ body!" << endl;
}
};
int
main()
{
HelloThread itc1("H1"), itc2("H2");
for (int i = 0; i < 10; ++i)
{
this_thread::sleep(millisec(1000));
itc1.hello();
itc2.hello();
}
this_thread::sleep(millisec(1000));
itc1.quit();
itc2.quit();
itc1.join();
itc2.join();
return 0;
}