0

在我的 C++ 应用程序中,我有 2 个线程:(i)主线程,(ii)后台线程。我有一个类定义为:

class helper
{
 public:
     bool login(const string& username, const string& password);
     void logout();

 private:
     bool loginInternal(const string& username, const string& password);
     void logoutInternal();
}

在主线程上调用 helper::login() 和 helper::logout() 函数(以及具有各种返回类型和 # of params 和 param 类型的其他几个成员函数)。在这些函数的实现中,对应的内部函数要入队,后台线程按照入队的顺序调用这些内部函数。所以是这样的:

bool helper::login(const string& username, const string& password)
{
    queue.push_back(boost::bind(&helper::loginInternal, this, username, password));
}

void helper::logout()
{
    queue.push_back(boost::bind(&helper::logoutInternal, this));
}

后台线程一直在运行,等待队列填满,一旦填满,这个后台线程就会开始调用队列中的函数:

queue.front()();
queue.pop_front();

那么问题来了,我该如何定义这样的队列呢?

deque<???> queue;

该队列的数据类型可能是什么,以便它可以在同一个队列中保存具有不同签名的回调函数?

编辑:这是解决方案(感谢 J. Calleja):

typedef boost::function<void ()> Command;
deque<Command> queue;

然后像这样调用仿函数:

// Execute the command at the front
Command cmd = queue.front();
cmd();

// remove the executed command from the queue
queue.pop_front();
4

2 回答 2

1

如果您规范化返回类型或忽略它,您可以使用boost::function 。该库定义了一个包装器,可以存储任何与您的签名(函数或仿函数)匹配的元素。

使用您的示例:

#include <boost/function.hpp>

class helper 
{  
public:      
  bool login(const std::string& username, const std::string& password);
  void logout();
private:      
  bool loginInternal(const std::string& username, const std::string& password);
  void logoutInternal();
private:
  typedef boost::function<void ()> Command;
  std::deque<Command> queue;
};

此示例忽略返回类型,因为它声明了返回 void 的函数。如果你想知道返回值,你必须让 logout 返回一个 bool 并将声明更改为:

  typedef boost::function<bool ()> Command;
于 2012-08-23T22:01:28.153 回答
0

我相信第一个的类型是bind<bool>,第二个的类型是bind<void>。由于这是两种不同的类型,您不能将它们放在一个队列中。使logoutreturn 成为一种bool(即使它总是返回true或其他东西)将是解决此问题的一种(可能相对无痛)的方法。

tl;dr:更改logout为返回 a bool,然后将您的队列声明为deque< bind<bool> >

编辑:考虑到多种类型,我建议您为自己创建某种特殊的容器类。像这样的东西:

class EnqueuedFunc
{
    virtual void operator()() = 0;
};

class LoginFunc : public EnqueuedFunc
{
    bind<bool> func;

    LoginFunc(bind<bool> fn)
    {
        func = fn;
    }
    void operator()()
    {
        fn();
    }
};

class LogoutFunc : public EnqueuedFunc
{
    bind<void> func;

    LoginFunc(bind<void> fn)
    {
        func = fn;
    }
    void operator()()
    {
        fn();
    }
};

然后你的队列是deque<EnqueuedFunc>.

于 2012-08-23T21:16:41.447 回答