summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/schedule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/schedule.cpp')
-rw-r--r--src/emu/schedule.cpp181
1 files changed, 110 insertions, 71 deletions
diff --git a/src/emu/schedule.cpp b/src/emu/schedule.cpp
index 4605dbb82de..52a2b84d2f3 100644
--- a/src/emu/schedule.cpp
+++ b/src/emu/schedule.cpp
@@ -44,8 +44,8 @@ enum
// emu_timer - constructor
//-------------------------------------------------
-emu_timer::emu_timer() :
- m_machine(nullptr),
+inline emu_timer::emu_timer() noexcept :
+ m_scheduler(nullptr),
m_next(nullptr),
m_prev(nullptr),
m_param(0),
@@ -72,7 +72,7 @@ emu_timer::~emu_timer()
// re-allocated as a non-device timer
//-------------------------------------------------
-emu_timer &emu_timer::init(
+inline emu_timer &emu_timer::init(
running_machine &machine,
timer_expired_delegate &&callback,
attotime start_delay,
@@ -80,7 +80,7 @@ emu_timer &emu_timer::init(
bool temporary)
{
// ensure the entire timer state is clean
- m_machine = &machine;
+ m_scheduler = &machine.scheduler();
m_next = nullptr;
m_prev = nullptr;
m_callback = std::move(callback);
@@ -88,43 +88,31 @@ emu_timer &emu_timer::init(
m_temporary = temporary;
m_period = attotime::never;
- device_scheduler &scheduler = machine.scheduler();
- m_start = scheduler.time();
+ m_start = m_scheduler->time();
m_expire = m_start + start_delay;
m_enabled = !m_expire.is_never();
// if we're not temporary, register ourselves with the save state system
if (!m_temporary)
- register_save();
+ register_save(machine.save());
// insert into the list
- scheduler.timer_list_insert(*this);
- if (this == scheduler.first_timer())
- scheduler.abort_timeslice();
+ m_scheduler->timer_list_insert(*this);
+ if (this == m_scheduler->first_timer())
+ m_scheduler->abort_timeslice();
return *this;
}
//-------------------------------------------------
-// release - release us from the global list
-// management when deallocating
-//-------------------------------------------------
-
-inline emu_timer &emu_timer::release()
-{
- // unhook us from the global list
- machine().scheduler().timer_list_remove(*this);
- return *this;
-}
-
-
-//-------------------------------------------------
// enable - enable/disable a timer
//-------------------------------------------------
-bool emu_timer::enable(bool enable)
+bool emu_timer::enable(bool enable) noexcept
{
+ assert(m_scheduler);
+
// reschedule only if the state has changed
const bool old = m_enabled;
if (old != enable)
@@ -133,8 +121,8 @@ bool emu_timer::enable(bool enable)
m_enabled = enable;
// remove the timer and insert back into the list
- machine().scheduler().timer_list_remove(*this);
- machine().scheduler().timer_list_insert(*this);
+ m_scheduler->timer_list_remove(*this);
+ m_scheduler->timer_list_insert(*this);
}
return old;
}
@@ -146,12 +134,13 @@ bool emu_timer::enable(bool enable)
// firings
//-------------------------------------------------
-void emu_timer::adjust(attotime start_delay, s32 param, const attotime &period)
+void emu_timer::adjust(attotime start_delay, s32 param, const attotime &period) noexcept
{
+ assert(m_scheduler);
+
// if this is the callback timer, mark it modified
- device_scheduler &scheduler = machine().scheduler();
- if (scheduler.m_callback_timer == this)
- scheduler.m_callback_timer_modified = true;
+ if (m_scheduler->m_callback_timer == this)
+ m_scheduler->m_callback_timer_modified = true;
// compute the time of the next firing and insert into the list
m_param = param;
@@ -162,17 +151,17 @@ void emu_timer::adjust(attotime start_delay, s32 param, const attotime &period)
start_delay = attotime::zero;
// set the start and expire times
- m_start = scheduler.time();
+ m_start = m_scheduler->time();
m_expire = m_start + start_delay;
m_period = period;
// remove and re-insert the timer in its new order
- scheduler.timer_list_remove(*this);
- scheduler.timer_list_insert(*this);
+ m_scheduler->timer_list_remove(*this);
+ m_scheduler->timer_list_insert(*this);
// if this was inserted as the head, abort the current timeslice and resync
- if (this == scheduler.first_timer())
- scheduler.abort_timeslice();
+ if (this == m_scheduler->first_timer())
+ m_scheduler->abort_timeslice();
}
@@ -183,7 +172,9 @@ void emu_timer::adjust(attotime start_delay, s32 param, const attotime &period)
attotime emu_timer::elapsed() const noexcept
{
- return machine().time() - m_start;
+ assert(m_scheduler);
+
+ return m_scheduler->time() - m_start;
}
@@ -194,7 +185,9 @@ attotime emu_timer::elapsed() const noexcept
attotime emu_timer::remaining() const noexcept
{
- attotime curtime = machine().time();
+ assert(m_scheduler);
+
+ const attotime curtime = m_scheduler->time();
if (curtime >= m_expire)
return attotime::zero;
return m_expire - curtime;
@@ -206,37 +199,37 @@ attotime emu_timer::remaining() const noexcept
// state system
//-------------------------------------------------
-void emu_timer::register_save()
+void emu_timer::register_save(save_manager &manager)
{
// determine our instance number - timers are indexed based on the callback function name
int index = 0;
std::string name = m_callback.name() ? m_callback.name() : "unnamed";
- for (emu_timer *curtimer = machine().scheduler().first_timer(); curtimer != nullptr; curtimer = curtimer->next())
+ for (const emu_timer *curtimer = m_scheduler->first_timer(); curtimer; curtimer = curtimer->m_next)
{
if (!curtimer->m_temporary)
{
- if (curtimer->m_callback.name() != nullptr && m_callback.name() != nullptr && strcmp(curtimer->m_callback.name(), m_callback.name()) == 0)
+ if (curtimer->m_callback.name() && m_callback.name() && !strcmp(curtimer->m_callback.name(), m_callback.name()))
index++;
- else if (curtimer->m_callback.name() == nullptr && m_callback.name() == nullptr)
+ else if (!curtimer->m_callback.name() && !m_callback.name())
index++;
}
}
- for (emu_timer *curtimer = machine().scheduler().m_inactive_timers; curtimer != nullptr; curtimer = curtimer->next())
+ for (const emu_timer *curtimer = m_scheduler->m_inactive_timers; curtimer; curtimer = curtimer->m_next)
{
assert(!curtimer->m_temporary);
- if (curtimer->m_callback.name() != nullptr && m_callback.name() != nullptr && strcmp(curtimer->m_callback.name(), m_callback.name()) == 0)
+ if (curtimer->m_callback.name() && m_callback.name() && !strcmp(curtimer->m_callback.name(), m_callback.name()))
index++;
- else if (curtimer->m_callback.name() == nullptr && m_callback.name() == nullptr)
+ else if (!curtimer->m_callback.name() && !m_callback.name())
index++;
}
// save the bits
- machine().save().save_item(nullptr, "timer", name.c_str(), index, NAME(m_param));
- machine().save().save_item(nullptr, "timer", name.c_str(), index, NAME(m_enabled));
- machine().save().save_item(nullptr, "timer", name.c_str(), index, NAME(m_period));
- machine().save().save_item(nullptr, "timer", name.c_str(), index, NAME(m_start));
- machine().save().save_item(nullptr, "timer", name.c_str(), index, NAME(m_expire));
+ manager.save_item(nullptr, "timer", name.c_str(), index, NAME(m_param));
+ manager.save_item(nullptr, "timer", name.c_str(), index, NAME(m_enabled));
+ manager.save_item(nullptr, "timer", name.c_str(), index, NAME(m_period));
+ manager.save_item(nullptr, "timer", name.c_str(), index, NAME(m_start));
+ manager.save_item(nullptr, "timer", name.c_str(), index, NAME(m_expire));
}
@@ -245,16 +238,17 @@ void emu_timer::register_save()
// period
//-------------------------------------------------
-inline void emu_timer::schedule_next_period()
+inline void emu_timer::schedule_next_period() noexcept
{
+ assert(m_scheduler);
+
// advance by one period
m_start = m_expire;
m_expire += m_period;
// remove and re-insert us
- device_scheduler &scheduler = machine().scheduler();
- scheduler.timer_list_remove(*this);
- scheduler.timer_list_insert(*this);
+ m_scheduler->timer_list_remove(*this);
+ m_scheduler->timer_list_insert(*this);
}
@@ -265,11 +259,13 @@ inline void emu_timer::schedule_next_period()
void emu_timer::dump() const
{
- machine().logerror("%p: en=%d temp=%d exp=%15s start=%15s per=%15s param=%d", this, m_enabled, m_temporary, m_expire.as_string(PRECISION), m_start.as_string(PRECISION), m_period.as_string(PRECISION), m_param);
- if (m_callback.name() == nullptr)
- machine().logerror(" cb=NULL\n");
+ assert(m_scheduler);
+
+ m_scheduler->machine().logerror("%p: en=%d temp=%d exp=%15s start=%15s per=%15s param=%d", this, m_enabled, m_temporary, m_expire.as_string(PRECISION), m_start.as_string(PRECISION), m_period.as_string(PRECISION), m_param);
+ if (!m_callback.name())
+ m_scheduler->machine().logerror(" cb=NULL\n");
else
- machine().logerror(" cb=%s\n", m_callback.name());
+ m_scheduler->machine().logerror(" cb=%s\n", m_callback.name());
}
@@ -319,9 +315,9 @@ device_scheduler::~device_scheduler()
{
// remove all timers
while (m_inactive_timers)
- m_timer_allocator.reclaim(m_inactive_timers->release());
+ m_timer_allocator.reclaim(timer_list_remove(*m_inactive_timers));
while (m_timer_list)
- m_timer_allocator.reclaim(m_timer_list->release());
+ m_timer_allocator.reclaim(timer_list_remove(*m_timer_list));
}
@@ -349,13 +345,15 @@ attotime device_scheduler::time() const noexcept
bool device_scheduler::can_save() const
{
// if any live temporary timers exit, fail
- for (emu_timer *timer = m_timer_list; timer != nullptr; timer = timer->next())
+ for (emu_timer *timer = m_timer_list; timer; timer = timer->m_next)
+ {
if (timer->m_temporary && !timer->expire().is_never())
{
machine().logerror("Failed save state attempt due to anonymous timers:\n");
dump_timers();
return false;
}
+ }
// otherwise, we're good
return true;
@@ -513,7 +511,7 @@ void device_scheduler::timeslice()
// current timeslice
//-------------------------------------------------
-void device_scheduler::abort_timeslice()
+void device_scheduler::abort_timeslice() noexcept
{
if (m_executing_device != nullptr)
m_executing_device->abort_timeslice();
@@ -570,6 +568,40 @@ emu_timer *device_scheduler::timer_alloc(timer_expired_delegate callback)
//-------------------------------------------------
+// timer_set - allocate an anonymous non-device
+// timer and set it to go off after the given
+// amount of time
+//-------------------------------------------------
+
+void device_scheduler::timer_set(const attotime &duration, timer_expired_delegate callback, int param)
+{
+ [[maybe_unused]] emu_timer &timer = m_timer_allocator.alloc()->init(
+ machine(),
+ std::move(callback),
+ duration,
+ param,
+ true);
+ assert(!timer.m_expire.is_never()); // this is not handled
+}
+
+
+//-------------------------------------------------
+// synchronize - allocate an anonymous non-device
+// timer and set it to go off as soon as possible
+//-------------------------------------------------
+
+void device_scheduler::synchronize(timer_expired_delegate callback, int param)
+{
+ m_timer_allocator.alloc()->init(
+ machine(),
+ std::move(callback),
+ attotime::zero,
+ param,
+ true);
+}
+
+
+//-------------------------------------------------
// eat_all_cycles - eat a ton of cycles on all
// CPUs to force a quick exit
//-------------------------------------------------
@@ -613,13 +645,14 @@ void device_scheduler::presave()
void device_scheduler::postload()
{
// remove all timers and make a private list of permanent ones
- simple_list<emu_timer> private_list;
+ emu_timer *private_list = nullptr;
while (m_inactive_timers)
{
emu_timer &timer = *m_inactive_timers;
assert(!timer.m_temporary);
- private_list.append(timer_list_remove(timer));
+ timer_list_remove(timer).m_next = private_list;
+ private_list = &timer;
}
while (m_timer_list->m_next)
{
@@ -630,12 +663,13 @@ void device_scheduler::postload()
assert(!timer.expire().is_never());
// temporary timers go away entirely (except our special never-expiring one)
- m_timer_allocator.reclaim(timer.release());
+ m_timer_allocator.reclaim(timer_list_remove(timer));
}
else
{
// permanent ones get added to our private list
- private_list.append(timer_list_remove(timer));
+ timer_list_remove(timer).m_next = private_list;
+ private_list = &timer;
}
}
@@ -645,9 +679,12 @@ void device_scheduler::postload()
assert(m_timer_list->m_expire.is_never());
// now re-insert them; this effectively re-sorts them by time
- emu_timer *timer;
- while ((timer = private_list.detach_head()) != nullptr)
- timer_list_insert(*timer);
+ while (private_list)
+ {
+ emu_timer &timer = *private_list;
+ private_list = timer.m_next;
+ timer_list_insert(timer);
+ }
m_suspend_changes_pending = true;
rebuild_execute_list();
@@ -768,7 +805,7 @@ inline emu_timer &device_scheduler::timer_list_insert(emu_timer &timer)
{
// loop over the timer list
emu_timer *prevtimer = nullptr;
- for (emu_timer *curtimer = m_timer_list; curtimer; prevtimer = curtimer, curtimer = curtimer->next())
+ for (emu_timer *curtimer = m_timer_list; curtimer; prevtimer = curtimer, curtimer = curtimer->m_next)
{
// if the current list entry expires after us, we should be inserted before it
if (curtimer->m_expire > timer.m_expire)
@@ -887,7 +924,7 @@ inline void device_scheduler::execute_timers()
else
{
// otherwise, remove it now
- m_timer_allocator.reclaim(timer.release());
+ m_timer_allocator.reclaim(timer_list_remove(timer));
}
}
}
@@ -950,7 +987,9 @@ void device_scheduler::dump_timers() const
{
machine().logerror("=============================================\n");
machine().logerror("Timer Dump: Time = %15s\n", time().as_string(PRECISION));
- for (emu_timer *timer = first_timer(); timer != nullptr; timer = timer->next())
+ for (emu_timer *timer = m_timer_list; timer; timer = timer->m_next)
+ timer->dump();
+ for (emu_timer *timer = m_inactive_timers; timer; timer = timer->m_next)
timer->dump();
machine().logerror("=============================================\n");
}