C++ - Execute function every X milliseconds

99封情书 提交于 2019-12-10 12:06:19

问题


I can't seem to find a good answer to this:

I'm making a game, and I want the logic loop to be separate from the graphics loop. In other words I want the game to go through a loop every X milliseconds regardless of how many frames/second it is displaying.

Obviously they will both be sharing a lot of variables, so I can't have a thread/timer passing one variable back and forth... I'm basically just looking for a way to have a timer in the background that every X milliseconds sends out a flag to execute the logic loop, regardless of where the graphics loop is.

I'm open to any suggestions. It seems like the best option is to have 2 threads, but I'm not sure what the best way to communicate between them is, without constantly synchronizing large amounts of data.


回答1:


You can very well do multithreading by having your "world view" exchanged every tick. So here is how it works:

  1. Your current world view is pointed to by a single smart pointer and is read only, so no locking is necessary.
  2. Your logic creates your (first) world view, publishes it and schedules the renderer.
  3. Your renderer grabs a copy of the pointer to your world view and renders it (remember, read-only)
  4. In the meantime, your logic creates a new, slightly different world view.
  5. When it's done it exchanges the pointer to the current world view, publishing it as the current one.
  6. Even if the renderer is still busy with the old world view there is no locking necessary.
  7. Eventually the renderer finishes rendering the (old) world. It grabs the new world view and starts another run.
  8. In the meantime, ... (goto step 4)

The only locking you need is for the time when you publish or grab the pointer to the world. As an alternative you can do atomic exchange but then you have to make sure you use smart pointers that can do that.




回答2:


Most toolkits have an event loop (built above some multiplexing syscall like poll(2) -or the obsolete select-...), e.g. GTK has g_application_run (which is above:) gtk_main which is built above Glib main event loop (which in fact does a poll or something similar). Likewise, Qt has QApplication and its exec methods.

Very often, you can register timers within the event loop. For GTK, use GTimers, g_timeout_add etc. For Qt learn about its timers.

Very often, you can also register some idle or background processing, which is one of your function which is started by the event loop after other events and timeouts have been processed. Your idle function is expected to run quickly (usually it does a small step of some computation in a few milliseconds, to keep the GUI responsive). For GTK, use g_idle_add etc. IIRC, in Qt you can use a timer with a 0 delay.

So you could code even a (conceptually) single threaded application, using timeouts and idle processing.

Of course, you could use multi-threading: generally the main thread is running the event loop, and other threads can do other things. You have synchronization issues. On POSIX systems, a nice synchronization trick could be to use a pipe(7) to self: you set up a pipe before running the event loop, and your computation threads may write a few bytes on it, while the main event loop is "listening" on it (with GTK, using g_source_add_poll or async IO or GUnixInputStream etc.., with Qt, using QSocketNotifier etc....). Then, in the input handler running in the main loop for that pipe, you could access traditional global data with mutexes etc...

Conceptually, read about continuations. It is a relevant notion.




回答3:


You could have a Draw and Update Method attached to all your game components. That way you can set it that while your game is running the update is called and the draw is ignored or any combination of the two. It also has the benefit of keeping logic and graphics completely separate.




回答4:


Couldn't you just have a draw method for each object that needs to be drawn and make them globals. Then just run your rendering thread with a sleep delay in it. As long as your rendering thread doesn't write any information to the globals you should be fine. Look up sfml to see an example of it in action.

If you are running on a unix system you could use usleep() however that is not available on windows so you might want to look here for alternatives.



来源:https://stackoverflow.com/questions/29835569/c-execute-function-every-x-milliseconds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!