Line data Source code
1 : /* 2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef SRC_BASE_INTRUSIVE_PTR_BACK_REF_H_ 6 : #define SRC_BASE_INTRUSIVE_PTR_BACK_REF_H_ 7 : 8 : #include <boost/intrusive_ptr.hpp> 9 : 10 : // IntrusivePtrRef Class is an extension to boost::intrusive_ptr 11 : // to provide additional functionality of making back reference 12 : // pointer available with callbacks intrusive_ptr_add_back_ref 13 : // and intrusive_ptr_del_back_ref, using which application using 14 : // IntrusivePtrRef can keep track of pointers who holds references 15 : // to the object 16 : 17 : // referrer, pair of base pointer and member pointer 18 : typedef std::pair<void*, void*> IntrusiveReferrer; 19 : 20 : template <class D> 21 : class IntrusivePtrRef : public boost::intrusive_ptr<D> { 22 : public: 23 1032 : IntrusivePtrRef() : boost::intrusive_ptr<D>(), referrer_(NULL) { 24 1032 : } 25 : 26 433 : IntrusivePtrRef(D *data) : boost::intrusive_ptr<D>(data), referrer_(NULL) { 27 433 : if (data) { 28 1 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer_, this), data); 29 : } 30 433 : } 31 : 32 3662 : IntrusivePtrRef(D *data, void *referrer) : boost::intrusive_ptr<D>(data), 33 3662 : referrer_(referrer) { 34 3662 : if (data) { 35 280 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer, this), data); 36 : } 37 3662 : } 38 : 39 34 : IntrusivePtrRef(IntrusivePtrRef const &rhs, void *referrer) 40 34 : : boost::intrusive_ptr<D>(rhs), referrer_(referrer) { 41 34 : if (this->get()) { 42 0 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer, this), 43 0 : this->get()); 44 : } 45 34 : } 46 : 47 5483 : virtual ~IntrusivePtrRef() { 48 5483 : if (this->get()) { 49 566 : intrusive_ptr_del_back_ref(IntrusiveReferrer(referrer_, this), this->get()); 50 : } 51 10966 : } 52 : 53 30 : IntrusivePtrRef & operator=(IntrusivePtrRef const &rhs) { 54 30 : IntrusivePtrRef(rhs, this).swap(*this); 55 30 : return *this; 56 : } 57 : 58 124 : IntrusivePtrRef & operator=(D *rhs) { 59 124 : IntrusivePtrRef(rhs, this).swap(*this); 60 124 : return *this; 61 : } 62 : 63 0 : void reset() { 64 0 : IntrusivePtrRef(NULL, this).swap(*this); 65 0 : } 66 : 67 13 : void reset(D *rhs) { 68 13 : IntrusivePtrRef(rhs, this).swap(*this); 69 13 : } 70 : 71 167 : void swap(IntrusivePtrRef &rhs) { 72 : // Trigger Base class swap to swap values 73 167 : boost::intrusive_ptr<D>::swap(rhs); 74 : 75 : // swap the referrer for this and rhs 76 167 : D *tmp = this->get(); 77 167 : if (tmp) { 78 : // change referrer for new value of IntrusivePtrRef 79 48 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer_, this), tmp); 80 48 : intrusive_ptr_del_back_ref(IntrusiveReferrer(rhs.referrer_, &rhs), tmp); 81 : } 82 167 : tmp = rhs.get(); 83 167 : if (tmp) { 84 : // change referrer for new value of rhs 85 79 : intrusive_ptr_add_back_ref(IntrusiveReferrer(rhs.referrer_, &rhs), tmp); 86 79 : intrusive_ptr_del_back_ref(IntrusiveReferrer(referrer_, this), tmp); 87 : } 88 167 : } 89 : 90 : private: 91 : void *referrer_; 92 : }; 93 : 94 : #endif // SRC_BASE_INTRUSIVE_PTR_BACK_REF_H_