fork(2) download
  1. #include <iostream>
  2. #include <thread>
  3. #include <chrono>
  4. #include <atomic>
  5. #include <functional>
  6. #include <mutex>
  7. #include <condition_variable>
  8.  
  9. using namespace std;
  10.  
  11. bool isMultiThreaded = true;
  12.  
  13. struct RenderThread
  14. {
  15. RenderThread()
  16. {
  17. end = false;
  18. drawing = false;
  19. readyToDraw = false;
  20. }
  21.  
  22. void Run()
  23. {
  24. while (!end)
  25. {
  26. DoJob();
  27. }
  28. }
  29.  
  30. void DoJob()
  31. {
  32. unique_lock<mutex> lk(renderReadyMutex);
  33. renderReady.wait(lk, [this](){ return readyToDraw; });
  34. drawing = true;
  35.  
  36. // RENDER DATA
  37. this_thread::sleep_for(chrono::milliseconds(15)); // simulated render time
  38. cout << "frame " << count << ": " << frame << endl;
  39. ++count;
  40.  
  41. drawing = false;
  42. readyToDraw = false;
  43.  
  44. lk.unlock();
  45. renderReady.notify_one();
  46. }
  47.  
  48. atomic<bool> end;
  49.  
  50. mutex renderReadyMutex;
  51. condition_variable renderReady;
  52. //mutex frame_mutex;
  53. int frame = -10;
  54. int count = 0;
  55.  
  56. bool readyToDraw;
  57. bool drawing;
  58. };
  59.  
  60. struct UpdateThread
  61. {
  62. UpdateThread(RenderThread& rt)
  63. : m_rt(rt)
  64. {}
  65.  
  66. void Run()
  67. {
  68. this_thread::sleep_for(chrono::milliseconds(500));
  69.  
  70. for (int i = 0; i < 20; ++i)
  71. {
  72. // DO GAME UPDATE
  73.  
  74. // when this is uncommented everything is fine
  75. // this_thread::sleep_for(chrono::milliseconds(10)); // simulated update time
  76.  
  77. // PREPARE RENDER THREAD
  78. unique_lock<mutex> lk(m_rt.renderReadyMutex);
  79. m_rt.renderReady.wait(lk, [this](){ return !m_rt.drawing; });
  80.  
  81. m_rt.readyToDraw = true;
  82.  
  83. // SUPPLY RENDER THREAD WITH DATA TO RENDER
  84. m_rt.frame = i;
  85.  
  86. lk.unlock();
  87. m_rt.renderReady.notify_one();
  88.  
  89. if (!isMultiThreaded)
  90. m_rt.DoJob();
  91. }
  92.  
  93. m_rt.end = true;
  94. }
  95.  
  96. RenderThread& m_rt;
  97. };
  98.  
  99. int main()
  100. {
  101. auto start = chrono::high_resolution_clock::now();
  102.  
  103. RenderThread rt;
  104. UpdateThread u(rt);
  105.  
  106. thread* rendering = nullptr;
  107. if (isMultiThreaded)
  108. rendering = new thread(bind(&RenderThread::Run, &rt));
  109.  
  110. u.Run();
  111.  
  112. if (rendering)
  113. rendering->join();
  114.  
  115. auto duration = chrono::high_resolution_clock::now() - start;
  116. cout << "Duration: " << double(chrono::duration_cast<chrono::microseconds>(duration).count())/1000 << endl;
  117.  
  118.  
  119. return 0;
  120. }
Success #stdin #stdout 0s 11664KB
stdin
Standard input is empty
stdout
frame 0: 19
Duration: 515.451