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 7608 : IntrusivePtrRef() : boost::intrusive_ptr<D>(), referrer_(NULL) { 24 7608 : } 25 : 26 2713 : IntrusivePtrRef(D *data) : boost::intrusive_ptr<D>(data), referrer_(NULL) { 27 2713 : if (data) { 28 3 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer_, this), data); 29 : } 30 2713 : } 31 : 32 23953 : IntrusivePtrRef(D *data, void *referrer) : boost::intrusive_ptr<D>(data), 33 23953 : referrer_(referrer) { 34 23953 : if (data) { 35 2371 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer, this), data); 36 : } 37 23953 : } 38 : 39 236 : IntrusivePtrRef(IntrusivePtrRef const &rhs, void *referrer) 40 236 : : boost::intrusive_ptr<D>(rhs), referrer_(referrer) { 41 236 : if (this->get()) { 42 0 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer, this), 43 0 : this->get()); 44 : } 45 236 : } 46 : 47 37005 : virtual ~IntrusivePtrRef() { 48 37005 : if (this->get()) { 49 4547 : intrusive_ptr_del_back_ref(IntrusiveReferrer(referrer_, this), this->get()); 50 : } 51 74010 : } 52 : 53 202 : IntrusivePtrRef & operator=(IntrusivePtrRef const &rhs) { 54 202 : IntrusivePtrRef(rhs, this).swap(*this); 55 202 : return *this; 56 : } 57 : 58 936 : IntrusivePtrRef & operator=(D *rhs) { 59 936 : IntrusivePtrRef(rhs, this).swap(*this); 60 936 : return *this; 61 : } 62 : 63 10 : void reset() { 64 10 : IntrusivePtrRef(NULL, this).swap(*this); 65 10 : } 66 : 67 37 : void reset(D *rhs) { 68 37 : IntrusivePtrRef(rhs, this).swap(*this); 69 37 : } 70 : 71 1185 : void swap(IntrusivePtrRef &rhs) { 72 : // Trigger Base class swap to swap values 73 1185 : boost::intrusive_ptr<D>::swap(rhs); 74 : 75 : // swap the referrer for this and rhs 76 1185 : D *tmp = this->get(); 77 1185 : if (tmp) { 78 : // change referrer for new value of IntrusivePtrRef 79 367 : intrusive_ptr_add_back_ref(IntrusiveReferrer(referrer_, this), tmp); 80 367 : intrusive_ptr_del_back_ref(IntrusiveReferrer(rhs.referrer_, &rhs), tmp); 81 : } 82 1185 : tmp = rhs.get(); 83 1185 : if (tmp) { 84 : // change referrer for new value of rhs 85 570 : intrusive_ptr_add_back_ref(IntrusiveReferrer(rhs.referrer_, &rhs), tmp); 86 570 : intrusive_ptr_del_back_ref(IntrusiveReferrer(referrer_, this), tmp); 87 : } 88 1185 : } 89 : 90 : private: 91 : void *referrer_; 92 : }; 93 : 94 : #endif // SRC_BASE_INTRUSIVE_PTR_BACK_REF_H_