Skip to content

Commit 75d019f

Browse files
committed
Allows tick events to auto-requeue when registered as listeners
1 parent f191334 commit 75d019f

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

docs/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
5353
## Documentation
5454

5555
## API
56+
- ``EventManager``: revises tick events to work as listeners. Tick events registered with ``registerListener`` will now automatically requeue at their designated frequency.
5657

5758
## Lua
5859

library/include/modules/EventManager.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ namespace DFHack {
4646
typedef void (*callback_t)(color_ostream&, void*); //called when the event happens
4747
callback_t eventHandler;
4848
int32_t freq; //how often event is allowed to fire (in ticks) use 0 to always fire when possible
49+
int32_t when = -1; //when to fire event (global tick count)
4950

50-
EventHandler(callback_t eventHandlerIn, int32_t freqIn): eventHandler(eventHandlerIn), freq(freqIn) {
51-
}
51+
EventHandler(callback_t eventHandlerIn, int32_t freqIn) :
52+
eventHandler(eventHandlerIn),
53+
freq(freqIn) {}
5254

5355
bool operator==(const EventHandler& handle) const {
5456
return eventHandler == handle.eventHandler && freq == handle.freq;
@@ -144,6 +146,7 @@ namespace std {
144146
size_t r = 17;
145147
const size_t m = 65537;
146148
r = m*(r+(intptr_t)h.eventHandler);
149+
r = m*(r+h.when);
147150
r = m*(r+h.freq);
148151
return r;
149152
}

library/modules/EventManager.cpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,25 @@ static int32_t eventLastTick[EventType::EVENT_MAX];
6767

6868
static const int32_t ticksPerYear = 403200;
6969

70+
// this function is only used within the file in registerListener and manageTickEvent
71+
void enqueueTickEvent(EventHandler &handler){
72+
int32_t when = 0;
73+
df::world* world = df::global::world;
74+
if ( world ) {
75+
when = world->frame_counter + handler.freq;
76+
} else {
77+
if ( Once::doOnce("EventManager registerListener unhonored absolute=false") )
78+
Core::getInstance().getConsole().print("EventManager::registerTick: warning! absolute flag=false not honored.\n");
79+
}
80+
handler.when = when;
81+
tickQueue.emplace(handler.when, handler);
82+
}
83+
7084
void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin) {
7185
DEBUG(log).print("registering handler %p from plugin %s for event %d\n", handler.eventHandler, plugin->getName().c_str(), e);
86+
if(e == EventType::TICK){
87+
enqueueTickEvent(handler);
88+
}
7289
handlers[e].insert(pair<Plugin*, EventHandler>(plugin, handler));
7390
}
7491

@@ -82,10 +99,12 @@ int32_t DFHack::EventManager::registerTick(EventHandler handler, int32_t when, P
8299
Core::getInstance().getConsole().print("EventManager::registerTick: warning! absolute flag=false not honored.\n");
83100
}
84101
}
85-
handler.freq = when;
86-
tickQueue.insert(pair<int32_t, EventHandler>(handler.freq, handler));
87102
DEBUG(log).print("registering handler %p from plugin %s for event TICK\n", handler.eventHandler, plugin->getName().c_str());
88-
handlers[EventType::TICK].insert(pair<Plugin*,EventHandler>(plugin,handler));
103+
handler.when = when;
104+
tickQueue.insert(pair<int32_t, EventHandler>(handler.when, handler));
105+
// we don't track this handler, this allows registerTick to retain the old behaviour of needing to re-register the tick event
106+
//handlers[EventType::TICK].insert(pair<Plugin*,EventHandler>(plugin,handler));
107+
// since the event isn't added to the handlers, we don't need to unregister these events
89108
return when;
90109
}
91110

@@ -393,29 +412,23 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
393412
static void manageTickEvent(color_ostream& out) {
394413
if (!df::global::world)
395414
return;
396-
unordered_set<EventHandler> toRemove;
415+
unordered_set<EventHandler> toRequeue;
397416
int32_t tick = df::global::world->frame_counter;
398417
while ( !tickQueue.empty() ) {
399-
if ( tick < (*tickQueue.begin()).first )
418+
auto iter = tickQueue.begin();
419+
if ( tick < iter->first )
400420
break;
401-
EventHandler &handle = (*tickQueue.begin()).second;
402-
tickQueue.erase(tickQueue.begin());
421+
EventHandler &handle = iter->second;
422+
tickQueue.erase(iter);
403423
DEBUG(log,out).print("calling handler for tick event\n");
404424
handle.eventHandler(out, (void*)intptr_t(tick));
405-
toRemove.insert(handle);
425+
toRequeue.emplace(handle);
406426
}
407-
if ( toRemove.empty() )
427+
if ( toRequeue.empty() )
408428
return;
409-
for ( auto a = handlers[EventType::TICK].begin(); a != handlers[EventType::TICK].end(); ) {
410-
EventHandler &handle = (*a).second;
411-
if ( toRemove.find(handle) == toRemove.end() ) {
412-
a++;
413-
continue;
414-
}
415-
a = handlers[EventType::TICK].erase(a);
416-
toRemove.erase(handle);
417-
if ( toRemove.empty() )
418-
break;
429+
for (auto pair : handlers[EventType::TICK]) {
430+
EventHandler &handler = pair.second;
431+
enqueueTickEvent(handler);
419432
}
420433
}
421434

0 commit comments

Comments
 (0)