#include "legoomni.h" #include "mxautolocker.h" #include "mxcore.h" #include "mxnotificationmanager.h" #include "mxparam.h" #include "mxtypes.h" #include "compat.h" #include "decomp.h" DECOMP_SIZE_ASSERT(MxNotification, 0x8); DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40); // OFFSET: LEGO1 0x100ac220 MxNotification::MxNotification(MxCore *p_target, MxParam *p_param) { m_target = p_target; m_param = p_param->Clone(); } // OFFSET: LEGO1 0x100ac240 MxNotification::~MxNotification() { delete m_param; } // OFFSET: LEGO1 0x100ac250 MxNotificationManager::MxNotificationManager() : MxCore(), m_lock(), m_listenerIds() { m_unk2c = 0; m_queue = NULL; m_active = TRUE; m_sendList = NULL; } // OFFSET: LEGO1 0x100ac450 MxNotificationManager::~MxNotificationManager() { MxAutoLocker lock(&m_lock); Tickle(); delete m_queue; m_queue = NULL; TickleManager()->Unregister(this); } // OFFSET: LEGO1 0x100ac800 MxResult MxNotificationManager::Tickle() { m_sendList = new MxNotificationPtrList(); if (m_sendList == NULL) { return FAILURE; } else { { MxAutoLocker lock(&m_lock); swap(m_queue, m_sendList); } while (m_sendList->size() != 0) { MxNotification *notif = m_sendList->front(); m_sendList->pop_front(); notif->GetTarget()->Notify(*notif->GetParam()); delete notif; } delete m_sendList; m_sendList = NULL; return SUCCESS; } } // OFFSET: LEGO1 0x100ac600 MxResult MxNotificationManager::Create(MxS32 p_unk1, MxS32 p_unk2) { MxResult result = SUCCESS; m_queue = new MxNotificationPtrList(); if (m_queue == NULL) { result = FAILURE; } else { TickleManager()->Register(this, 10); } return result; } // OFFSET: LEGO1 0x100acd20 void MxNotificationManager::Register(MxCore *p_listener) { MxAutoLocker lock(&m_lock); MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); if (it != m_listenerIds.end()) return; m_listenerIds.push_back(p_listener->GetId()); } // OFFSET: LEGO1 0x100acdf0 void MxNotificationManager::Unregister(MxCore *p_listener) { MxAutoLocker lock(&m_lock); MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); if (it != m_listenerIds.end()) { m_listenerIds.erase(it); FlushPending(p_listener); } } // OFFSET: LEGO1 0x100ac990 void MxNotificationManager::FlushPending(MxCore *p_listener) { MxNotificationPtrList pending; MxNotification *notif; { MxAutoLocker lock(&m_lock); // Find all notifications from, and addressed to, p_listener. if (m_sendList != NULL) { MxNotificationPtrList::iterator it = m_sendList->begin(); while (it != m_sendList->end()) { notif = *it; if ((notif->GetTarget()->GetId() == p_listener->GetId()) || (notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { m_sendList->erase(it++); pending.push_back(notif); } else { it++; } } } MxNotificationPtrList::iterator it = m_queue->begin(); while (it != m_queue->end()) { notif = *it; if ((notif->GetTarget()->GetId() == p_listener->GetId()) || (notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { m_queue->erase(it++); pending.push_back(notif); } else { it++; } } } // Deliver those notifications. while (pending.size() != 0) { notif = pending.front(); pending.pop_front(); notif->GetTarget()->Notify(*notif->GetParam()); delete notif; } } // OFFSET: LEGO1 0x100ac6c0 MxResult MxNotificationManager::Send(MxCore *p_listener, MxParam *p_param) { MxAutoLocker lock(&m_lock); if (m_active == FALSE) { return FAILURE; } else { MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); if (it == m_listenerIds.end()) { return FAILURE; } else { MxNotification *notif = new MxNotification(p_listener, p_param); if (notif != NULL) { m_queue->push_back(notif); return SUCCESS; } } } return FAILURE; }