Hooks and threads

Hello.

I have been wondering for a while about what script hooks are thread safe and what are not.

I know for example that from void ScriptedAI::UpdateAI(uint32 diff) it is not safe to modify (and access) a global std::map as then multiple creatures on different maps could access the map at the same time.

For just accessing it could be safe as it is said(?) that a map is safe to go through if it is not modified, but not if edited in multithreaded environment.

When one is making a script or contemplating on how the system works, there is no information about what is thread safe and what is not.

A thought was first that the creature AI hooks would not be safe to be used, as they are (all?) processed on map update, which is done for different maps simultaneously.

But this fell as I noticed that OnPlayerKilledByCreature hook triggers on kill. This means that it is likely also processed on map update.

Obviously any function /can/ be called at will, but the base structure is unclear.

Is there any base idea/structure?

Would this be needed to considered individually for each hook?

Does anyone know / have an idea about what hooks are executed in safe environment and what are not?

I believe thread safety among custom scripts is most likely lacking a lot in many cases.

ps. just realized this should be in TrinityCore Code Discussion

afaik if you use the basic script hooks, you will never have to modify any worldobject wich is not on the same map so its in the same thread

But what about if I want to collect data.

Lets say I have a global map that stores some random data from the player on each hook call - lets say login.

Or lets say I would need to access players on other maps and do something to them. Let say I buff everyone when the player kills Illidan Stormrage.

In these situations I would be using the basic script hooks and still run into problems if things are not handled in same thread and or have locking.

Locking is likely not an option in the second case.

Very many custom scripts store data for players in a global map and there are many other ways to mess around.

The reason I was asking in first place.

Thanks for reply anyways :3

I think this problem can be somewhat alleviated if we forbid storing WorldObject* in scripts, i.e, replace all Creature*, Player*, etc by their guids and when you actually need a WO* use the guid accessors “in-place”.

well, if you really need a global storage, simply do it in a singleton class (no idea how is it named in boost)

ACE example:

#define sObjectMgr ACE_Singleton<ObjectMgr, ACE_Null_Mutex>::instance()

all operations going thru the manager are safe, you can simple write a data store class with some accessor functions…

class datastore{

map<…>data

*** GetData(return data[x]

}

#define sDataStore …

then you can call sDataStore->GetData from anywhere in a safe way

ofc this is for ACE

I thought that was not safe (with null mutex) and thus the mutex locks were implemented on the hash tables in object accessor but guess that was wrong assumption.

Anyways, the question was more about the current structure, not about a workaround.

So currently I guess the answer is that the safe and unsafe hooks are mixed.