std :: list和垃圾收集算法

问题描述 投票:0回答:2

我有一台服务器可以根据要求将2名玩家聚集在一起并在一个新线程中开始游戏Game

struct GInfo {Game* game; std::thread* g_thread};

while  (true) {
    players_pair = matchPlayers();
    Game* game = new Game(players_pair);
    std::thread* game_T = new std::thread(&Game::start, game);
    GInfo ginfo = {game, game_T}
    _actives.push_back(ginfo);    // std::list
}

我正在编写一个“垃圾收集器”,它运行在另一个线程中,以清除已终止游戏的内存。

void garbageCollector() {
    while (true) {
        for (std::list<Ginfo>::iterator it = _actives.begin(); it != _actives.end(); ++it) {
            if (! it->game->isActive()) {
                delete it->game; it->game = nullptr;
                it->g_thread->join();
                delete it->g_thread; it->g_thread = nullptr;
                _actives.erase(it);
            }
        }
        sleep(2);
    }
}

这会产生一个段错误,我怀疑这是因为_active.erase(it)处于迭代循环中。为了排除故障,我使_actives成为std::vector(而不是std::list)并应用相同的算法,但使用索引而不是迭代器,它工作正常。

有没有解决的办法?

是算法,数据结构用得好吗?有没有更好的方法来进行垃圾收集?

感谢帮助!

c++ algorithm list stl garbage-collection
2个回答
1
投票

如果您查看erase方法的文档,它会在删除元素后返回元素的迭代器。

使用它的方法是将返回值分配给迭代器,就像这样。

for (std::list<Ginfo>::iterator it = _actives.begin(); it != _actives.end();) {
    if (! it->game->isActive()) {
        delete it->game; it->game = nullptr;
        it->g_thread->join();
        delete it->g_thread; it->g_thread = nullptr;
        it = _actives.erase(it);
    }
    else {
        ++it;
    }
}

因为从erase中获取返回值会将迭代器提升到下一个元素,所以我们必须确保在发生这种情况时不增加迭代器。

在一个不相关的注释中,以下划线开头的变量名通常保留给编译器的内部,应该在您自己的代码中避免。


0
投票

有没有更好的方法来进行垃圾收集?

是的,不要一起使用new,delete或动态内存:

struct Players{};
struct Game{
    Game(Players&& players){}
};
struct GInfo {
    GInfo(Players&& players_pair):
        game(std::move(players_pair)),g_thread(&Game::start, game){}

    Game game; 
    std::thread g_thread;
};

std::list<GInfo> _actives;

void someLoop()
{
    while  (true) {
        GInfo& ginfo = _actives.emplace_back(matchPlayers());
    }
}

void garbageCollector() {
    while (true) {
        //Since C++20
        //_active.remove_if([](GInfo& i){ return !i.game.isActive();});
        //Until C++20
        auto IT =std::remove_if(_actives.begin(),_actives.end(),
                      [](GInfo& i){ return !i.game.isActive();});
        _active.erase(IT,_active.end());
        //
        sleep(2);
    }
}

可能会有一些拼写错误,但这就是主意。

© www.soinside.com 2019 - 2024. All rights reserved.