Eluna fix crash in timed events and prepare some for future changes. Ditched EventProcessor

This commit is contained in:
Rochet2
2014-09-13 16:05:16 +03:00
parent 7be917335a
commit 06be9650bb
12 changed files with 388 additions and 346 deletions

View File

@@ -6,6 +6,7 @@
#include "ElunaEventMgr.h"
#include "LuaEngine.h"
#include "Object.h"
extern "C"
{
@@ -13,139 +14,131 @@ extern "C"
#include "lauxlib.h"
};
LuaEvent::LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj):
E(_E), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls), obj(_obj)
LuaEvent::LuaEvent(ElunaEventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls) :
to_Abort(false), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls)
{
if (_events)
E.m_EventMgr->LuaEvents[_events].insert(this); // Able to access the event if we have the processor
}
LuaEvent::~LuaEvent()
{
if (events)
{
// Attempt to remove the pointer from LuaEvents
EventMgr::EventMap::const_iterator it = E.m_EventMgr->LuaEvents.find(events); // Get event set
if (it != E.m_EventMgr->LuaEvents.end())
E.m_EventMgr->LuaEvents[events].erase(this);// Remove pointer
}
luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref
luaL_unref(sEluna->L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref
}
bool LuaEvent::Execute(uint64 /*time*/, uint32 /*diff*/)
void LuaEvent::Execute()
{
bool remove = (calls == 1);
if (!remove)
events->AddEvent(this, events->CalculateTime(delay)); // Reschedule before calling incase RemoveEvents used
lua_rawgeti(E.L, LUA_REGISTRYINDEX, funcRef);
Eluna::Push(E.L, funcRef);
Eluna::Push(E.L, delay);
Eluna::Push(E.L, calls);
if (!remove && calls)
// In multithread get map from object and the map's lua state
lua_rawgeti(sEluna->L, LUA_REGISTRYINDEX, funcRef);
Eluna::Push(sEluna->L, funcRef);
Eluna::Push(sEluna->L, delay);
Eluna::Push(sEluna->L, calls);
if (calls) // Must be before calling
--calls;
Eluna::Push(E.L, obj);
Eluna::ExecuteCall(E.L, 4, 0);
return remove; // Destory (true) event if not run
Eluna::Push(sEluna->L, events->obj);
Eluna::ExecuteCall(sEluna->L, 4, 0);
}
EventMgr::EventMgr(Eluna& _E): E(_E)
ElunaEventProcessor::ElunaEventProcessor(WorldObject* _obj) : m_time(0), obj(_obj)
{
// In multithread get the object's map's lua state
Eluna* E = obj ? sEluna : sEluna;
EventMgr::WriteGuard lock(E->eventMgr->GetLock());
E->eventMgr->processors.insert(this);
}
ElunaEventProcessor::~ElunaEventProcessor()
{
RemoveEvents();
// In multithread get the object's map's lua state
Eluna* E = obj ? sEluna : sEluna;
EventMgr::WriteGuard lock(E->eventMgr->GetLock());
E->eventMgr->processors.erase(this);
}
void ElunaEventProcessor::Update(uint32 diff)
{
m_time += diff;
for (EventList::iterator it = eventList.begin(); it != eventList.end() && it->first <= m_time; it = eventList.begin())
{
LuaEvent* event = it->second;
eventList.erase(it);
eventMap.erase(event->funcRef);
if (event->to_Abort)
{
delete event;
continue;
}
bool remove = event->calls == 1;
if (!remove)
AddEvent(event); // Reschedule before calling incase RemoveEvents used
event->Execute();
if (remove)
delete event;
}
}
void ElunaEventProcessor::RemoveEvents()
{
//if (!final)
//{
// for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it)
// it->second->to_Abort = true;
// return;
//}
for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it)
delete it->second;
eventList.clear();
eventMap.clear();
}
void ElunaEventProcessor::RemoveEvent(int eventId)
{
if (eventMap.find(eventId) != eventMap.end())
eventMap[eventId]->to_Abort = true;
}
void ElunaEventProcessor::AddEvent(LuaEvent* event)
{
eventList.insert(std::pair<uint64, LuaEvent*>(m_time + event->delay, event));
eventMap[event->funcRef] = event;
}
void ElunaEventProcessor::AddEvent(int funcRef, uint32 delay, uint32 repeats)
{
AddEvent(new LuaEvent(this, funcRef, delay, repeats));
}
EventMgr::EventMgr() : globalProcessor(NULL)
{
}
EventMgr::~EventMgr()
{
RemoveEvents();
delete globalProcessor;
}
void EventMgr::Update(uint32 diff)
{
GlobalEvents.Update(diff);
}
/*
void EventMgr::KillAllEvents(EventProcessor* events)
{
if (!events)
return;
if (LuaEvents.empty())
return;
EventMap::const_iterator it = LuaEvents.find(events); // Get event set
if (it == LuaEvents.end())
return;
if (it->second.empty())
return;
for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end();) // Loop events
(*(itr++))->to_Abort = true; // Abort event
}
*/
void EventMgr::RemoveEvents()
{
if (!LuaEvents.empty())
for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors
(it++)->first->KillAllEvents(false); // KillAllEvents((it++)->first);
LuaEvents.clear(); // remove pointers
// This is handled automatically on delete
// for (ProcessorMap::iterator it = Processors.begin(); it != Processors.end();)
// (it++)->second.KillAllEvents(true);
// Processors.clear(); // remove guid saved processors
GlobalEvents.KillAllEvents(true);
}
void EventMgr::RemoveEvents(EventProcessor* events)
{
if (!events)
return;
// KillAllEvents(events);
events->KillAllEvents(false);
LuaEvents.erase(events); // remove pointer set
}
int EventMgr::AddEvent(EventProcessor* events, int funcRef, uint32 delay, uint32 calls, Object* obj)
{
if (!events || funcRef <= 0) // If funcRef <= 0, function reference failed
return 0; // on fail always return 0. funcRef can be negative.
events->AddEvent(new LuaEvent(E, events, funcRef, delay, calls, obj), events->CalculateTime(delay));
return funcRef; // return the event ID
}
LuaEvent* EventMgr::GetEvent(EventProcessor* events, int eventId)
{
if (!events || !eventId)
return NULL;
if (LuaEvents.empty())
return NULL;
EventMap::const_iterator it = LuaEvents.find(events); // Get event set
if (it == LuaEvents.end())
return NULL;
if (it->second.empty())
return NULL;
for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr) // Loop events
if ((*itr) && (*itr)->funcRef == eventId) // Check if the event has our ID
return *itr; // Return the event if found
return NULL;
}
bool EventMgr::RemoveEvent(EventProcessor* events, int eventId)
{
// eventId = funcRef
if (!events || !eventId)
return false;
LuaEvent* luaEvent = GetEvent(events, eventId);
if (!luaEvent)
return false;
luaEvent->to_Abort = true; // Set to remove on next call
LuaEvents[events].erase(luaEvent); // Remove pointer
return true;
ReadGuard lock(GetLock());
if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvents();
globalProcessor->RemoveEvents();
}
void EventMgr::RemoveEvent(int eventId)
{
if (!eventId)
return;
if (LuaEvents.empty())
return;
for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors
if (RemoveEvent((it++)->first, eventId))
break; // succesfully remove the event, stop loop.
ReadGuard lock(GetLock());
if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvent(eventId);
globalProcessor->RemoveEvent(eventId);
}