使用linux下的线程创建函数pthread_create已久,在传递给它void*型的入口参数时,总是两种方式: 1. 在堆中创建,传入参数指针至线程中,由线程内部释放或等待线程退出后再释放; 2. 不在堆中创建或使用全局变量;
虽然在各种书上提及这种方式的种种不足,但我一直用得还挺好.主要就是注意资源的释放就成,毕竟这种低层的API能给程序员最大的灵活性,所谓有空间才能发挥嘛.但不可否认的是,站得更高是会看得更远.一些设计确实能让代码变得更加简洁,并且不用关注太多低层的细节.其实我一直觉得细节很重要,但要会取舍.
看看以下几个类如何能让代码更优雅: boost::shared_ptr boost::bind boost::thread
作为比较,以下是linux下标准的创建线程的例子:
/* build args: -lpthread */
#include <pthread.h> #include <iostream> #include <string>
using namespace std;
class B { public: B() {cout << "construct B;" << endl;} void out() { cout << "B::out();" << endl; } ~B(){ cout << "destroy B;" << endl;} };
void* fun2(void* p) { B* pb =(B*)p; pb->out(); sleep(3); delete pb; // 在这里释放主线程中创建的对象. }
void fun() { pthread_attr_t ta; pthread_attr_init(&ta); pthread_t tid;
B *pb = new B(); // 创建B的对象作为线程的参数 pthread_create(&tid, &ta, (void*(*)(void*))fun2, (void*)pb); pthread_join(tid, NULL); }
int main() { fun(); cout << "FINISH" << endl; }
| 如果用上shared_ptr,就不再需要在线程中来删除资源了.因为当引用计数为0时,shared_ptr会自动的销毁掉内含的指针.
/* build args(boost 1.34.1 installed /usr/local/): -I/usr/local/include/boost-1_34_1 -L/usr/local/lib -lboost_thread-gcc41-mt */
#include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp>
#include <iostream> #include <string>
using namespace std;
class B { public: B() {cout << "construct B;" << endl;} void out() { cout << "B::out();" << endl; } ~B(){ cout << "destroy B;" << endl;} };
void* fun2(void* p) { /* 转呀转就把原类型转回来了. */ boost::shared_ptr<B> pb = *(boost::shared_ptr<B>*)(p); pb->out();
sleep(10); // 注意在这里就不再需要delete }
void fun() { /* boost中的引用指针计数器(shared_ptr),这个shared_ptr对象内含B的对象指针, 但由于fun2()函数的参数是void*,所以还需要取这个对象的地址传入. fun2()其实可以直接用boost::shared_ptr<B>类型,就无须这样麻烦的转换,不过这样的话,就不能支持任意类型了. */ boost::shared_ptr<B> pb(new B()); /* 这里不再需要关注thread的创建细节; boost::bind设计得太巧妙了; */ boost::thread bthread(boost::bind(fun2, (void*)&pb));
bthread.join(); }
int main() { fun(); cout << "FINISH" << endl; }
| 上面的类型转换有点恶心,不过好在shared_ptr也是允许内部指针的类型继承的,好绕口.
还是看以下代码吧,B类由A类派生而来.所以boost::shared_ptr<A>这个类型,可以传递boost::shared_ptr<B>对象,并且由于shared_ptr重载了"->"符号,所以直接就可以访问B的成员了.
#include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp> #include <iostream> #include <string>
using namespace std;
class A { public: virtual void out() {cout << "A::out();" << endl;} };
class B : public A { public: B() {cout << "construct B;" << endl;} virtual void out() { cout << "B::out();" << endl; }
~B(){ cout << "destroy B;" << endl;} };
/* fun2 可以接收任何A类以及从A派生的类的shared_ptr对象. 这样做,勉强也可算是支持任意类型了,因为只要传递的参数是从A派生即可. */ void* fun2(boost::shared_ptr<A> pa) { // 不再需要任何转换,直接访问其子类的虚方法了.
pa->out(); sleep(10); }
void fun() { /* 代码确实很简洁了. */ boost::shared_ptr<B> pb(new B()); boost::thread bthread(boost::bind(fun2, pb));
bthread.join(); }
int main() { fun(); cout << "FINISH" << endl; }
| | |
发布评论