blob: ced11c3846ff01c31016df705d74839919e0019d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/***************************************************************************
event.cpp - Event schdeduler (based on alarm
from Vice)
-------------------
begin : Wed May 9 2001
copyright : (C) 2001 by Simon White
email : s_a_white@email.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/***************************************************************************
* $Log: event.cpp,v $
* Revision 1.7 2002/11/21 19:55:38 s_a_white
* We now jump to next event directly instead on clocking by a number of
* cycles.
*
* Revision 1.6 2002/07/17 19:20:03 s_a_white
* More efficient event handling code.
*
* Revision 1.5 2001/10/02 18:24:09 s_a_white
* Updated to support safe scheduler interface.
*
* Revision 1.4 2001/09/17 19:00:28 s_a_white
* Constructor moved out of line.
*
* Revision 1.3 2001/09/15 13:03:50 s_a_white
* timeWarp now zeros m_eventClk instead of m_pendingEventClk which
* fixes a inifinite loop problem when driving libsidplay1.
*
***************************************************************************/
#include <string.h>
#include "event.h"
#define EVENT_TIMEWARP_COUNT 0x0FFFFF
EventScheduler::EventScheduler (const char * const name)
:m_name(name),
m_pendingEventCount(0),
m_timeWarp(this)
{
memset (&m_pendingEvents, 0, sizeof (Event));
m_pendingEvents.m_next = &m_pendingEvents;
m_pendingEvents.m_prev = &m_pendingEvents;
reset ();
}
// Usefull to prevent clock overflowing
void EventScheduler::timeWarp ()
{
Event *e = &m_pendingEvents;
uint count = m_pendingEventCount;
while (count--)
{ // Reduce all event clocks and clip them
// so none go negative
event_clock_t clk;
e = e->m_next;
clk = e->m_clk;
e->m_clk = 0;
if (clk >= m_eventClk)
e->m_clk = clk - m_eventClk;
}
m_eventClk = 0;
// Re-schedule the next timeWarp
schedule (&m_timeWarp, EVENT_TIMEWARP_COUNT);
}
void EventScheduler::reset (void)
{ // Remove all events
Event *e = &m_pendingEvents;
uint count = m_pendingEventCount;
while (count--)
{
e = e->m_next;
e->m_pending = false;
}
m_pendingEvents.m_next = &m_pendingEvents;
m_pendingEvents.m_prev = &m_pendingEvents;
m_pendingEventClk = m_eventClk = m_schedClk = 0;
m_pendingEventCount = 0;
timeWarp ();
}
// Add event to ordered pending queue
void EventScheduler::schedule (Event *event, event_clock_t cycles)
{
uint clk = m_eventClk + cycles;
if (event->m_pending)
cancelPending (*event);
event->m_pending = true;
event->m_clk = clk;
{ // Now put in the correct place so we don't need to keep
// searching the list later.
Event *e = m_pendingEvents.m_next;
uint count = m_pendingEventCount;
while (count-- && (e->m_clk <= clk))
e = e->m_next;
event->m_next = e;
event->m_prev = e->m_prev;
e->m_prev->m_next = event;
e->m_prev = event;
m_pendingEventClk = m_pendingEvents.m_next->m_clk;
m_pendingEventCount++;
}
}
// Cancel a pending event
void EventScheduler::cancel (Event *event)
{
if (event->m_pending)
cancelPending (*event);
}
|