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
6// B
7
8#include <boost/atomic.hpp>
9//#include <boost/log/trivial.hpp>
10#include <boost/chrono.hpp>
11#include <boost/chrono/chrono_io.hpp>
12#include <boost/thread.hpp>
13#include <boost/thread/condition_variable.hpp>
14
15typedef boost::chrono::high_resolution_clock Clock;
16typedef Clock::time_point TimePoint;
17
18inline TimePoint real_time_now()
19{
20 return Clock::now();
21}
22
23class Foo {
24 boost::atomic<bool> m_is_exiting;
25 TimePoint m_next_tick_time;
26
27public:
28
29 bool is_exiting() const
30 {
31 return m_is_exiting;
32 }
33
34 TimePoint spawn_tasks() // note that in my app, this call takes more time than here
35 {
36 using namespace boost::chrono;
37 const TimePoint now = real_time_now();
38
39 if (m_next_tick_time < now) {
40 m_next_tick_time = now + seconds(1);
41 //BOOST_LOG_TRIVIAL(info) << "TICK!";
42 }
43
44 return m_next_tick_time;
45 }
46
47};
48
49int main()
50{
51 using namespace boost::chrono;
52 static const milliseconds MIN_TIME_TASKS_SPAWN_FREQUENCY = milliseconds(1);
53 //microseconds(1); // THE SHORTER THE QUICKER TO REPRODUCE THE BUG
54
55 boost::condition_variable m_task_spawn_condition;
56 Foo foo;
57
58 boost::mutex main_thread_mutex;
59 boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex);
60
61 //BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN";
62
63 int i =11;
64 while (i--)
65 {
66 const TimePoint next_task_spawn_time = foo.spawn_tasks();
67
68 const TimePoint now = real_time_now();
69 const TimePoint next_minimum_spawn_time = now + MIN_TIME_TASKS_SPAWN_FREQUENCY;
70 const TimePoint next_spawn_time = next_task_spawn_time > TimePoint()
71 && next_task_spawn_time < next_minimum_spawn_time
72 ? next_task_spawn_time : next_minimum_spawn_time;
73
74 const TimePoint::duration wait_time = next_spawn_time - now;
75 if (wait_time > wait_time.zero()) {
76 // BOOST_LOG_TRIVIAL(trace) << "WAIT TIME: " << wait_time; // UNCOMMENT THIS: MAKES IT WORKS. WAT??????
77 boost::this_thread::sleep_for(d: boost::chrono::seconds(1));
78 std::cout << next_spawn_time << std::endl;
79 m_task_spawn_condition.wait_until(
80 lock&: main_thread_lock,
81 t: next_spawn_time); // DON'T WORK: WILL WAIT IF next_spawn_time is too close!
82 }
83
84 }
85
86}
87

source code of boost/libs/thread/test/test_9079_b.cpp