Skip to content

Commit

Permalink
perf: onThink multithreading (opentibiabr#3075)
Browse files Browse the repository at this point in the history
  • Loading branch information
mehah authored Dec 9, 2024
1 parent dec87cb commit e325965
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 25 deletions.
3 changes: 2 additions & 1 deletion src/creatures/creature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,8 @@ class Creature : virtual public Thing, public SharedObject {
AsyncTaskRunning = 1 << 0,
UpdateTargetList = 1 << 1,
UpdateIdleStatus = 1 << 2,
Pathfinder = 1 << 3
Pathfinder = 1 << 3,
OnThink = 1 << 4,
};

virtual bool isDead() const {
Expand Down
40 changes: 18 additions & 22 deletions src/creatures/monsters/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,27 +423,13 @@ void Monster::onCreatureMove(const std::shared_ptr<Creature> &creature, const st
if (const auto &nextTile = g_game().map.getTile(checkPosition)) {
const auto &topCreature = nextTile->getTopCreature();
if (followCreature != topCreature && isOpponent(topCreature)) {
g_dispatcher().addEvent([selfWeak = std::weak_ptr(getMonster()), topCreatureWeak = std::weak_ptr(topCreature)] {
const auto &self = selfWeak.lock();
const auto &topCreature = topCreatureWeak.lock();
if (self && topCreature) {
self->selectTarget(topCreature);
}
},
"Monster::onCreatureMove");
selectTarget(topCreature);
}
}
}
} else if (isOpponent(creature)) {
// we have no target lets try pick this one
g_dispatcher().addEvent([selfWeak = std::weak_ptr(getMonster()), creatureWeak = std::weak_ptr(creature)] {
const auto &self = selfWeak.lock();
const auto &creaturePtr = creatureWeak.lock();
if (self && creaturePtr) {
self->selectTarget(creaturePtr);
}
},
"Monster::onCreatureMove");
selectTarget(creature);
}
}
};
Expand Down Expand Up @@ -978,7 +964,7 @@ void Monster::setIdle(bool idle) {
}

void Monster::updateIdleStatus() {
if (g_dispatcher().context().getGroup() == TaskGroup::Walk) {
if (!g_dispatcher().context().isAsync()) {
setAsyncTaskFlag(UpdateIdleStatus, true);
return;
}
Expand Down Expand Up @@ -1073,8 +1059,11 @@ void Monster::onThink(uint32_t interval) {
}

updateIdleStatus();
setAsyncTaskFlag(OnThink, true);
}

if (isIdle) {
void Monster::onThink_async() {
if (isIdle) { // updateIdleStatus(); is executed before this method
return;
}

Expand Down Expand Up @@ -1109,10 +1098,13 @@ void Monster::onThink(uint32_t interval) {
}
}

onThinkTarget(interval);
onThinkYell(interval);
onThinkDefense(interval);
onThinkSound(interval);
onThinkTarget(EVENT_CREATURE_THINK_INTERVAL);

safeCall([this] {
onThinkYell(EVENT_CREATURE_THINK_INTERVAL);
onThinkDefense(EVENT_CREATURE_THINK_INTERVAL);
onThinkSound(EVENT_CREATURE_THINK_INTERVAL);
});
}

void Monster::doAttacking(uint32_t interval) {
Expand Down Expand Up @@ -2661,4 +2653,8 @@ void Monster::onExecuteAsyncTasks() {
if (hasAsyncTaskFlag(UpdateIdleStatus)) {
updateIdleStatus();
}

if (hasAsyncTaskFlag(OnThink)) {
onThink_async();
}
}
2 changes: 2 additions & 0 deletions src/creatures/monsters/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ class Monster final : public Creature {
void onExecuteAsyncTasks() override;

private:
void onThink_async();

auto getTargetIterator(const std::shared_ptr<Creature> &creature) {
return std::ranges::find_if(targetList.begin(), targetList.end(), [id = creature->getID()](const std::weak_ptr<Creature> &ref) {
const auto &target = ref.lock();
Expand Down
14 changes: 12 additions & 2 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6457,8 +6457,18 @@ void Game::checkCreatures() {
if (const auto creature = weak.lock()) {
if (creature->creatureCheck && creature->isAlive()) {
creature->onThink(EVENT_CREATURE_THINK_INTERVAL);
creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL);
creature->executeConditions(EVENT_CREATURE_THINK_INTERVAL);
if (creature->getMonster()) {
// The monster's onThink is executed asynchronously,
// so the target is updated later, so we need to postpone the actions below.
g_dispatcher().addEvent([creature] {
if (creature->isAlive()) {
creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL);
creature->executeConditions(EVENT_CREATURE_THINK_INTERVAL);
} }, __FUNCTION__);
} else {
creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL);
creature->executeConditions(EVENT_CREATURE_THINK_INTERVAL);
}
return false;
}

Expand Down

0 comments on commit e325965

Please sign in to comment.