-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix scheduler leaks #4882
base: master
Are you sure you want to change the base?
Fix scheduler leaks #4882
Conversation
@@ -634,11 +634,11 @@ void Game::playerMoveThing(uint32_t playerId, const Position& fromPos, uint16_t | |||
} | |||
|
|||
if (movingCreature->getPosition().isInRange(player->getPosition(), 1, 1, 0)) { | |||
SchedulerTask* task = createSchedulerTask( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe in these situations we should use auto
, because it doesn't even matter what the type is here, we just pass it along. Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or just move the creation directly to method call, then we can let the compiler do its best thing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::move shouldnt be needed there, but yeah, might be true, it doesnt look the best
This is really neat, we should do more of that. I'd love to help more but valgrind borked on my machine and won't run :( |
Thanks, you can help by doing a review :) |
class SchedulerTask : public Task | ||
{ | ||
public: | ||
SchedulerTask(uint32_t delay, TaskFunc&& f) : Task(std::forward<TaskFunc>(f)), delay(delay) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
must become public to give abllity to call c-tor by make_unique from SchedulerTask_ptr createSchedulerTask(uint32_t delay, TaskFunc&& f)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could use a friend class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Friend is here but somehow it's not compile :<
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem is make_unique becouse it has no access to private c-tor of SchedulerTask class
there is no way to use something like as friend:
template <typename... Args> Friend std::unique_ptr<SchedulerTask> std::make_unique(Args&&... args);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
friend
sucks, just make it public
Btw, wouldn't it be dangerous to use |
{ | ||
if (walkTaskEvent != 0) { | ||
g_scheduler.stopEvent(walkTaskEvent); | ||
walkTaskEvent = 0; | ||
} | ||
|
||
delete walkTask; | ||
walkTask = task; | ||
walkTask = std::move(task); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe if you use
walkTask = std::move(task); | |
std::swap(walkTask, task); |
You may skip one deletion. This is absolutely minor, change it only if you touch this code again 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? deletion will be moved to end of the scope
@@ -3469,8 +3468,7 @@ void Player::onWalkAborted() | |||
void Player::onWalkComplete() | |||
{ | |||
if (walkTask) { | |||
walkTaskEvent = g_scheduler.addEvent(walkTask); | |||
walkTask = nullptr; | |||
walkTaskEvent = g_scheduler.addEvent(std::move(walkTask)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prone to use-after-move, you still need walkTask = nullptr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your suggestion is good, good capture, I was thinking about this:
walkTaskEvent = g_scheduler.addEvent(SchedulerTask_ptr(walkTask.release()));
However, I am not convinced about having to build a new unique_ptr, although it should be free, I don't know how profitable it is.
The option to assign nullptr is correct and I like it
I recall reading that this behaviour isn't explicitly predictable to be always nullified. There is no guarantee, so it's not safe to assume, but maybe that wasn't for unique ptr. |
It is better not to assume anything and do things as safely as possible. |
Nice, so this is one of the few use-after-move situations that are defined 😆 good to go |
yes, this is one of the few cases where it is defined in the standard |
Pull Request Prelude
Changes Proposed
Fix scheduler memory leaks
Issues addressed:
#4288
How to test:
Requirements: Linux