blob: 4ec13de0b21f75b292c1fbedb6ee217562111e8f [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>
Chaoyi Bian3e1eb162012-04-03 16:59:32 -070019 * Chaoyi Bian <bcy@pku.edu.cn>
Alexander Afanasyev45fba082012-03-12 18:05:24 -070020 * 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
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -070069 if (nextTime > get_system_time ())
Alexander Afanasyev45fba082012-03-12 18:05:24 -070070 {
71 this_thread::sleep (nextTime - get_system_time ());
72
73 // sleeping
74
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -070075 if (nextTime > get_system_time ())
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
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700110void
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700111Scheduler::schedule (const boost::posix_time::time_duration &reltime, Event event, uint32_t label)
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700112{
Alexander Afanasyevca6f3292012-04-09 10:03:30 -0700113 {
114 lock_guard<mutex> lock (m_eventsMutex);
115 m_events.insert (LogicEvent (boost::get_system_time () + reltime, event, label));
116 }
117 m_eventsCondition.notify_one ();
118 m_thread.interrupt (); // interrupt sleep, if currently sleeping
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700119}
120
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700121void
122Scheduler::cancel (uint32_t label)
123{
124 {
125 // cout << "Canceling label " << label << " size: " << m_events.size () << endl;
126 lock_guard<mutex> lock (m_eventsMutex);
127 m_events.get<byLabel> ().erase (label);
128 // cout << "Canceled label " << label << " size: " << m_events.size () << endl;
129 }
130 m_eventsCondition.notify_one ();
131 m_thread.interrupt (); // interrupt sleep, if currently sleeping
132}
133
134
Alexander Afanasyev45fba082012-03-12 18:05:24 -0700135} // Sync