blob: f54f91f2689a15a3ae2f46879b5820f70c8b5638 [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"
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070024#include "sync-log.h"
Alexander Afanasyev45fba082012-03-12 18:05:24 -070025
26using namespace boost;
27using namespace std;
28
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070029INIT_LOGGER ("Scheduler");
30
Alexander Afanasyev45fba082012-03-12 18:05:24 -070031namespace Sync {
32
33Scheduler::Scheduler ()
34 : m_threadRunning (true)
35{
36 m_thread = thread (&Scheduler::threadLoop, this);
37}
38
39Scheduler::~Scheduler ()
40{
41 m_threadRunning = false;
42 // cout << "Requested stop" << this_thread::get_id () << endl;
43 m_thread.interrupt ();
44 m_thread.join ();
45}
46
47void
48Scheduler::threadLoop ()
49{
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070050 _LOG_FUNCTION (this);
Alexander Afanasyev45fba082012-03-12 18:05:24 -070051 while (m_threadRunning)
52 {
53 try
54 {
55 boost::system_time nextTime;
56 {
57 unique_lock<mutex> lock (m_eventsMutex);
58 while (m_threadRunning && m_events.size () == 0)
59 {
60 m_eventsCondition.wait (lock);
61 // cout << "Got something" << endl;
62 }
63
64 if (m_events.size () == 0) continue;
65
66 nextTime = m_events.begin ()->time;
67 }
68
69 if (nextTime - get_system_time () > posix_time::time_duration (0,0,0,0))
70 {
71 this_thread::sleep (nextTime - get_system_time ());
72
73 // sleeping
74
75 if (nextTime - get_system_time () > posix_time::time_duration (0,0,0,0))
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070076 {
77 // cout << "expected here" << endl;
78 continue; // something changes, try again
79 }
Alexander Afanasyev45fba082012-03-12 18:05:24 -070080 }
81
82 if (!m_threadRunning) continue;
83
84 Event event;
85
86 {
87 lock_guard<mutex> lock (m_eventsMutex);
88
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070089 if (m_events.size () == 0)
90 {
91 // cout << "Here" << endl;
92 continue;
93 }
Alexander Afanasyev45fba082012-03-12 18:05:24 -070094
95 event = m_events.begin ()->event;
96 m_events.erase (m_events.begin ());
97 }
98
99 event (); // calling the event outside the locked mutex
100 }
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700101 catch (thread_interrupted &e)
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700102 {
103 // cout << "interrupted: " << this_thread::get_id () << endl;
104 // do nothing
105 }
106 }
107 // cout << "Exited...\n";
108}
109
110
111void
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700112Scheduler::schedule (const boost::system_time &abstime, Event event, uint32_t label)
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700113{
114 {
115 lock_guard<mutex> lock (m_eventsMutex);
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700116 m_events.insert (LogicEvent (abstime, event, label));
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700117 }
118 m_eventsCondition.notify_one ();
119 m_thread.interrupt (); // interrupt sleep, if currently sleeping
120}
121
122void
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700123Scheduler::schedule (const boost::posix_time::time_duration &reltime, Event event, uint32_t label)
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700124{
125 // cout << reltime << endl;
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700126 schedule (boost::get_system_time () + reltime, event, label);
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700127}
128
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700129void
130Scheduler::cancel (uint32_t label)
131{
132 {
133 // cout << "Canceling label " << label << " size: " << m_events.size () << endl;
134 lock_guard<mutex> lock (m_eventsMutex);
135 m_events.get<byLabel> ().erase (label);
136 // cout << "Canceled label " << label << " size: " << m_events.size () << endl;
137 }
138 m_eventsCondition.notify_one ();
139 m_thread.interrupt (); // interrupt sleep, if currently sleeping
140}
141
142
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700143} // Sync