* changed the way how objects are stored. they are now no longer deleted directly, but moved into a *depleted* state. this prevents crashes with already deleted objects accessed by other threads

This commit is contained in:
false_genesis 2008-03-30 23:02:21 +00:00
parent e0a0b7d82d
commit d7ea5fe553
14 changed files with 78 additions and 31 deletions

View File

@ -1016,7 +1016,10 @@ DefReturnResult DefScriptPackage::SCGui(CmdSet &Set)
// TODO: not sure if this piece of code will work as intended, needs some testing
if(ins->GetWSession() && ins->GetWSession()->InWorld())
{
ins->GetGUI()->SetSceneState(SCENESTATE_WORLD);
ins->GetWSession()->objmgr.ReNotifyGUI();
}
else
ins->GetGUI()->SetSceneState(SCENESTATE_GUISTART);

View File

@ -46,6 +46,7 @@ void DrawObjMgr::Update(void)
while(_add.size())
{
std::pair<uint64,DrawObject*> p = _add.next();
DEBUG(logdebug("DrawObjMgr: adding DrawObj 0x%X guid "I64FMT" to main storage",p.second,p.first));
_storage[p.first] = p.second;
}
@ -55,10 +56,16 @@ void DrawObjMgr::Update(void)
uint64 guid = _del.next();
if(_storage.find(guid) != _storage.end())
{
DrawObject *o = _storage[guid];
DEBUG(logdebug("DrawObjMgr: removing DrawObj 0x%X guid "I64FMT" from main storage",o,guid));
_storage.erase(guid);
delete o;
}
else
{
DEBUG(logdebug("DrawObjMgr: ERROR: removable DrawObject "I64FMT" not exising",guid));
}
}
// now draw everything

View File

@ -226,7 +226,7 @@ void PseuGUI::NotifyObjectDeletion(uint64 guid)
// called from ObjMgr::Add(Object*)
void PseuGUI::NotifyObjectCreation(Object *o)
{
DrawObject *d = new DrawObject(_smgr,o);
DrawObject *d = new DrawObject(_device,o);
domgr.Add(o->GetGUID(),d);
}

View File

@ -30,6 +30,16 @@ enum DriverIDs
DIRECTX9 = 5,
};
#define MOUSE_SENSIVITY 0.5f
#define ANGLE_STEP (M_PI/180.0f)
#define DEG_TO_RAD(x) ((x)*ANGLE_STEP)
#define RAD_TO_DEG(x) ((x)/ANGLE_STEP)
#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) )
#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) )
#define COORD_SCALE_VALUE_X 0.336f
#define COORD_SCALE_VALUE_Y 0.2f
class PseuGUIRunnable : public ZThread::Runnable
{
public:

View File

@ -12,18 +12,6 @@
#include "WorldSession.h"
#include "World.h"
#define MOUSE_SENSIVITY 0.5f
#define ANGLE_STEP (M_PI/180)
#define DEG_TO_RAD(x) ((x)*ANGLE_STEP)
#define RAD_TO_DEG(x) ((x)/ANGLE_STEP)
#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) )
#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) )
#define COORD_SCALE_VALUE_X 0.336f
#define COORD_SCALE_VALUE_Y 0.2f
SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
{
DEBUG(logdebug("SceneWorld: Initializing..."));
@ -360,8 +348,8 @@ void SceneWorld::SetWorldPosition(WorldPosition wp)
cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE);
float heading = RAD_TO_DEG(((M_PI*3.0f)/2.0f) - wp.o);
float heading_diff = camera->getHeading() - heading;
logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading);
camera->turnLeft(heading_diff);
//logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading);
//camera->turnLeft(heading_diff);
// TODO:
// - correct the above formulas

View File

@ -1,6 +1,6 @@
#include "DynamicObject.h"
DynamicObject::DynamicObject()
DynamicObject::DynamicObject() : WorldObject()
{
_uint32values=NULL;
_type=TYPE_DYNAMICOBJECT;

View File

@ -1,6 +1,6 @@
#include "GameObject.h"
GameObject::GameObject()
GameObject::GameObject() : WorldObject()
{
_uint32values=NULL;
_type=TYPE_GAMEOBJECT;

View File

@ -114,6 +114,7 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
Item::Item()
{
_depleted = false;
_type |= TYPE_ITEM;
_typeid = TYPEID_ITEM;

View File

@ -32,24 +32,29 @@ void ObjMgr::RemoveAll(void)
}
while(_obj.size())
{
Remove(_obj.begin()->first);
Remove(_obj.begin()->first, true);
}
}
void ObjMgr::Remove(uint64 guid)
void ObjMgr::Remove(uint64 guid, bool del)
{
Object *o = GetObj(guid);
Object *o = GetObj(guid, true); // here get also depleted objs and delete if necessary
if(o)
{
o->_SetDepleted();
PseuGUI *gui = _instance->GetGUI();
if(gui)
gui->NotifyObjectDeletion(guid); // we have a gui, which must delete linked DrawObject
_obj.erase(guid); // now delete the obj from the mgr
delete o; // and delete the obj itself
if(del)
{
_obj.erase(guid); // now delete the obj from the mgr
delete o; // and delete the obj itself
}
}
else
{
_obj.erase(guid);
_obj.erase(guid); // we can safely erase an object that does not exist
// - if we reach this point there was a bug anyway
logcustom(2,LRED,"ObjMgr::Remove("I64FMT") - not existing",guid);
}
}
@ -58,20 +63,29 @@ void ObjMgr::Remove(uint64 guid)
void ObjMgr::Add(Object *o)
{
_obj[o->GetGUID()] = o;
Object *ox = GetObj(o->GetGUID(),true); // if an object already exists in the mgr, store old ptr...
_obj[o->GetGUID()] = o; // ...assign new one...
if(ox) // and if != NULL, delete the old object (completely, from memory)
{
Remove(ox->GetGUID(),true);
}
PseuGUI *gui = _instance->GetGUI();
if(gui)
gui->NotifyObjectCreation(o);
}
Object *ObjMgr::GetObj(uint64 guid)
Object *ObjMgr::GetObj(uint64 guid, bool also_depleted)
{
if(!guid)
return NULL;
for(ObjectMap::iterator i = _obj.begin(); i!=_obj.end(); i++)
if(i->second->GetGUID() == guid)
{
if(i->second->_IsDepleted() && !also_depleted)
return NULL;
return i->second;
}
return NULL;
}
@ -90,6 +104,22 @@ uint32 ObjMgr::AssignNameToObj(uint32 entry, uint8 type, std::string name)
return changed;
}
void ObjMgr::ReNotifyGUI(void)
{
PseuGUI *gui = _instance->GetGUI();
if(!gui)
return;
for(ObjectMap::iterator it = _obj.begin(); it != _obj.end(); it++)
{
Object *o = it->second;
if(o->_IsDepleted())
continue;
gui->NotifyObjectCreation(o);
}
}
// -- Item part --
void ObjMgr::Add(ItemProto *proto)

View File

@ -49,10 +49,11 @@ public:
// Object functions
void Add(Object*);
void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway)
Object *GetObj(uint64 guid);
void Remove(uint64 guid, bool del); // remove all objects with that guid (should be only 1 object in total anyway)
Object *GetObj(uint64 guid, bool also_depleted = false);
inline uint32 GetObjectCount(void) { return _obj.size(); }
uint32 AssignNameToObj(uint32 entry, uint8 type, std::string name);
void ReNotifyGUI(void);
private:
ItemProtoMap _iproto;

View File

@ -5,6 +5,7 @@
Object::Object()
{
_depleted = false;
_uint32values=NULL;
_type=TYPE_OBJECT;
_typeid=TYPEID_OBJECT;
@ -39,6 +40,7 @@ void Object::Create( uint64 guid )
WorldObject::WorldObject()
{
_depleted = false;
_m = 0;
}
@ -121,7 +123,7 @@ void WorldSession::_HandleDestroyObjectOpcode(WorldPacket& recvPacket)
GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set);
}
objmgr.Remove(guid);
objmgr.Remove(guid, false);
}

View File

@ -92,6 +92,8 @@ public:
}
void Create(uint64 guid);
inline bool _IsDepleted(void) { return _depleted; }
inline void _SetDepleted(void) { _depleted = true; }
protected:
Object();
@ -106,6 +108,7 @@ protected:
uint8 _type;
uint8 _typeid;
std::string _name;
bool _depleted : 1; // true if the object was deleted from the objmgr, but not from memory
};
class WorldObject : public Object

View File

@ -86,7 +86,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
if(uguid != GetGuid())
{
logdev("- already exists, deleting old, creating new object");
objmgr.Remove(uguid);
objmgr.Remove(uguid, false);
// do not call script here, since the object does not really get deleted
}
else
@ -128,6 +128,8 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
}
case TYPEID_PLAYER:
{
if(GetGuid() == uguid) // objmgr.Add() would cause quite some trouble if we added ourself again
break;
Player *player = new Player();
player->Create(uguid);
objmgr.Add(player);
@ -201,7 +203,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set);
}
objmgr.Remove(uguid);
objmgr.Remove(uguid, false);
}
}
break;

View File

@ -597,8 +597,8 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
// that means even if the server sends create object with that guid, do NOT recreate it!!
MyCharacter *my = new MyCharacter();
my->Create(_myGUID);
objmgr.Add(my);
my->SetName(plr[charId]._name);
objmgr.Add(my);
// TODO: initialize the world here, and load required maps.
// must remove appropriate code from _HandleLoginVerifyWorldOpcode() then!!