libsidplayfp  1.5.3
EventScheduler.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright (C) 2011-2012 Leandro Nini
5  * Copyright (C) 2009 Antti S. Lankila
6  * Copyright (C) 2001 Simon White
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #ifndef EVENTSCHEDULER_H
24 #define EVENTSCHEDULER_H
25 
26 #include "event.h"
27 
28 
29 template< class This >
30 class EventCallback: public Event
31 {
32 private:
33  typedef void (This::*Callback) ();
34 
35 private:
36  This &m_this;
37  Callback const m_callback;
38 
39 private:
40  void event() { (m_this.*m_callback)(); }
41 
42 public:
43  EventCallback(const char * const name, This &_this, Callback callback) :
44  Event(name),
45  m_this(_this),
46  m_callback(callback) {}
47 };
48 
49 
56 {
57 private:
61  event_clock_t currentTime;
62 
66  Event *firstEvent;
67 
68 private:
74  void schedule(Event &event)
75  {
76  // find the right spot where to tuck this new event
77  Event **scan = &firstEvent;
78  for (;;)
79  {
80  if (*scan == 0 || (*scan)->triggerTime > event.triggerTime)
81  {
82  event.next = *scan;
83  *scan = &event;
84  break;
85  }
86  scan = &((*scan)->next);
87  }
88  }
89 
90 protected:
91  void schedule(Event &event, event_clock_t cycles,
92  event_phase_t phase)
93  {
94  // this strange formulation always selects the next available slot regardless of specified phase.
95  event.triggerTime = (cycles << 1) + currentTime + ((currentTime & 1) ^ phase);
96  schedule(event);
97  }
98 
99  void schedule(Event &event, event_clock_t cycles)
100  {
101  event.triggerTime = (cycles << 1) + currentTime;
102  schedule(event);
103  }
104 
105  void cancel(Event &event);
106 
107 public:
108  EventScheduler () :
109  currentTime(0),
110  firstEvent(0) {}
111 
115  void reset();
116 
120  void clock()
121  {
122  Event &event = *firstEvent;
123  firstEvent = firstEvent->next;
124  currentTime = event.triggerTime;
125  event.event();
126  }
127 
131  bool isPending(Event &event) const;
132 
133  event_clock_t getTime(event_phase_t phase) const
134  {
135  return (currentTime + (phase ^ 1)) >> 1;
136  }
137 
138  event_clock_t getTime(event_clock_t clock, event_phase_t phase) const
139  {
140  return getTime (phase) - clock;
141  }
142 
143  event_phase_t phase() const { return (event_phase_t) (currentTime & 1); }
144 };
145 
146 #endif // EVENTSCHEDULER_H