libsidplayfp 1.0.3
|
00001 /* 00002 * This file is part of libsidplayfp, a SID player engine. 00003 * 00004 * Copyright (C) 2011-2012 Leandro Nini 00005 * Copyright (C) 2009 Antti S. Lankila 00006 * Copyright (C) 2001 Simon White 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #ifndef EVENTSCHEDULER_H 00024 #define EVENTSCHEDULER_H 00025 00026 #include <stdint.h> 00027 00028 #include "event.h" 00029 00030 00031 template< class This > 00032 class EventCallback: public Event 00033 { 00034 private: 00035 typedef void (This::*Callback) (); 00036 00037 private: 00038 This &m_this; 00039 Callback const m_callback; 00040 00041 private: 00042 void event() { (m_this.*m_callback)(); } 00043 00044 public: 00045 EventCallback(const char * const name, This &_this, Callback callback) : 00046 Event(name), 00047 m_this(_this), 00048 m_callback(callback) {} 00049 }; 00050 00051 00057 class EventScheduler: public EventContext 00058 { 00059 private: 00061 event_clock_t currentTime; 00062 00064 Event *firstEvent; 00065 00066 private: 00072 void schedule(Event &event) 00073 { 00074 /* find the right spot where to tuck this new event */ 00075 Event **scan = &firstEvent; 00076 for (;;) 00077 { 00078 if (*scan == 0 || (*scan)->triggerTime > event.triggerTime) 00079 { 00080 event.next = *scan; 00081 *scan = &event; 00082 break; 00083 } 00084 scan = &((*scan)->next); 00085 } 00086 } 00087 00088 protected: 00089 void schedule(Event &event, event_clock_t cycles, 00090 event_phase_t phase) 00091 { 00092 // this strange formulation always selects the next available slot regardless of specified phase. 00093 event.triggerTime = (cycles << 1) + currentTime + ((currentTime & 1) ^ phase); 00094 schedule(event); 00095 } 00096 00097 void schedule(Event &event, event_clock_t cycles) 00098 { 00099 event.triggerTime = (cycles << 1) + currentTime; 00100 schedule(event); 00101 } 00102 00103 void cancel(Event &event); 00104 00105 public: 00106 EventScheduler () : 00107 currentTime(0), 00108 firstEvent(0) {} 00109 00111 void reset(); 00112 00114 void clock() 00115 { 00116 Event &event = *firstEvent; 00117 firstEvent = firstEvent->next; 00118 currentTime = event.triggerTime; 00119 event.event(); 00120 } 00121 00122 bool isPending(Event &event) const; 00123 00124 event_clock_t getTime(event_phase_t phase) const 00125 { 00126 return (currentTime + (phase ^ 1)) >> 1; 00127 } 00128 00129 event_clock_t getTime(event_clock_t clock, event_phase_t phase) const 00130 { 00131 return getTime (phase) - clock; 00132 } 00133 00134 event_phase_t phase() const { return (event_phase_t) (currentTime & 1); } 00135 }; 00136 00137 #endif // EVENTSCHEDULER_H