首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

12.5 给线程函数传递一个参数

问题

在Boost线程库中的创建函数只接受不带参数的算符,如何实现给你的线程函数传递一个参数?

解决方案

创建一个带着你的参数的算符适配器并返回一个不带参数的算符。当你需要给线程函数传递一个不带参数的算符时就可以使用这个算符适配器。请看一下示例12-6是如何这样做的:

示例12-6  给一个线程函数传递一个参数

#include <iostream>

#include <string>

#include <functional>

#include <boost/thread/thread.hpp>

// A typedef to make the declarations below easier to read

typedef void (*WorkerFunPtr)(const std::string&);

template<typename FunT,   // The type of the function being called

         typename ParamT> // The type of its parameter

struct Adapter {

   Adapter(FunT f, ParamT& p) : // Construct this adapter and set the

      f_(f), p_(&p) {}          // members to the function and its arg

   void operator()() { // This just calls the function with its arg

      f_(*p_);   

   }

private:

   FunT    f_;

   ParamT* p_;  // Use the parameter's address to avoid extra copying

};

void worker(const std::string& s) {

   std::cout << s << '\n';

}

int main() {

   std::string s1 = "This is the first thread!";

   std::string s2 = "This is the second thread!";

   boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1));

   boost::thread thr2(Adapter<WorkerFunPtr, std::string>(worker, s2));

   thr1.join();

   thr2.join();

}

讨论

你需要解决的基本问题并不特定于线程或者Boost线程库,当你不得不传递一个某种签名的算符给某个需要一个与它不同签名的算符作为参数的算法时,这是一个通常的问题。这个问题的解决方案就是创建一个适配器。

这个语法可能有点乱,但示例12-6中必须做的就是创建一个临时的算符,这个临时的算符就像人们期望的那样可被一个线程构造函数作为一个不带参数的函数而调用。第一件事情就是:使用一个typedef来重新定义一下这个函数指针使得它更容易阅读:

typedef void (*WorkerFunPtr)(const std::string&);

这就创建了一个WorkerFunPtr类型,它是一个函数指针,它带一个字符串引用作为参数并且返回一个void类型。然后,我创建这个适配器类模板。它提供了实例化一个动态算符的方法。请看下面这个构造函数:

template<typename FunT,

         typename ParamT>

struct Adapter {

   Adapter(FunT f, ParamT& p) :

      f_(f), p_(&p) {}

// ...

这个构造函数所做的就是实例化两个成员,它们可以是任何类型,但我们期望它们是一个函数指针和任何类型的参数p。为了提高效率我把这个参数的地址存储下来,而不是采用值复制的方式来复制它。

请看来自主线程中的下面的这行代码:

boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1));

这个thr1的构造函数的参数就是这个适配器类模板的一个实例,使用两个类型WorkerFunPtr和std::string作为它的参数。这个实例为适配器的f_和p_成员使用这两个类型。最后,适配器重写了操作符(),因此它能够像函数一样被调用。当它被调用时,其形式如下所示:

f_(*p_);

使用这个适配器类模板,你就可以给线程函数传递参数,尽管需要使用一些额外的语法。如果你需要传递多个参数,仅需要在这个适配器中增加另一个类型和成员变量。这种方法的一个比较好的方面就是你可以创建一序列的泛型适配器类模板,并且你可以在各种其他的上下文中使用它们。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论