blob: c5f1ca005951c2b65c20fef41b1c98e33a9477b2 [file] [log] [blame]
Alexander Afanasyev45fba082012-03-12 18:05:24 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
19 * 卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
20 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
21 */
22
23#include "sync-scheduler.h"
24#include <boost/date_time/posix_time/posix_time.hpp>
25
26using namespace boost;
27using namespace std;
28
29namespace Sync {
30
31Scheduler::Scheduler ()
32 : m_threadRunning (true)
33{
34 m_thread = thread (&Scheduler::threadLoop, this);
35}
36
37Scheduler::~Scheduler ()
38{
39 m_threadRunning = false;
40 // cout << "Requested stop" << this_thread::get_id () << endl;
41 m_thread.interrupt ();
42 m_thread.join ();
43}
44
45void
46Scheduler::threadLoop ()
47{
48 while (m_threadRunning)
49 {
50 try
51 {
52 boost::system_time nextTime;
53 {
54 unique_lock<mutex> lock (m_eventsMutex);
55 while (m_threadRunning && m_events.size () == 0)
56 {
57 m_eventsCondition.wait (lock);
58 // cout << "Got something" << endl;
59 }
60
61 if (m_events.size () == 0) continue;
62
63 nextTime = m_events.begin ()->time;
64 }
65
66 if (nextTime - get_system_time () > posix_time::time_duration (0,0,0,0))
67 {
68 this_thread::sleep (nextTime - get_system_time ());
69
70 // sleeping
71
72 if (nextTime - get_system_time () > posix_time::time_duration (0,0,0,0))
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070073 {
74 // cout << "expected here" << endl;
75 continue; // something changes, try again
76 }
Alexander Afanasyev45fba082012-03-12 18:05:24 -070077 }
78
79 if (!m_threadRunning) continue;
80
81 Event event;
82
83 {
84 lock_guard<mutex> lock (m_eventsMutex);
85
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070086 if (m_events.size () == 0)
87 {
88 // cout << "Here" << endl;
89 continue;
90 }
Alexander Afanasyev45fba082012-03-12 18:05:24 -070091
92 event = m_events.begin ()->event;
93 m_events.erase (m_events.begin ());
94 }
95
96 event (); // calling the event outside the locked mutex
97 }
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070098 catch (thread_interrupted &e)
Alexander Afanasyev45fba082012-03-12 18:05:24 -070099 {
100 // cout << "interrupted: " << this_thread::get_id () << endl;
101 // do nothing
102 }
103 }
104 // cout << "Exited...\n";
105}
106
107
108void
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700109Scheduler::schedule (const boost::system_time &abstime, Event event, uint32_t label)
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700110{
111 {
112 lock_guard<mutex> lock (m_eventsMutex);
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700113 m_events.insert (LogicEvent (abstime, event, label));
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700114 }
115 m_eventsCondition.notify_one ();
116 m_thread.interrupt (); // interrupt sleep, if currently sleeping
117}
118
119void
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700120Scheduler::schedule (const boost::posix_time::time_duration &reltime, Event event, uint32_t label)
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700121{
122 // cout << reltime << endl;
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700123 schedule (boost::get_system_time () + reltime, event, label);
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700124}
125
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700126void
127Scheduler::cancel (uint32_t label)
128{
129 {
130 // cout << "Canceling label " << label << " size: " << m_events.size () << endl;
131 lock_guard<mutex> lock (m_eventsMutex);
132 m_events.get<byLabel> ().erase (label);
133 // cout << "Canceled label " << label << " size: " << m_events.size () << endl;
134 }
135 m_eventsCondition.notify_one ();
136 m_thread.interrupt (); // interrupt sleep, if currently sleeping
137}
138
139
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700140} // Sync