2

在直接问你我的问题之前,我将描述我的问题的性质。我正在使用 C++/OpenGL 和 GLFW 库编写 2D 模拟。而且我需要正确管理很多线程。在 GLFW 中我们必须调用函数:thread = glfwCreateThread(ThreadFunc, NULL); (第一个参数是执行线程的函数,第二个代表这个函数的参数)。而且glfwCreateThread,每次都必须调用!(即:在每个周期中)。这种工作方式并没有真正帮助我,因为它破坏了我构建代码的方式,因为我需要在主循环范围之外创建线程。所以我正在创建一个 ThreadManager 类,它将具有以下原型:

class ThreadManager {

  public:
         ThreadManager();
         void AddThread(void*, void GLFWCALL (*pt2Func)(void*)); 
         void DeleteThread(void GLFWCALL (*pt2Func)(void*));
         void ExecuteAllThreads();

  private:
         vector<void GLFWCALL (*pt2Func)(void*)> list_functions;
         // some attributs             


};

例如,如果我想添加一个特定线程,我只需要使用特定参数和特定函数调用 AddThread。目标只是能够调用: ExecuteAllThreads(); 在主循环范围内。但为此我需要有类似的东西:

void ExecuteAllThreads() {

      vector<void GLFWCALL (*pt2Func)(void*)>::const_iterator iter_end = list_functions.end();
      for(vector<void GLFWCALL (*pt2Func)(void*)>::const_iterator iter = list_functions.begin();
      iter != iter_end; ++iter) {

           thread = glfwCreateThread(&(iter*), param);
      }
}

在 AddThread 中,我只需要将 pt2Func 引用的函数添加到向量:list_functions。

好吧,这是我想做的事情的总体思路..这是正确的方法吗?你有更好的主意吗?如何做到这一点,真的吗?(我的意思是问题在于语法,我不知道该怎么做)。

谢谢 !

4

4 回答 4

3

您需要在每个模拟周期中创建线程吗?这听起来很可疑。创建一次线程,然后重复使用它们。

线程创建不是一项廉价的操作。您绝对不想在每个迭代步骤中都这样做。

如果可能的话,我建议您使用 Boost.Thread 来代替线程,以便为您提供类型安全和其他方便的功能。线程足够复杂,不会抛弃类型安全性并针对原始 C API 工作。

也就是说,您要问的是可能的,尽管它会变得混乱。首先,您还需要存储函数的参数,因此您的类看起来像这样:

class ThreadManager {

  public:
         typedef void GLFWCALL (*pt2Func)(void*); // Just a convenience typedef
         typedef std::vector<std::pair<pt2Func, void*> > func_vector;
         ThreadManager();
         void AddThread(void*, pt2Func); 
         void DeleteThread(pt2Func);
         void ExecuteAllThreads();

  private:
         func_vector list_functions;
};

然后执行所有线程:

void ExecuteAllThreads() {

      func_vector::const_iterator iter_end = list_functions.end();

      for(func_vector::const_iterator iter = list_functions.begin();
      iter != iter_end; ++iter) {

           thread = glfwCreateThread(iter->first, iter->second);
      }
}

当然,在 AddThread 中,您必须向向量添加一对函数指针和参数。

请注意,Boost.Thread 会更干净地解决大部分问题,因为它希望线程是函子(可以保持状态,因此不需要显式参数)。

您的线程函数可以这样定义:

class MyThread {
  MyThread(/* Pass whatever arguments you want in the constructor, and store them in the object as members */);

  void operator()() {
    // The actual thread function
  }

};

而且由于 operator() 不带任何参数,因此启动线程变得更加简单。

于 2009-04-24T14:49:53.667 回答
2

尝试使用 boost::function 存储它们怎么样?

它们可以模拟您的特定功能,因为它们的行为类似于真实对象,但实际上是简单的函子。

于 2009-04-24T14:48:07.743 回答
2

考虑Boost 线程和线程组

于 2009-04-24T15:02:01.703 回答
1

我不熟悉您使用的线程系统。所以请耐心等待。

你不应该维护一个线程标识符列表吗?

 class ThreadManager {
     private:
       vector<thread_id_t> mThreads;
     // ...
 };

然后ExecuteAllThreads你会做:

 for_each(mThreads.begin(), mThreads.end(), bind(some_fun, _1));

(使用 Boost Lambda 绑定和占位符参数)其中 some_fun 是您为所有线程调用的函数。

还是您想为给定线程调用一组函数?

于 2009-04-24T14:50:35.117 回答