0

我在对象的数据一致性方面遇到问题,例如如何处理在用户仍然引用它们时被删除的对象。

简单的伪代码示例

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")
    /*....*/

是否有任何我可以定义的函数在每次使用时在节点对象上运行,我可以检查它是否仍然有效?

我希望这些信息足以理解我的问题,...感谢阅读!

塞布

4

1 回答 1

0

正如Node所公开的那样boost::shared_ptr,实例的生命周期可能会受到 C++ 和 Python 的影响。Node只要持有boost::shared_ptr存在的 Python 对象的句柄, Python 就会使 C++对象保持活动状态。

Node因此,在下面的代码中,让我们从一个名为spam的前提条件开始graph。代码使用 C++Node实例以及 PythonNode实例的引用计数进行注释。

# 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()

请注意Node' 的析构函数仅在 Python 不再具有该对象的句柄时才被调用。

于 2013-09-24T20:34:15.257 回答