Otclient  14/8/2020
eventdispatcher.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #include "eventdispatcher.h"
24 
25 #include <framework/core/clock.h>
26 #include "timer.h"
27 
29 
31 {
32  while(!m_eventList.empty())
33  poll();
34 
35  while(!m_scheduledEventList.empty()) {
36  ScheduledEventPtr scheduledEvent = m_scheduledEventList.top();
37  scheduledEvent->cancel();
38  m_scheduledEventList.pop();
39  }
40  m_disabled = true;
41 }
42 
44 {
45  int loops = 0;
46  for(int count = 0, max = m_scheduledEventList.size(); count < max && !m_scheduledEventList.empty(); ++count) {
47  ScheduledEventPtr scheduledEvent = m_scheduledEventList.top();
48  if(scheduledEvent->remainingTicks() > 0)
49  break;
50  m_scheduledEventList.pop();
51  scheduledEvent->execute();
52 
53  if(scheduledEvent->nextCycle())
54  m_scheduledEventList.push(scheduledEvent);
55  }
56 
57  // execute events list until all events are out, this is needed because some events can schedule new events that would
58  // change the UIWidgets layout, in this case we must execute these new events before we continue rendering,
59  m_pollEventsSize = m_eventList.size();
60  loops = 0;
61  while(m_pollEventsSize > 0) {
62  if(loops > 50) {
63  static Timer reportTimer;
64  if(reportTimer.running() && reportTimer.ticksElapsed() > 100) {
65  g_logger.error("ATTENTION the event list is not getting empty, this could be caused by some bad code");
66  reportTimer.restart();
67  }
68  break;
69  }
70 
71  for(int i=0;i<m_pollEventsSize;++i) {
72  EventPtr event = m_eventList.front();
73  m_eventList.pop_front();
74  event->execute();
75  }
76  m_pollEventsSize = m_eventList.size();
77 
78  loops++;
79  }
80 }
81 
82 ScheduledEventPtr EventDispatcher::scheduleEvent(const std::function<void()>& callback, int delay)
83 {
84  if(m_disabled)
85  return ScheduledEventPtr(new ScheduledEvent(nullptr, delay, 1));
86 
87  assert(delay >= 0);
88  ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay, 1));
89  m_scheduledEventList.push(scheduledEvent);
90  return scheduledEvent;
91 }
92 
93 ScheduledEventPtr EventDispatcher::cycleEvent(const std::function<void()>& callback, int delay)
94 {
95  if(m_disabled)
96  return ScheduledEventPtr(new ScheduledEvent(nullptr, delay, 0));
97 
98  assert(delay > 0);
99  ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay, 0));
100  m_scheduledEventList.push(scheduledEvent);
101  return scheduledEvent;
102 }
103 
104 EventPtr EventDispatcher::addEvent(const std::function<void()>& callback, bool pushFront)
105 {
106  if(m_disabled)
107  return EventPtr(new Event(nullptr));
108 
109  EventPtr event(new Event(callback));
110  // front pushing is a way to execute an event before others
111  if(pushFront) {
112  m_eventList.push_front(event);
113  // the poll event list only grows when pushing into front
114  m_pollEventsSize++;
115  } else
116  m_eventList.push_back(event);
117  return event;
118 }
119 
eventdispatcher.h
ScheduledEvent::remainingTicks
int remainingTicks()
Definition: scheduledevent.h:38
ScheduledEvent::execute
void execute()
Definition: scheduledevent.cpp:33
Timer::ticksElapsed
ticks_t ticksElapsed()
Definition: timer.cpp:33
g_dispatcher
EventDispatcher g_dispatcher
Definition: eventdispatcher.cpp:28
Logger::error
void error(const std::string &what)
Definition: logger.h:54
EventPtr
stdext::shared_object_ptr< Event > EventPtr
Definition: declarations.h:41
clock.h
Event
Definition: event.h:29
EventDispatcher::cycleEvent
ScheduledEventPtr cycleEvent(const std::function< void()> &callback, int delay)
Definition: eventdispatcher.cpp:93
g_logger
Logger g_logger
Definition: logger.cpp:35
timer.h
ScheduledEvent::nextCycle
bool nextCycle()
Definition: scheduledevent.cpp:47
EventDispatcher::addEvent
EventPtr addEvent(const std::function< void()> &callback, bool pushFront=false)
Definition: eventdispatcher.cpp:104
EventDispatcher
Definition: eventdispatcher.h:32
Timer::restart
void restart()
Definition: timer.cpp:27
Timer::running
bool running()
Definition: timer.h:40
EventDispatcher::poll
void poll()
Definition: eventdispatcher.cpp:43
EventDispatcher::shutdown
void shutdown()
Definition: eventdispatcher.cpp:30
stdext::shared_object_ptr< ScheduledEvent >
ScheduledEvent
Definition: scheduledevent.h:30
Timer
Definition: timer.h:28
ScheduledEventPtr
stdext::shared_object_ptr< ScheduledEvent > ScheduledEventPtr
Definition: declarations.h:42
EventDispatcher::scheduleEvent
ScheduledEventPtr scheduleEvent(const std::function< void()> &callback, int delay)
Definition: eventdispatcher.cpp:82
Event::cancel
void cancel()
Definition: event.cpp:49