test_9079_b.cpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright (C) 2013 Vicente Botet
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // B
  6. #include <boost/atomic.hpp>
  7. //#include <boost/log/trivial.hpp>
  8. #include <boost/chrono.hpp>
  9. #include <boost/chrono/chrono_io.hpp>
  10. #include <boost/thread.hpp>
  11. #include <boost/thread/condition_variable.hpp>
  12. typedef boost::chrono::high_resolution_clock Clock;
  13. typedef Clock::time_point TimePoint;
  14. inline TimePoint real_time_now()
  15. {
  16. return Clock::now();
  17. }
  18. class Foo {
  19. boost::atomic<bool> m_is_exiting;
  20. TimePoint m_next_tick_time;
  21. public:
  22. bool is_exiting() const
  23. {
  24. return m_is_exiting;
  25. }
  26. TimePoint spawn_tasks() // note that in my app, this call takes more time than here
  27. {
  28. using namespace boost::chrono;
  29. const TimePoint now = real_time_now();
  30. if (m_next_tick_time < now) {
  31. m_next_tick_time = now + seconds(1);
  32. //BOOST_LOG_TRIVIAL(info) << "TICK!";
  33. }
  34. return m_next_tick_time;
  35. }
  36. };
  37. int main()
  38. {
  39. using namespace boost::chrono;
  40. static const milliseconds MIN_TIME_TASKS_SPAWN_FREQUENCY = milliseconds(1);
  41. //microseconds(1); // THE SHORTER THE QUICKER TO REPRODUCE THE BUG
  42. boost::condition_variable m_task_spawn_condition;
  43. Foo foo;
  44. boost::mutex main_thread_mutex;
  45. boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex);
  46. //BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN";
  47. int i =11;
  48. while (i--)
  49. {
  50. const TimePoint next_task_spawn_time = foo.spawn_tasks();
  51. const TimePoint now = real_time_now();
  52. const TimePoint next_minimum_spawn_time = now + MIN_TIME_TASKS_SPAWN_FREQUENCY;
  53. const TimePoint next_spawn_time = next_task_spawn_time > TimePoint()
  54. && next_task_spawn_time < next_minimum_spawn_time
  55. ? next_task_spawn_time : next_minimum_spawn_time;
  56. const TimePoint::duration wait_time = next_spawn_time - now;
  57. if (wait_time > wait_time.zero()) {
  58. // BOOST_LOG_TRIVIAL(trace) << "WAIT TIME: " << wait_time; // UNCOMMENT THIS: MAKES IT WORKS. WAT??????
  59. boost::this_thread::sleep_for(boost::chrono::seconds(1));
  60. std::cout << next_spawn_time << std::endl;
  61. m_task_spawn_condition.wait_until(
  62. main_thread_lock,
  63. next_spawn_time); // DON'T WORK: WILL WAIT IF next_spawn_time is too close!
  64. }
  65. }
  66. }