开发者

Is there a boost::weak_intrusive_pointer?

For legacy reasons I need to use intrusive pointers, as I need the ability to convert raw pointers to smart pointers.

However I noticed there is no weak intrusive pointer for boost. I did find a talk about it on the b开发者_开发技巧oost thread list, however nothing concrete.

Does anyone know of a thread safe implementation of weak intrusive pointer?

Thanks Rich


It does not make any sense.

To elaborate: weak_ptr points to the same instance of a counter object that shared_ptr do. When the shared_ptr goes out of scope, the instance of the counter stays (with a count effectively at 0), which allows the weak_ptr instances to check that they effectively point to a freed object.

With Intrusive Counting, the counter is integrated within the object. When the count reaches 0, the object is usually either recycled or deleted... but the point is the counter is no longer available. The rationale is that this allow for a more efficient storage (1 single chunk) and greater speed (cache locality).

If you need Weak Reference counting and do not care for the benefits of intrusive counting, you can use a combination of shared_ptr and weak_ptr.

The idea is to deassociate the counter from the objects.

class Counted
{
  // bla
private:
  boost::shared_ptr<int> mCounter;
};

Now you can return weak handles:

class WeakHandle
{
public:
  explicit WeakHandle(Counted& c): mCounter(c.mCounter), mObject(&c) {}

  bool expired() const { return mCounter.expired(); }

private:
  boost::weak_ptr<int> mCounter;
  Counted* mObject;
};

Here, we deassociate the lifetime of the counter from the lifetime of the object, so that it will survive the destruction of the object... partially. Thus making the weak_ptr effectively possible.

And of course, using shared_ptr and weak_ptr this is Thread Safe ;)


I didn't really like either of the previous answers so:

No, I don't know of an implementation, but I think it is possible. The standard implementation of the shared_ptr holds two reference counts, one for the "strong" and one for the "weak" references, and a pointer to the referent. In an intrusive_ptr implementation the strong count needs to be part of the object, but the weak can't be. So, it seems like you could create a "weakable" intrusive_ptr.

Define a weak pointer helper:

template<class X>
class intrusive_ptr_weak_helper {
    long weak_ref_count;
    X *target_instance;
};

Then record that into the object beside the reference count:

struct X {
    ...
    intrusive_ptr_weak_helper *ref_weak_helper;
    ...
    long ref_count;
    ...
};

When constructing X:

ref_count = 0;
ref_weak_helper = NULL;

The "strong" pointer, intrusive_strong_ptr, is identical to intrusive_ptr, until deletion occurs. When the strong ref count goes to zero (before deletion occurs):

if (ref_weak_helper != NULL) {
    if (ref_weak_helper->weak_ref_count == 0)
        delete ref_weak_helper;
    else
        ref_weak_helper->target_instance = NULL;
}

The "weak" version, intrusive_weak_ptr, records the pointer to the weak helper, manipulating that reference count, and accessing the target object via the target_instance pointer. When the weak_ref_count decrements to zero the status of target_instance determines whether the helper is deleted or not.

There are many details missing (concurrency concerns for instance) but this is a mixing of the shared_ptr and the intrusive_ptr. It maintains the basic benefits of the intrusive_ptr (cache optimization, reuse of 3rd party intrusive (strong) ref count, strong and weak pointer stand-ins are pointer sized) while adding extra work mainly in the weak reference path.


Current implementation of intrusive pointer is using reference counter. So deleting object delete also delete the counter, so weak_intrusive_pointer will never know that the object was deleted.

If you need to get weak_ptr from this, you probably search boost::enable_shared_from_this<T>.


OpenSceneGraph and its successor, VulkanSceneGraph, each have comprehensive implementations of intrusive strong pointers and associated weak pointers, named ref_ptr<> and observer_ptr<>, respectively.

I don't know every detail of these systems, but it seems they work using an additional object which is informed when the referent (a descendant of the class Referenced) is deleted. Weak pointers use this third object when an attempt is made to convert them to strong pointers.

VulkanSceneGraph is the next generation scene graph that is currently in development and intended to replace OpenSceneGraph, so I assume its intrusive pointer system is a more advanced implementation.

Worth checking out:

https://github.com/vsg-dev/VulkanSceneGraph/blob/master/include/vsg/core/observer_ptr.h

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜