eraseInterpreters(interpreters_.begin(), interpreters_.end());
}
+prefix_ void senf::detail::PacketImpl::release()
+{
+ SENF_ASSERT(refcount_ >= 1, "Internal failure: Releasing dead PacketImpl ??");
+ // uah ... we need to be extremely careful here. If refcount_ is 1, we want to commit suicide,
+ // however the destructor will remove all PacketInterpreters from the list and will thereby
+ // decrement refcount -> only decrement refcount_ when *not* calling delete (otherwise
+ // the assert above will fail)
+ if (refcount_ == 1)
+ delete this;
+ else
+ -- refcount_;
+}
+
// interpreter chain
prefix_ void senf::detail::PacketImpl::appendInterpreter(PacketInterpreterBase * p)
// reference/memory management
-prefix_ void senf::detail::PacketImpl::add_ref(refcount_t n)
+prefix_ void senf::detail::PacketImpl::add_ref()
{
- refcount_ += n;
+ ++ refcount_;
}
prefix_ senf::detail::PacketImpl::refcount_t senf::detail::PacketImpl::refcount()
return data_.capacity();
}
-// This function has a problem being inlined. Somehow, often when calling this, the size of the
-// resulting inlined code would be huge?
-
-prefix_ void senf::detail::PacketImpl::release(refcount_t n)
-{
- SENF_ASSERT(refcount_ >= n, "Internal failure: Releasing dead PacketImpl ??");
- // uah ... we need to be extremely careful here. If refcount_ is n, we want to commit suicide,
- // however the destructor will remove all PacketInterpreters from the list and will thereby
- // decrement refcount -> only decrement refcount_ when *not* calling delete
- if (refcount_ == n)
- delete this;
- else
- refcount_ -= n;
-}
-
// Annotations
prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_type key)
// rerference/memory management
- void add_ref(refcount_t n=1);
- void release(refcount_t n=1);
+ void add_ref();
+ void release();
refcount_t refcount() const;
// Interpreter chain
// refcount ..
- p->add_ref(2);
- BOOST_CHECK_EQUAL(p->refcount(), 3);
- p->release(2);
+ p->add_ref();
+ BOOST_CHECK_EQUAL(p->refcount(), 2);
+ p->release();
BOOST_CHECK_EQUAL(p->refcount(), 1);
{
senf::pool_alloc_mixin< senf::PacketInterpreter<VoidPacket> >::allocCounter(), 1u);
#endif
senf::PacketInterpreterBase::ptr pi2 (pi);
- BOOST_CHECK_EQUAL(p->refcount(), 3);
+ BOOST_CHECK_EQUAL(p->refcount(), 2);
}
BOOST_CHECK_EQUAL(p->refcount(),1);
finalizeThis();
}
+// reference/memory management
+
+prefix_ void senf::PacketInterpreterBase::add_ref()
+{
+ if (impl_ && !refcount())
+ impl_->add_ref();
+ intrusive_refcount_t<PacketInterpreterBase>::add_ref();
+}
+
+prefix_ bool senf::PacketInterpreterBase::release()
+{
+ if (impl_ && refcount()==1)
+ // This call will set impl_ to 0 if we just removed the last reference ...
+ impl_->release();
+ if (intrusive_refcount_t<PacketInterpreterBase>::release() && !impl_)
+ delete this;
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::PacketInterpreterBase::Factory
////////////////////////////////////////
// private members
-// reference/memory management
-
-prefix_ void senf::PacketInterpreterBase::add_ref()
-{
- intrusive_refcount_t<PacketInterpreterBase>::add_ref();
- if (impl_)
- impl_->add_ref();
-}
-
-prefix_ bool senf::PacketInterpreterBase::release()
-{
- if (impl_)
- // This call will set impl_ to 0 if we just removed the last reference ...
- impl_->release();
- return intrusive_refcount_t<PacketInterpreterBase>::release() && !impl_;
-}
-
// containment management. Only to be called by PacketImpl.
prefix_ void senf::PacketInterpreterBase::assignImpl(detail::PacketImpl * impl)
{
SENF_ASSERT(!impl_, "Internal failure: PacketInterpreter added to two Packets");
impl_ = impl;
- impl_->add_ref(refcount());
+ if (refcount())
+ impl_->add_ref();
}
prefix_ void senf::PacketInterpreterBase::releaseImpl()
{
SENF_ASSERT(impl_, "Internal failure: release of lone PacketInterpreter");
- refcount_t refc (refcount());
- if (refc) {
- impl_->release(refc);
+ if (refcount()) {
+ detail::PacketImpl * i (impl_);
impl_ = 0;
+ // This call might delete this ...
+ i->release();
} else {
impl_ = 0;
delete this;
}
}
+prefix_ void senf::intrusive_ptr_add_ref(PacketInterpreterBase const * p)
+{
+ if (! p->refcount())
+ const_cast<PacketInterpreterBase *>(p)->add_ref();
+ else
+ const_cast<PacketInterpreterBase *>(p)->intrusive_refcount_base::add_ref();
+}
+
+prefix_ void senf::intrusive_ptr_release(PacketInterpreterBase const * p)
+{
+ if (p->refcount() <= 1)
+ const_cast<PacketInterpreterBase *>(p)->release();
+ else
+ const_cast<PacketInterpreterBase *>(p)->intrusive_refcount_base::release();
+}
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
template <class PacketType> friend class PacketInterpreter;
friend class detail::packet::test::TestDriver;
friend class PacketParserBase;
+
+ friend void senf::intrusive_ptr_add_ref(PacketInterpreterBase const *);
+ friend void senf::intrusive_ptr_release(PacketInterpreterBase const *);
};
+ void intrusive_ptr_add_ref(PacketInterpreterBase const * p);
+ void intrusive_ptr_release(PacketInterpreterBase const * p);
+
/** \brief Internal: Concrete packet interpreter
\internal
///////////////////////////////cci.p///////////////////////////////////////
prefix_ senf::intrusive_refcount_base::refcount_t senf::intrusive_refcount_base::refcount()
+ const
{
return refcount_;
}
prefix_ bool senf::intrusive_refcount_base::is_shared()
+ const
{
return refcount()>1;
}
virtual ~intrusive_refcount_base();
- refcount_t refcount(); ///< current refcount
- bool is_shared(); ///< return \c true if refcount() > 1
+ refcount_t refcount() const; ///< current refcount
+ bool is_shared() const; ///< return \c true if refcount() > 1
protected:
intrusive_refcount_base();