如何维护 C++/STL 中的函数列表?

发布于 2024-07-17 05:47:59 字数 1336 浏览 7 评论 0原文

在直接问你我的问题之前,我将描述我的问题的性质。 我正在使用 C++/OpenGL 和 GLFW 库编写 2D 模拟。 而且我需要正确管理很多线程。 在 GLFW 中我们必须调用该函数: 线程 = 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 中。

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

谢谢 !

Before asking you my question directly, I'm going to describe the nature of my prolem.
I'm coding a 2D simulation using C++/OpenGL with the GLFW library. And I need to manage a lot of threads properly. In GLFW we have to call the function:
thread = glfwCreateThread(ThreadFunc, NULL); (the first parameter is the function that'll execute the thread, and the second represents the parameters of this function).
And glfwCreateThread, has to be called every time! (ie: in each cycle). This way of working, doesn't really help me, because it breaks the way i'm building my code because i need to create threads out of the main loop scope. So I'm creating a ThreadManager class, that'll have the following prototype :

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             


};

So for example, if I want to add a specific thread I'll just need to call AddThread with the specific parameters, and the specific function. And the goal is just to be able to call: ExecuteAllThreads(); inside the main loop scope. But for this i need to have something like:

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);
      }
}

And inside AddThread, I'll just have to add the function referenced by the pt2Func to the vector : list_functions.

Alright, this is the general idea of what i want to do.. is it the right way to go ? You have a better idea ? How to do this, really ? (I mean the problem is the syntax, i'm not sure how to do this).

Thank you !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

紅太極 2024-07-24 05:47:59

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

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

如果可能的话,我建议您使用 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;
};

然后 ExecuteAllThreads:

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() 不接受任何参数,因此启动线程变得更加简单。

You need to create threads in each simulation cycle? That sounds suspicious. Create your threads once, and reuse them.

Thread creation isn't a cheap operation. You definitely don't want to do that in every iteration step.

If possible, I'd recommend you use Boost.Thread for threads instead, to give you type safety and other handy features. Threading is complicated enough without throwing away type safety and working against a primitive C API.

That said, what you're asking is possible, although it gets messy. First, you need to store the arguments for the functions as well, so your class looks something like this:

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;
};

And then ExecuteAllThreads:

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);
      }
}

And of course inside AddThread you'd have to add a pair of function pointer and argument to the vector.

Note that Boost.Thread would solve most of this a lot cleaner, since it expects a thread to be a functor (which can hold state, and therefore doesn't need explicit arguments).

Your thread function could be defined something like this:

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
  }

};

And since the operator() doesn't take any parameters, it becomes a lot simpler to start the thread.

凑诗 2024-07-24 05:47:59

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

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

What about trying to store them using boost::function ?

They could simulate your specific functions, since they behave like real objects but in fact are simple functors.

时光暖心i 2024-07-24 05:47:59

我不熟悉你使用的线程系统。 所以请耐心听我说。

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

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

然后在 ExecuteAllThreads 中,您需要执行以下操作:(

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

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

或者您想为给定线程调用一组函数?

I am not familiar with the threading system you use. So bear with me.

Shouldn't you maintain a list of thread identifiers?

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

and then in ExecuteAllThreads you'd do:

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

(using Boost Lambda bind and placeholder arguments) where some_fun is the function you call for all threads.

Or is it that you want to call a set of functions for a given thread?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文