| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- // ================================================================================
- // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
- // == See tb_core.h for more information. ==
- // ================================================================================
- #include "tb_msg.h"
- #include "tb_system.h"
- #include <stddef.h>
- namespace tb {
- /** List of all delayed messages */
- TBLinkListOf<TBMessageLink> g_all_delayed_messages;
- /** List of all nondelayed messages. */
- TBLinkListOf<TBMessageLink> g_all_normal_messages;
- // == TBMessage =========================================================================
- TBMessage::TBMessage(TBID message, TBMessageData *data, double fire_time_ms, TBMessageHandler *mh)
- : message(message), data(data), fire_time_ms(fire_time_ms), mh(mh)
- {
- }
- TBMessage::~TBMessage()
- {
- delete data;
- }
- // == TBMessageHandler ==================================================================
- TBMessageHandler::TBMessageHandler()
- {
- }
- TBMessageHandler::~TBMessageHandler()
- {
- DeleteAllMessages();
- }
- bool TBMessageHandler::PostMessageDelayed(TBID message, TBMessageData *data, uint32 delay_in_ms)
- {
- return PostMessageOnTime(message, data, TBSystem::GetTimeMS() + (double)delay_in_ms);
- }
- bool TBMessageHandler::PostMessageOnTime(TBID message, TBMessageData *data, double fire_time)
- {
- if (TBMessage *msg = new TBMessage(message, data, fire_time, this))
- {
- // Find the message that is already in the list that should fire later, so we can
- // insert msg just before that. (Always keep the list ordered after fire time)
- // NOTE: If another message is added during OnMessageReceived, it might or might not be fired
- // in the right order compared to other delayed messages, depending on if it's inserted before or
- // after the message being processed!
- TBMessage *later_msg = nullptr;
- TBMessageLink *link = g_all_delayed_messages.GetFirst();
- while (link)
- {
- TBMessage *msg_in_list = static_cast<TBMessage*>(link);
- if (msg_in_list->fire_time_ms > msg->fire_time_ms)
- {
- later_msg = msg_in_list;
- break;
- }
- link = link->GetNext();
- }
- // Add it to the global list in the right order.
- if (later_msg)
- g_all_delayed_messages.AddBefore(msg, later_msg);
- else
- g_all_delayed_messages.AddLast(msg);
- // Add it to the list in messagehandler.
- m_messages.AddLast(msg);
- // If we added it first and there's no normal messages, the next fire time has
- // changed and we have to reschedule the timer.
- if (!g_all_normal_messages.GetFirst() && g_all_delayed_messages.GetFirst() == msg)
- TBSystem::RescheduleTimer(msg->fire_time_ms);
- return true;
- }
- return false;
- }
- bool TBMessageHandler::PostMessage(TBID message, TBMessageData *data)
- {
- if (TBMessage *msg = new TBMessage(message, data, 0, this))
- {
- g_all_normal_messages.AddLast(msg);
- m_messages.AddLast(msg);
- // If we added it and there was no messages, the next fire time has
- // changed and we have to rescedule the timer.
- if (g_all_normal_messages.GetFirst() == msg)
- TBSystem::RescheduleTimer(0);
- return true;
- }
- return false;
- }
- TBMessage *TBMessageHandler::GetMessageByID(TBID message)
- {
- TBLinkListOf<TBMessage>::Iterator iter = m_messages.IterateForward();
- while (TBMessage *msg = iter.GetAndStep())
- if (msg->message == message)
- return msg;
- return nullptr;
- }
- void TBMessageHandler::DeleteMessage(TBMessage *msg)
- {
- assert(msg->mh == this); // This is not the message handler owning the message!
- // Remove from global list (g_all_delayed_messages or g_all_normal_messages)
- if (g_all_delayed_messages.ContainsLink(msg))
- g_all_delayed_messages.Remove(msg);
- else if (g_all_normal_messages.ContainsLink(msg))
- g_all_normal_messages.Remove(msg);
- // Remove from local list
- m_messages.Remove(msg);
- delete msg;
- // Note: We could call TBSystem::RescheduleTimer if we think that deleting
- // this message changed the time for the next message.
- }
- void TBMessageHandler::DeleteAllMessages()
- {
- while (TBMessage *msg = m_messages.GetFirst())
- DeleteMessage(msg);
- }
- //static
- void TBMessageHandler::ProcessMessages()
- {
- // Handle delayed messages
- TBLinkListOf<TBMessageLink>::Iterator iter = g_all_delayed_messages.IterateForward();
- while (TBMessage *msg = static_cast<TBMessage*>(iter.GetAndStep()))
- {
- if (TBSystem::GetTimeMS() >= msg->fire_time_ms)
- {
- // Remove from global list
- g_all_delayed_messages.Remove(msg);
- // Remove from local list
- msg->mh->m_messages.Remove(msg);
- msg->mh->OnMessageReceived(msg);
- delete msg;
- }
- else
- break; // Since the list is sorted, all remaining messages should fire later
- }
- // Handle normal messages
- iter = g_all_normal_messages.IterateForward();
- while (TBMessage *msg = static_cast<TBMessage*>(iter.GetAndStep()))
- {
- // Remove from global list
- g_all_normal_messages.Remove(msg);
- // Remove from local list
- msg->mh->m_messages.Remove(msg);
- msg->mh->OnMessageReceived(msg);
- delete msg;
- }
- }
- //static
- double TBMessageHandler::GetNextMessageFireTime()
- {
- if (g_all_normal_messages.GetFirst())
- return 0;
- if (g_all_delayed_messages.GetFirst())
- {
- TBMessage *first_delayed_msg = static_cast<TBMessage*>(g_all_delayed_messages.GetFirst());
- return first_delayed_msg->fire_time_ms;
- }
- return TB_NOT_SOON;
- }
- }; // namespace tb
|