# # # add_file "intrusive_ptr.hh" # content [fab77279c4bd359d34092b0386576cfe7a274ac2] # # patch "database.cc" # from [45a853c398d98224ff998f8769cf4dcbbb0a7d40] # to [c6ab3d8eaef1299724b739a97b07ffb1d3a3cb7b] # # patch "pcrewrap.hh" # from [bcb9af0ef76ffbf353ee409ba9f071971584e157] # to [fb737d8451af1743d4f880a1488c23a59107a481] # # patch "unit-tests/xdelta.cc" # from [a0183bed5c69963c3a39531792657ba3b97b763b] # to [f3ed971854fb0b36336c9628a550f97dbacfc2b8] # # patch "xdelta.cc" # from [5094e62fb1c7881a0b8da6331f2fc7488a342146] # to [7bb0ace9b1deb1fff95ac7aca6a95514d48a09e3] # # patch "xdelta.hh" # from [59ad94776aa99040452c7f678b9c642ccbb29ec0] # to [8b260b196ba13de6bc65c166cc235890c40cc5b7] # ============================================================ --- intrusive_ptr.hh fab77279c4bd359d34092b0386576cfe7a274ac2 +++ intrusive_ptr.hh fab77279c4bd359d34092b0386576cfe7a274ac2 @@ -0,0 +1,52 @@ +// Copyright (C) 2009 Zack Weinberg +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#ifndef __INTRUSIVE_PTR_HH__ +#define __INTRUSIVE_PTR_HH__ + +#include +#include "sanity.hh" + +// By convention, intrusively reference-counted objects should have a +// private member of type intrusive_refcnt_t, named "refcnt", and be +// friends with these functions. Since monotone is single-threaded, +// we do not worry about locking. + +typedef long intrusive_refcnt_t; + +template inline void intrusive_ptr_add_ref(T * ptr) +{ + ptr->refcnt++; + I(ptr->refcnt > 0); +} + +template inline void intrusive_ptr_release(T * ptr) +{ + ptr->refcnt--; + I(ptr->refcnt >= 0); + if (ptr->refcnt == 0) + delete ptr; +} + +// This base class takes care of the above conventions for you. +// Note that intrusive_ptr_add_ref/release still need to be template +// functions, as one must apply delete to a pointer with the true type +// of the object. + +class intrusively_refcounted +{ + intrusive_refcnt_t refcnt; + // sadly, no way to say "any subclass of this" + template friend void intrusive_ptr_add_ref(T *); + template friend void intrusive_ptr_release(T *); +public: + intrusively_refcounted() : refcnt(0) {} +}; + +#endif // intrusive_ptr.hh ============================================================ --- database.cc 45a853c398d98224ff998f8769cf4dcbbb0a7d40 +++ database.cc c6ab3d8eaef1299724b739a97b07ffb1d3a3cb7b @@ -86,6 +86,7 @@ using std::accumulate; using std::vector; using std::accumulate; +using boost::intrusive_ptr; using boost::shared_ptr; using boost::shared_dynamic_cast; using boost::lexical_cast; @@ -1828,7 +1829,7 @@ database_impl::get_version(id const & id else get_file_or_manifest_base_unchecked(curr, begin, data_table); - shared_ptr appl = new_piecewise_applicator(); + intrusive_ptr appl = new_piecewise_applicator(); appl->begin(begin()); for (reconstruction_path::reverse_iterator i = selected_path.rbegin(); ============================================================ --- pcrewrap.hh bcb9af0ef76ffbf353ee409ba9f071971584e157 +++ pcrewrap.hh fb737d8451af1743d4f880a1488c23a59107a481 @@ -53,8 +53,7 @@ namespace pcre { private: // disable the default and copy constructors - we never need to copy - // these, and this lets us use bare pointers below instead of - // boost::shared_ptr. + // these. This makes it safe to use bare pointers below. regex(); regex(regex const &); regex & operator=(regex const &); ============================================================ --- unit-tests/xdelta.cc a0183bed5c69963c3a39531792657ba3b97b763b +++ unit-tests/xdelta.cc f3ed971854fb0b36336c9628a550f97dbacfc2b8 @@ -21,7 +21,7 @@ using std::string; boost::uniform_smallint xdelta_lengen(1, 256); using std::string; -using boost::shared_ptr; +using boost::intrusive_ptr; UNIT_TEST(basic) { @@ -48,7 +48,7 @@ apply_via_piecewise(string const & base, static string apply_via_piecewise(string const & base, string const & delta) { - shared_ptr appl = new_piecewise_applicator(); + intrusive_ptr appl = new_piecewise_applicator(); appl->begin(base); apply_delta(appl, delta); appl->next(); @@ -170,7 +170,7 @@ UNIT_TEST(random_piecewise_delta) { string prev, next, got; xdelta_random_string(prev); - shared_ptr appl = new_piecewise_applicator(); + intrusive_ptr appl = new_piecewise_applicator(); appl->begin(prev); for (int j = 0; j < 5; ++j) { ============================================================ --- xdelta.cc 5094e62fb1c7881a0b8da6331f2fc7488a342146 +++ xdelta.cc 7bb0ace9b1deb1fff95ac7aca6a95514d48a09e3 @@ -51,6 +51,7 @@ using std::lower_bound; using std::memcmp; using std::lower_bound; +using boost::intrusive_ptr; using boost::shared_ptr; struct identity {size_t operator()(u32 const & v) const { return static_cast(v);}}; @@ -398,7 +399,7 @@ void } void -apply_delta(shared_ptr da, +apply_delta(intrusive_ptr da, string const & delta) { string::const_iterator i = delta.begin(); @@ -444,7 +445,7 @@ apply_delta(string const & a, string const & delta, string & b) { - shared_ptr da(new simple_applicator()); + intrusive_ptr da(new simple_applicator()); da->begin(a); apply_delta(da, delta); da->next(); @@ -695,16 +696,16 @@ piecewise_applicator // these just hide our implementation types from outside -shared_ptr +intrusive_ptr new_simple_applicator() { - return shared_ptr(new simple_applicator()); + return intrusive_ptr(new simple_applicator()); } -shared_ptr +intrusive_ptr new_piecewise_applicator() { - return shared_ptr(new piecewise_applicator()); + return intrusive_ptr(new piecewise_applicator()); } @@ -813,7 +814,8 @@ invert_xdelta(string const & old_str, string const & delta, string & delta_inverse) { - shared_ptr da(new inverse_delta_writing_applicator(old_str)); + intrusive_ptr + da(new inverse_delta_writing_applicator(old_str)); apply_delta(da, delta); da->finish(delta_inverse); } ============================================================ --- xdelta.hh 59ad94776aa99040452c7f678b9c642ccbb29ec0 +++ xdelta.hh 8b260b196ba13de6bc65c166cc235890c40cc5b7 @@ -10,7 +10,7 @@ #ifndef __XDELTA_HH__ #define __XDELTA_HH__ -#include +#include "intrusive_ptr.hh" #include "vocab.hh" void @@ -35,7 +35,7 @@ void patch(data const & olddata, data & newdata); -struct delta_applicator +struct delta_applicator : intrusively_refcounted { virtual ~delta_applicator () {} virtual void begin(std::string const & base) = 0; @@ -46,10 +46,10 @@ struct delta_applicator virtual void insert(std::string const & str) = 0; }; -boost::shared_ptr new_simple_applicator(); -boost::shared_ptr new_piecewise_applicator(); +boost::intrusive_ptr new_simple_applicator(); +boost::intrusive_ptr new_piecewise_applicator(); -void apply_delta(boost::shared_ptr da, +void apply_delta(boost::intrusive_ptr da, std::string const & delta); u64 measure_delta_target_size(std::string const & delta);