关于杂碎的一些c++多线程编程问题,由winapi到boost::thread
2013-11-29 09:31
609 查看
构思了下,觉得到时写的时候用上多线程什么的,肯定是不能避免的, 而c++实现多线程又是特别考验人的和折磨人的,所以就先开个小程序把有可能出现的问题都搞搞吧
第一个:超级烦的LPVOID的,其实我觉得这种明明方式还真的挺丑的,直译的话是“老婆空”么?哎…怪不得程序员都那么屌丝。好吧,其实是这样的,因为这个东西呢,是个可以指向任意类型的指针,好像是为了平台的可移植性而搞的吧,反正在winapi里面(当然也就包括了要用到的线程的接口和很有可能也要用到的winsock这些),这个东西是出现很多的,而可想而知我自己的里面,经常会有像char*啊string之类这些东西的出现,所以转换就成了一个问题。好吧,原来直接转的话还貌似不行,或者是极端的麻烦,网上很多方法,有些还涉及到了什么LPTSTR,LPCTSTR,LPWSTR,其实我真的觉得在这个方面c++易用性太低了,哎
说说我的需求下,我所采用的并且行之有效的办法吧:首先发现一般情况下char*还是很不错的,很通用,string毕竟不是标准库里面的东西,它只是个经过包装后的类
调用线程的api的时候,要传进字符串之类的东西,用char*吧,如果本来有些东西是string的话,string.c_str()是个非常棒的函数,返回值是char*,赋值给Cstring也可以,对了,cstring我现在是暂时用不到了,但是原来它要包含的头文件是<altstr.h>,额,真别扭,查了msdn才知道
上面这样搞就可以了,无非就是char和lpvoid两个类型的指针的转换,比其他任何方法都简单明了多了。
好吧,这篇已经是半个多月之前写下来的笔记了,那时候貌似还没考试搞boost,现在上面的很丑的内带winapi实现我也已经彻底决定放弃它了,为什么呢?
因为boost有thread库…
boost现在在c++11里面已经有很大一部分原本的库的东西成为了标准了,貌似当然也包括这个线程库,也就意味着以后c++11流行了之后,没有人会再记得winapi这样这么土鳖的方式是怎么写的了,所以我就当然毅然用boost::thread,而且刚好asio的例程里面也有几行简单的代码,再网上随便一搜,还是很快上手的。这里记录下,我的小小的测试代码片段:
这里值得一提的是,貌似用boost的智能指针来包装一些东西这个做法 很值得提倡,具体原因我还不知道,不过应该会对内存的回收和使用效率有比较好的地方,所以这里可以看到就用实例化了智能指针的模板,用一个vector来当做一个线程池,然后每创建一个新的线程就跟它bind一个很简单的print函数,它就会开始执行了,跟java的线程实现方式比较类似,当然没有python那么简单易用,以下就是简单运行一下的图,冒号前面代表的是线程的编号吧,我特意用了2秒和3秒这两个错开的停顿时间,这样线程的效果就很明显了:
对了,现在有点明白那个thread.join()的作用了,比如这里如果将join也去掉注释的话,那它就会等某一个线程完,才会执行下一个语句,如果是单线程的时候,当然感觉不到这个效果,或者是,两个线程已经生成了,然后又将两个线程的join写在一起,那就根本没有效果,怪不得我之前没有注意到这个效果,好吧,挫逼了……
还有个更挫逼的问题需要记录下,菜鸟级的问题:不说了,说多了都是翔,指针和引用的关系:
所以要注意server2的例程代码当中,是这样的,
Io_service_ptr是一个智能指针的vector,然后指针的意思就是这个vector里面存的都是每个ioservice对象的地址,所以那个:
是返回一个指针所指向的值,用引用来表示,所以这里就用一个ioservice对象的引用来标示!!!!初始化的比如boost::asio::io_service& io_service表示一个对象的引用,然后就这样吧,传出引用,然后要收他的函数的函数也是对象引用的参数类型。
然后request_handler是server的一个私有对像,传进去的可以直接传对象,像这个connection的构造函数,第一个参数就是io_service的指针来的,从get_io_service那个函数中从vector中获得的,而第二个就是传进来一个requesthandler对象而已,但是它在函数的声明中是要引用的,所以也是会改变值的。
第一个:超级烦的LPVOID的,其实我觉得这种明明方式还真的挺丑的,直译的话是“老婆空”么?哎…怪不得程序员都那么屌丝。好吧,其实是这样的,因为这个东西呢,是个可以指向任意类型的指针,好像是为了平台的可移植性而搞的吧,反正在winapi里面(当然也就包括了要用到的线程的接口和很有可能也要用到的winsock这些),这个东西是出现很多的,而可想而知我自己的里面,经常会有像char*啊string之类这些东西的出现,所以转换就成了一个问题。好吧,原来直接转的话还貌似不行,或者是极端的麻烦,网上很多方法,有些还涉及到了什么LPTSTR,LPCTSTR,LPWSTR,其实我真的觉得在这个方面c++易用性太低了,哎
说说我的需求下,我所采用的并且行之有效的办法吧:首先发现一般情况下char*还是很不错的,很通用,string毕竟不是标准库里面的东西,它只是个经过包装后的类
调用线程的api的时候,要传进字符串之类的东西,用char*吧,如果本来有些东西是string的话,string.c_str()是个非常棒的函数,返回值是char*,赋值给Cstring也可以,对了,cstring我现在是暂时用不到了,但是原来它要包含的头文件是<altstr.h>,额,真别扭,查了msdn才知道
char* test_cahr = "test_char"; HANDLE hThread = CreateThread(NULL, 0, Fun, (LPVOID*)test_char, 0, NULL); DWORD WINAPI Fun(LPVOID IpParamater) { char* try_char = (char*)IpParamater; }
上面这样搞就可以了,无非就是char和lpvoid两个类型的指针的转换,比其他任何方法都简单明了多了。
好吧,这篇已经是半个多月之前写下来的笔记了,那时候貌似还没考试搞boost,现在上面的很丑的内带winapi实现我也已经彻底决定放弃它了,为什么呢?
因为boost有thread库…
boost现在在c++11里面已经有很大一部分原本的库的东西成为了标准了,貌似当然也包括这个线程库,也就意味着以后c++11流行了之后,没有人会再记得winapi这样这么土鳖的方式是怎么写的了,所以我就当然毅然用boost::thread,而且刚好asio的例程里面也有几行简单的代码,再网上随便一搜,还是很快上手的。这里记录下,我的小小的测试代码片段:
void simple_print(int* id) { for (int i = 0; i < 5; i++) { cout << *id << ":" << i << endl; Sleep(3000); } } int main() { int forcin = 0; int argc = 3; char* argv[5]; vector<boost::shared_ptr<boost::thread>> thread_pool; for (int thread_num = 0; thread_num < 5; thread_num ++) { boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&simple_print, &thread_num))); thread_pool.push_back(thread); // thread->join(); Sleep(2000); }
这里值得一提的是,貌似用boost的智能指针来包装一些东西这个做法 很值得提倡,具体原因我还不知道,不过应该会对内存的回收和使用效率有比较好的地方,所以这里可以看到就用实例化了智能指针的模板,用一个vector来当做一个线程池,然后每创建一个新的线程就跟它bind一个很简单的print函数,它就会开始执行了,跟java的线程实现方式比较类似,当然没有python那么简单易用,以下就是简单运行一下的图,冒号前面代表的是线程的编号吧,我特意用了2秒和3秒这两个错开的停顿时间,这样线程的效果就很明显了:
对了,现在有点明白那个thread.join()的作用了,比如这里如果将join也去掉注释的话,那它就会等某一个线程完,才会执行下一个语句,如果是单线程的时候,当然感觉不到这个效果,或者是,两个线程已经生成了,然后又将两个线程的join写在一起,那就根本没有效果,怪不得我之前没有注意到这个效果,好吧,挫逼了……
还有个更挫逼的问题需要记录下,菜鸟级的问题:不说了,说多了都是翔,指针和引用的关系:
void test_ptr(int* num) { (*num)++; cout << *num << " :in the test_ptr" << endl; } int test_num = 0; test_ptr(&test_num);
所以要注意server2的例程代码当中,是这样的,
typedef boost::shared_ptr<boost::asio::io_service> io_service_ptr; typedef boost::shared_ptr<boost::asio::io_service::work> work_ptr; /// The pool of io_services. std::vector<io_service_ptr> io_services_; /// The work that keeps the io_services running. std::vector<work_ptr> work_; /// The next io_service to use for a connection. std::size_t next_io_service_; };
Io_service_ptr是一个智能指针的vector,然后指针的意思就是这个vector里面存的都是每个ioservice对象的地址,所以那个:
/// Get an io_service to use. boost::asio::io_service& get_io_service();
是返回一个指针所指向的值,用引用来表示,所以这里就用一个ioservice对象的引用来标示!!!!初始化的比如boost::asio::io_service& io_service表示一个对象的引用,然后就这样吧,传出引用,然后要收他的函数的函数也是对象引用的参数类型。
然后request_handler是server的一个私有对像,传进去的可以直接传对象,像这个connection的构造函数,第一个参数就是io_service的指针来的,从get_io_service那个函数中从vector中获得的,而第二个就是传进来一个requesthandler对象而已,但是它在函数的声明中是要引用的,所以也是会改变值的。
explicit connection(boost::asio::io_service& io_service, request_handler& handler);
相关文章推荐
- 关于linux中多线程编程的一些初级问题
- 关于杂碎的一些c++多线程编程问题(二)
- 关于嵌入式C&&C++的一些编程问题(三)
- 关于嵌入式C&&C++的一些编程问题(四)
- 关于嵌入式C&&C++的一些编程问题(一)
- 关于嵌入式C&&C++的一些编程问题(二)
- C++使用thread类多线程编程
- c++中关于内存的一些问题
- C++ Boost Thread 编程指南
- C++ Boost Thread 编程指南
- 关于c#调用c++ dll 的一些问题和解决方案
- 关于c++模板的一些问题
- C/C++关于数据类型的一些问题
- 【面向对象语言系列】关于 C++ 多线程编程,你需要知道的事
- 智力拼图问题–关于回溯和并行:单线到多线程再到GPU编程的进阶(一)
- 关于一些编程问题的记录总结
- C++ Boost Thread 编程指南
- 《Visual C++ 2010入门教程》系列三:关于C++的一些问题(转)
- C++ Boost Thread 编程指南
- C++ Boost Thread 编程指南