boost::asio::io_service::strand不肯走
boost::asio::io_service::strand refuses to go away
我正在使用 strand 在一些 object 中序列化某些处理。然而,当 object 消失时, strand 元素以某种方式拒绝消失。就像炼狱中的灵魂一样,它设法活在内存中,并导致内存使用量随着时间的推移而增加。我已经成功地在示例代码中复制了这个问题。
我正在创建 5 个家庭,每个家庭有一个 parent 和一个 child。 parent object 包含 child 和一个链 object 以确保以串行方式进行处理。每个家庭都被分配了 3 个处理任务,并且它们以正确的顺序执行,而不管它们 运行 在哪个线程上。在 object 创建和处理之前和之后,我正在 VC++ 中拍摄内存堆快照。快照比较显示,即使在 Parent 和 Child object 被销毁后,单独的链仍然存在。
如何确保链 object 被销毁?与示例程序不同,我的应用程序 运行s 多年没有关闭。我将在一个月内陷入数百万个僵尸链object。
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio/strand.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/asio/yield.hpp>
#include <boost/log/attributes/current_thread_id.hpp>
#include <iostream>
boost::mutex mtx;
class Child : public boost::noncopyable, public boost::enable_shared_from_this<Child>
{
int _id;
public:
Child(int id) : _id(id) {}
void process(int order)
{
boost::this_thread::sleep_for(boost::chrono::seconds(2));
boost::lock_guard<boost::mutex> lock(mtx);
std::cout << "Family " << _id << " processing order " << order << " in thread " << std::hex << boost::this_thread::get_id() << std::endl;
}
};
class Parent : public boost::noncopyable, public boost::enable_shared_from_this<Parent>
{
boost::shared_ptr<Child> _child;
boost::asio::io_service::strand _strand;
public:
Parent(boost::asio::io_service& ioS, int id) : _strand(ioS)
{
_child = boost::make_shared<Child>(id);
}
void process()
{
for (int order = 1; order <= 3; order++)
{
_strand.post(boost::bind(&Child::process, _child, order));
}
}
};
int main(int argc, char* argv[])
{
boost::asio::io_service ioS;
boost::thread_group threadPool;
boost::asio::io_service::work work(ioS);
int noOfCores = boost::thread::hardware_concurrency();
for (int i = 0; i < noOfCores; i++)
{
threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioS));
}
std::cout << "Take the first snapshot" << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(10));
std::cout << "Creating families" << std::endl;
for (int family = 1; family <= 5; family++)
{
auto obj = boost::make_shared<Parent>(ioS,family);
obj->process();
}
std::cout << "Take the second snapshot after all orders are processed" << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(60));
return 0;
}
输出如下所示:
Take the first snapshot
Creating families
Take the second snapshot after all orders are processed
Family 3 processing order 1 in thread 50c8
Family 1 processing order 1 in thread 5e38
Family 4 processing order 1 in thread a0c
Family 5 processing order 1 in thread 47e8
Family 2 processing order 1 in thread 5f94
Family 3 processing order 2 in thread 46ac
Family 2 processing order 2 in thread 47e8
Family 5 processing order 2 in thread a0c
Family 1 processing order 2 in thread 50c8
Family 4 processing order 2 in thread 5e38
Family 2 processing order 3 in thread 47e8
Family 4 processing order 3 in thread 5e38
Family 1 processing order 3 in thread 50c8
Family 5 processing order 3 in thread a0c
Family 3 processing order 3 in thread 46ac
我在创建系列之前拍摄了第一个堆快照。在打印完所有 15 行(5 个家庭 X 3 个任务)后几秒钟,我拍摄了第二张快照。堆比较显示如下:
所有的Parent和Childobject都走了,但是所有的5股object都活着在...
编辑:对于那些不理解 shared_ptr 的人,object 不会在循环结束时死掉。由于 child 的引用已传递给 3 个流程任务,因此至少 child 过着迷人的生活,直到完成给定家庭的所有任务。清除所有引用后,Child object 将死亡。
我正在使用 strand 在一些 object 中序列化某些处理。然而,当 object 消失时, strand 元素以某种方式拒绝消失。就像炼狱中的灵魂一样,它设法活在内存中,并导致内存使用量随着时间的推移而增加。我已经成功地在示例代码中复制了这个问题。
我正在创建 5 个家庭,每个家庭有一个 parent 和一个 child。 parent object 包含 child 和一个链 object 以确保以串行方式进行处理。每个家庭都被分配了 3 个处理任务,并且它们以正确的顺序执行,而不管它们 运行 在哪个线程上。在 object 创建和处理之前和之后,我正在 VC++ 中拍摄内存堆快照。快照比较显示,即使在 Parent 和 Child object 被销毁后,单独的链仍然存在。
如何确保链 object 被销毁?与示例程序不同,我的应用程序 运行s 多年没有关闭。我将在一个月内陷入数百万个僵尸链object。
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio/strand.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/asio/yield.hpp>
#include <boost/log/attributes/current_thread_id.hpp>
#include <iostream>
boost::mutex mtx;
class Child : public boost::noncopyable, public boost::enable_shared_from_this<Child>
{
int _id;
public:
Child(int id) : _id(id) {}
void process(int order)
{
boost::this_thread::sleep_for(boost::chrono::seconds(2));
boost::lock_guard<boost::mutex> lock(mtx);
std::cout << "Family " << _id << " processing order " << order << " in thread " << std::hex << boost::this_thread::get_id() << std::endl;
}
};
class Parent : public boost::noncopyable, public boost::enable_shared_from_this<Parent>
{
boost::shared_ptr<Child> _child;
boost::asio::io_service::strand _strand;
public:
Parent(boost::asio::io_service& ioS, int id) : _strand(ioS)
{
_child = boost::make_shared<Child>(id);
}
void process()
{
for (int order = 1; order <= 3; order++)
{
_strand.post(boost::bind(&Child::process, _child, order));
}
}
};
int main(int argc, char* argv[])
{
boost::asio::io_service ioS;
boost::thread_group threadPool;
boost::asio::io_service::work work(ioS);
int noOfCores = boost::thread::hardware_concurrency();
for (int i = 0; i < noOfCores; i++)
{
threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioS));
}
std::cout << "Take the first snapshot" << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(10));
std::cout << "Creating families" << std::endl;
for (int family = 1; family <= 5; family++)
{
auto obj = boost::make_shared<Parent>(ioS,family);
obj->process();
}
std::cout << "Take the second snapshot after all orders are processed" << std::endl;
boost::this_thread::sleep_for(boost::chrono::seconds(60));
return 0;
}
输出如下所示:
Take the first snapshot
Creating families
Take the second snapshot after all orders are processed
Family 3 processing order 1 in thread 50c8
Family 1 processing order 1 in thread 5e38
Family 4 processing order 1 in thread a0c
Family 5 processing order 1 in thread 47e8
Family 2 processing order 1 in thread 5f94
Family 3 processing order 2 in thread 46ac
Family 2 processing order 2 in thread 47e8
Family 5 processing order 2 in thread a0c
Family 1 processing order 2 in thread 50c8
Family 4 processing order 2 in thread 5e38
Family 2 processing order 3 in thread 47e8
Family 4 processing order 3 in thread 5e38
Family 1 processing order 3 in thread 50c8
Family 5 processing order 3 in thread a0c
Family 3 processing order 3 in thread 46ac
我在创建系列之前拍摄了第一个堆快照。在打印完所有 15 行(5 个家庭 X 3 个任务)后几秒钟,我拍摄了第二张快照。堆比较显示如下:
所有的Parent和Childobject都走了,但是所有的5股object都活着在...
编辑:对于那些不理解 shared_ptr 的人,object 不会在循环结束时死掉。由于 child 的引用已传递给 3 个流程任务,因此至少 child 过着迷人的生活,直到完成给定家庭的所有任务。清除所有引用后,Child object 将死亡。