若需要執行一個可能會花些時間的函式 (e.g., 有 blocking read) 但又不希望停住目前的 thread, 解法之一是產生一個新 thread, 然後在該 thread 執行原本欲執行的函式。先來看看 Python 遇到這種情況要怎麼作:
import thread class A(object): def out(self): print 'A.out()' a = A() thread.start_new_thread(A.out, (a,)) # 就這行
相當地直覺。
在 C++ 裡想要執行 non-static member function 的話, 就有點惱人。解決的方法很多, 以下是我土法煉鋼的陽春解法。看 code 即可明白, 關鍵是使用 template 以及 pointer-to-member function。算是一個練習 template 的好題目, 還有了解 C++ 編譯時期多型的威力。
t.h
#include <pthread.h> template<class T> struct MethodWrapper { typedef void(T::*Method)(); MethodWrapper(T *object, Method method) : m_object(object), m_method(method) {} void Run() { (m_object->*m_method)(); } T *m_object; Method m_method; }; // The interface for pthread's usage. template <class T> void* CallMethod(void *v) { MethodWrapper<T> *p = (MethodWrapper<T>*)v; p->Run(); delete p; return NULL; } template <class T> inline pthread_t RunInNewThread(MethodWrapper<T>* param) { pthread_t th; pthread_create(&th, NULL, CallMethod<T>, (void*)param); return th; }
f.h
#include <iostream> #include <sys/syscall.h> struct A { void Out() { std::cout << "tid=" << syscall(__NR_gettid) << " A.Out()" << std::endl; } };
f.cpp
#include "f.h" #include "t.h" /* Compilation: g++ f.cpp -o f -g -Wall -lpthread */ int main(void) { A a; a.Out(); // Direct call. MethodWrapper<A>* m = new MethodWrapper<A>(&a, &A::Out); m->Run(); // Called via the wrapper. CallMethod<A>(m); // Called via a template function. m = new MethodWrapper<A>(&a, &A::Out); pthread_t th = RunInNewThread(m); // Called in a new thread. pthread_join(th, NULL); return 0; }
C++ passing method pointer as template argument 提到用 boost::function0 的解法, 以後再來讀吧。
2012-12-02 更新
- 使用 C++11 的 thread 和 lambda:
std::thread th([&a] { a.Out(); });
- 使用 Boost thread 和 bind
Btw, 這篇文章主要目的是練習 template, 另外在這裡補上若要土法煉鋼地支援參數時該怎麼辦。
沒有留言:
張貼留言