C ++ - 每X毫秒执行一次函数

时间:2015-04-23 22:35:50

标签: c++ multithreading opengl timing glew

我似乎无法找到一个好的答案:

我正在制作游戏,我希望逻辑循环与图形循环分开。换句话说,我希望游戏每隔X毫秒进行一次循环,无论它显示多少帧/秒。

显然他们都会共享很多变量,所以我不能让一个线程/计时器来回传递一个变量......我基本上只是想找一种在后台有一个计时器的方法每隔X毫秒发出一个标志来执行逻辑循环,无论图形循环在哪里。

我愿意接受任何建议。似乎最好的选择是拥有2个线程,但我不确定它们之间进行通信的最佳方式是,不经常同步大量数据。

4 个答案:

答案 0 :(得分:3)

你可以通过你的"世界观"来做多线程。交换每一个滴答。所以这是它的工作原理:

  1. 您当前的世界视图由单个智能指针指向,并且只读,因此无需锁定。
  2. 您的逻辑创建您的(第一个)世界视图,发布它并安排渲染器。
  3. 您的渲染器抓取指向您世界视图的指针副本并呈现它(请记住,只读)
  4. 与此同时,您的逻辑会创建一个新的,略有不同的世界观。
  5. 完成后,它会将指针交换到当前世界视图,并将其作为当前世界视图发布。
  6. 即使渲染器仍然忙于旧世界视图,也不需要锁定。
  7. 最终渲染器完成渲染(旧)世界。它抓住新的世界观并开始另一次运行。
  8. 与此同时,......(转到步骤4)
  9. 您需要的唯一锁定是发布或抓取指向世界的指针。作为替代方案,您可以进行原子交换,但是您必须确保使用能够做到这一点的智能指针。

答案 1 :(得分:1)

大多数工具包都有一个事件循环(构建在某些多路复用系统调用之上,如poll(2) - 或过时的select -...),例如GTK有g_application_run(位于上方:) gtk_main,它位于Glib main event loop之上(实际上是poll或类似的东西)。同样,Qt有QApplication及其exec方法。

通常,您可以在事件循环中注册计时器。对于GTK,请使用GTimer s,g_timeout_add等。有关Qt了解其timers

通常,您还可以注册一些空闲后台处理,这是您在其他事件和超时之后由事件循环启动的功能之一处理。您的空闲函数预计会快速运行(通常它会在几毫秒内执行一些小的步骤,以保持GUI响应)。对于GTK,请使用g_idle_add等.IIRC,在Qt中,您可以使用延迟为0的计时器。

因此,您甚至可以使用超时和空闲处理对(概念上的)单线程应用程序进行编码。

当然,您可以使用多线程:通常主线程正在运行事件循环,而其他线程可以执行其他操作。您有同步问题。在POSIX系统上,一个很好的同步技巧可能是使用pipe(7)自我:你在运行事件循环之前设置一个管道,你的计算线程可能会在其上写几个字节,而主事件循环是"听音"在它上面(使用{,3}}或g_source_add_pollasync IO等,使用GUnixInputStream等,使用QSocketNotifier等等。然后,在该管道的主循环中运行的输入处理程序中,您可以使用互斥锁等访问传统的全局数据...

从概念上讲,请阅读continuations。这是一个相关的概念。

答案 2 :(得分:0)

您可以在所有游戏组件上附加绘图和更新方法。这样你可以设置它在游戏运行时调用更新并忽略绘图或两者的任意组合。它还具有将逻辑和图形完全分开的好处。

答案 3 :(得分:0)

难道你不能为每个需要绘制的对象设置一个draw方法,并使它们成为全局变量。然后运行你的渲染线程,其中有一个睡眠延迟。只要您的渲染线程没有向全局变量写入任何信息,您应该没问题。查找sfml以查看其中的示例。

如果您在unix系统上运行,则可以使用usleep(),但这在Windows上不可用,因此您可能希望查看here以寻找替代方案。