您的位置:首页 > 编程语言 > C语言/C++

关于杂碎的一些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* 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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: