Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Portable hack to leak raw pointer from weak_ptr

I have object structure which is made of shared_ptrs, plus weak_ptrs to avoid circularity. Raw pointers are a no-go as boost::serialization needs to restore shared and weak pointers when deserializing via object tracking as serialization time. Object lifetime patterns are complex (particle simulation) but entirely predictable. Whenever I use weak_ptr::lock(), I am sure the pointer is still valid. Typically, I use lock().get() as I only need the object for a very short time.

Now, lock().get() has performance implications, as it will increment shared count (in lock()), and then decrement it shortly afterwards (the temporary shared_ptr is destructed).

This boost.devel post from 2002 says that while weak_ptr was being developed, the functionality of accessing the raw pointer directly was considered (to be named unsafe_get or leak) but never made it to the actual implementation. Its absence forces programmer to use suboptimal interface under given conditions.

Now, the question is how to emulate the unsafe_get/leak, in another words, get the raw pointer from weak_ptr, invalid at the programmer's risk, only reading (not writing) data. I can imagine that some trickery like finding out the offset of the raw pointer inside shared_ptr or such would do the job.

I am using boost::shared_ptr, but the solution could work for c++11's std::shared_ptr as well.

like image 753
eudoxos Avatar asked Nov 06 '14 09:11

eudoxos


2 Answers

Since you asked for a portable hack.

A funny part of code found in boost's weak_ptr.hpp is:

template<class T> class weak_ptr
{
  ...

public:

  ...

// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)

#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS

private:

    template<class Y> friend class weak_ptr;
    template<class Y> friend class shared_ptr;

#endif

    element_type * px;            // contained pointer
    boost::detail::weak_count pn; // reference counter

};  // weak_ptr

Which means if you compile boost with the BOOST_NO_MEMBER_TEMPLATE_FRIENDS option, you will publicly have access to the member px of weak_ptr which seems to be a raw pointer to the element type.

like image 198
Drax Avatar answered Sep 23 '22 03:09

Drax


I suggest you simply hold both a weak_ptr and a raw pointer and use the raw pointer directly as an optimization when you know it is safe to do so. You could wrap up the weak_ptr and associated raw pointer in a class that has an unsafe_get if you like.

like image 45
Chris Drew Avatar answered Sep 22 '22 03:09

Chris Drew