我遇到了对象的数据一致性问题,例如如何处理在用户仍然引用它们时被删除的对象。
简单的伪代码示例
node = graph.getNode(name)
node.destroy() < -- node gets destroyed
#or
graph.destroyNode(name)
node.getName() #<-- should complain that we're trying to reference an object that does not exist any more
一个简单的伪代码示例是
struct Node
{
/*...*/
};
typedef boost::shared_ptr<Node> NodePtr;
struct Graph
{
std::map<std::string,NodePtr> nodeMap;
NodePtr getNode(std::string name);
void removeNode(std::string name);
/*...*/
};
typedef boost::shared_ptr<Graph> GraphPtr;
// wrapper arround the the getNode function
object Graph_getNode( object obj, const std::string& key )
{
GraphPtr graphPtr = extract< GraphPtr >(obj);
return boost::python::api::object(graphPtr->getNode(key));
};
class_< Node,boost::noncopyable, NodePtr >( "Node", "node", no_init )
/*....*/
class_< Graph, bases<Node>, boost::noncopyable, GraphPtr >( "Graph", "graph", no_init )
.def("getNode", Graph_getNode, "get a node if it exists")
/*....*/
我是否可以定义哪些函数在每次使用时都在Node-object上运行,我可以检查它是否仍然有效?
我希望这些信息足以理解我的问题, ...感谢阅读!
的Seb
答案 0 :(得分:0)
当Node
被boost::shared_ptr
公开时,实例的生命周期可能会受到C ++和Python的影响。只要存在Node
的Python对象的句柄,Python就会使C ++ boost::shared_ptr
对象保持活动状态。
因此,在以下代码中,让我们从Node
中保存名为spam
graph
的前提条件开始。代码注释了C ++ Node
实例的引用计数,以及Python Node
实例。
# The node named 'spam' is held in
# graph's nodeMap.
# cpp count: 1; python count: 0
# Boost.Python creats a Python Node object
# that holds boost::shared_ptr<Node>.
node = graph.getNode('spam') # cpp count: 2; python count: 1
# Removes the boost::shared_ptr<Node> for
# 'spam' from graph.nodeMap.
graph.destroyNode('spam') # cpp count: 1; python count: 1
# The C++ Node is still alive because the
# Python Node holds a boost::shared_ptr<Node>
node.getName() # cpp count: 1; python count: 1
# When Python no longer has a handle to the
# Python Node object, it will be garbage
# collected, which in turn will destroy
# the held boost::shared_ptr<Node>
node = None # cpp count: 0; python count: 0
如果node.getName()
无法在已销毁的node
上成功运行,请考虑明确管理状态。例如,node.destroy()
将在node
内设置状态,成员函数将在执行操作之前检查状态。如果状态指示node
已被销毁,则引发异常或正确处理它。
以下是演示生命周期的基本示例:
#include <map>
#include <string>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
class Node
{
public:
Node(std::string name)
: name_(name)
{
std::cout << "Node()" << std::endl;
}
~Node()
{
std::cout << "~Node()" << std::endl;
}
std::string name() { return name_; }
private:
std::string name_;
};
class Graph
{
public:
// @brief Add node by name.
void add_node(std::string name)
{
nodes_.insert(make_pair(name, boost::make_shared<Node>(name)));
}
/// @brief Destroy node by name.
void destroy_node(std::string name)
{
nodes_.erase(name);
}
// @brief Get node by name.
boost::shared_ptr<Node> get_node(std::string name)
{
nodes_type::iterator result = nodes_.find(name);
return (result != nodes_.end())
? result->second
: boost::shared_ptr<Node>();
}
private:
typedef std::map<std::string, boost::shared_ptr<Node> > nodes_type;
nodes_type nodes_;
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<Node, boost::shared_ptr<Node>,
boost::noncopyable>("Node", python::no_init)
.def("name", &Node::name)
;
python::class_<Graph, boost::noncopyable>("Graph")
.def("add_node", &Graph::add_node)
.def("get_node", &Graph::get_node)
.def("destroy_node", &Graph::destroy_node)
;
}
它在Python中的用法:
>>> from example import Graph
>>> graph = Graph()
>>> graph.add_node('spam')
Node()
>>> node = graph.get_node('spam')
>>> print node.name()
spam
>>> graph.destroy_node('spam')
>>> print node.name()
spam
>>> graph = None
>>> node = None
~Node()
注意只有在Python不再拥有对象句柄时才会调用Node
的析构函数。