Ticket #186: ref-counted-subclassables.patch
File ref-counted-subclassables.patch, 10.8 KB (added by , 12 years ago) |
---|
-
xapian-bindings/perl/perl.i
diff --git a/xapian-bindings/perl/perl.i b/xapian-bindings/perl/perl.i index 1ae61d3..317b515 100644
a b sub set_stopper { 343 343 } 344 344 %} 345 345 346 %feature("shadow") Xapian::QueryParser::add_valuerangeprocessor347 %{348 sub add_valuerangeprocessor {349 my ($self, $vrproc) = @_;350 push @{$self{_vrproc}}, $vrproc;351 Search::Xapianc::QueryParser_add_valuerangeprocessor( @_ );352 }353 %}354 355 346 /* Xapian::SimpleStopper */ 356 347 %feature("shadow") Xapian::SimpleStopper::SimpleStopper 357 348 %{ -
xapian-bindings/python/extra.i
diff --git a/xapian-bindings/python/extra.i b/xapian-bindings/python/extra.i index 0d24f0b..f819924 100644
a b _enquire_get_query.__doc__ = __enquire_get_query_orig.__doc__ 728 728 Enquire.get_query = _enquire_get_query 729 729 del _enquire_get_query 730 730 731 # When we set a ValueRangeProcessor into the QueryParser, keep a python732 # reference so it won't be deleted. This hack can probably be removed once733 # xapian bug #186 is fixed.734 __queryparser_add_valuerangeprocessor_orig = QueryParser.add_valuerangeprocessor735 def _queryparser_add_valuerangeprocessor(self, vrproc):736 if not hasattr(self, '_vrps'):737 self._vrps = []738 self._vrps.append(vrproc)739 return __queryparser_add_valuerangeprocessor_orig(self, vrproc)740 _queryparser_add_valuerangeprocessor.__doc__ = __queryparser_add_valuerangeprocessor_orig.__doc__741 QueryParser.add_valuerangeprocessor = _queryparser_add_valuerangeprocessor742 del _queryparser_add_valuerangeprocessor743 744 731 # When we set a FieldProcessor into the QueryParser, keep a python 745 732 # reference so it won't be deleted. This hack can probably be removed once 746 733 # xapian bug #186 is fixed. -
xapian-bindings/xapian-headers.i
diff --git a/xapian-bindings/xapian-headers.i b/xapian-bindings/xapian-headers.i index 85ec281..9e09d68 100644
a b SUBCLASSABLE(Xapian, KeyMaker) 324 324 SUBCLASSABLE(Xapian, FieldProcessor) 325 325 SUBCLASSABLE(Xapian, Stopper) 326 326 SUBCLASSABLE(Xapian, ValueRangeProcessor) 327 %warnfilter(SWIGWARN_TYPE_UNDEFINED_CLASS) Xapian::ValueRangeProcessor; 328 %feature("ref") Xapian::ValueRangeProcessor "$this->ref();" 329 %feature("unref") Xapian::ValueRangeProcessor "$this->unref();" 327 330 STANDARD_IGNORES(Xapian, QueryParser) 328 331 %ignore Xapian::QueryParser::QueryParser(const QueryParser &); 329 332 %include <xapian/queryparser.h> -
xapian-core/include/xapian/intrusive_ptr.h
diff --git a/xapian-core/include/xapian/intrusive_ptr.h b/xapian-core/include/xapian/intrusive_ptr.h index 4290782..4376897 100644
a b 5 5 // Based on Boost's intrusive_ptr.hpp 6 6 // 7 7 // Copyright (c) 2001, 2002 Peter Dimov 8 // Copyright (c) 2011 Olly Betts8 // Copyright (c) 2011, 2013 Olly Betts 9 9 // 10 10 // Distributed under the Boost Software License, Version 1.0. 11 11 // … … template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const 175 175 return a != b.get(); 176 176 } 177 177 178 /// Base class for objects managed by opt_intrusive_ptr. 179 class opt_intrusive_base : public intrusive_base { 180 public: 181 opt_intrusive_base(const opt_intrusive_base&) : intrusive_base() { } 182 183 opt_intrusive_base& operator=(const opt_intrusive_base&) { 184 // Don't touch _refs. 185 return *this; 186 } 187 188 /** Construct object which is initially not reference counted. 189 * 190 * The reference counting starts if release_() is called. 191 */ 192 opt_intrusive_base() : intrusive_base() { } 193 194 /* Subclasses of opt_intrusive_base may be deleted by calling delete on a 195 * pointer to intrusive_base*. 196 */ 197 virtual ~opt_intrusive_base() { } 198 199 /** Start reference counting. 200 * 201 * The object is constructed with _refs set to 0, meaning it isn't being 202 * reference counted. 203 * 204 * Calling release() sets _refs to 1 if it is 0, and from then 205 * opt_intrusive_ptr will increment and decrement _refs. If it is 206 * decremented to 1, the object is deleted. 207 */ 208 void release() const { 209 if (_refs == 0) 210 _refs = 1; 211 } 212 213 void ref() const { 214 if (_refs == 0) 215 _refs = 2; 216 else 217 ++_refs; 218 } 219 220 void unref() const { 221 if (--_refs == 1) 222 delete this; 223 } 224 }; 225 226 // 227 // opt_intrusive_ptr 228 // 229 230 /// A smart pointer that uses intrusive reference counting. 231 template<class T> class opt_intrusive_ptr 232 { 233 private: 234 235 typedef opt_intrusive_ptr this_type; 236 237 public: 238 239 opt_intrusive_ptr(): px( 0 ) 240 { 241 } 242 243 opt_intrusive_ptr( T * p): px( p ) 244 { 245 if( px != 0 && px->_refs ) ++px->_refs; 246 } 247 248 template<class U> 249 opt_intrusive_ptr( opt_intrusive_ptr<U> const & rhs ) 250 : px( rhs.get() ) 251 { 252 if( px != 0 && px->_refs ) ++px->_refs; 253 } 254 255 opt_intrusive_ptr(opt_intrusive_ptr const & rhs): px( rhs.px ) 256 { 257 if( px != 0 && px->_refs ) ++px->_refs; 258 } 259 260 ~opt_intrusive_ptr() 261 { 262 if( px != 0 && px->_refs && --px->_refs == 1 ) delete px; 263 } 264 265 opt_intrusive_ptr & operator=(opt_intrusive_ptr const & rhs) 266 { 267 this_type(rhs).swap(*this); 268 return *this; 269 } 270 271 opt_intrusive_ptr & operator=(T * rhs) 272 { 273 this_type(rhs).swap(*this); 274 return *this; 275 } 276 277 T * get() const 278 { 279 return px; 280 } 281 282 T & operator*() const 283 { 284 return *px; 285 } 286 287 T * operator->() const 288 { 289 return px; 290 } 291 292 void swap(opt_intrusive_ptr & rhs) 293 { 294 T * tmp = px; 295 px = rhs.px; 296 rhs.px = tmp; 297 } 298 299 private: 300 301 T * px; 302 }; 303 304 template<class T, class U> inline bool operator==(opt_intrusive_ptr<T> const & a, opt_intrusive_ptr<U> const & b) 305 { 306 return a.get() == b.get(); 307 } 308 309 template<class T, class U> inline bool operator!=(opt_intrusive_ptr<T> const & a, opt_intrusive_ptr<U> const & b) 310 { 311 return a.get() != b.get(); 312 } 313 314 template<class T, class U> inline bool operator==(opt_intrusive_ptr<T> const & a, U * b) 315 { 316 return a.get() == b; 317 } 318 319 template<class T, class U> inline bool operator!=(opt_intrusive_ptr<T> const & a, U * b) 320 { 321 return a.get() != b; 322 } 323 324 template<class T, class U> inline bool operator==(T * a, opt_intrusive_ptr<U> const & b) 325 { 326 return a == b.get(); 327 } 328 329 template<class T, class U> inline bool operator!=(T * a, opt_intrusive_ptr<U> const & b) 330 { 331 return a != b.get(); 332 } 333 178 334 } 179 335 } 180 336 -
xapian-core/include/xapian/queryparser.h
diff --git a/xapian-core/include/xapian/queryparser.h b/xapian-core/include/xapian/queryparser.h index 84b5c43..b3b169b 100644
a b 1 1 /** @file queryparser.h 2 2 * @brief parsing a user query string to build a Xapian::Query object 3 3 */ 4 /* Copyright (C) 2005,2006,2007,2008,2009,2010,2011,2012 Olly Betts4 /* Copyright (C) 2005,2006,2007,2008,2009,2010,2011,2012,2013 Olly Betts 5 5 * Copyright (C) 2010 Adam Sjøgren 6 6 * 7 7 * This program is free software; you can redistribute it and/or … … class XAPIAN_VISIBILITY_DEFAULT SimpleStopper : public Stopper { 85 85 }; 86 86 87 87 /// Base class for value range processors. 88 struct XAPIAN_VISIBILITY_DEFAULT ValueRangeProcessor { 88 struct XAPIAN_VISIBILITY_DEFAULT ValueRangeProcessor 89 : public Xapian::Internal::opt_intrusive_base { 89 90 /// Destructor. 90 91 virtual ~ValueRangeProcessor(); 91 92 -
xapian-core/queryparser/queryparser.lemony
diff --git a/xapian-core/queryparser/queryparser.lemony b/xapian-core/queryparser/queryparser.lemony index 8fd3b8c..c02add3 100644
a b 1 1 %include { 2 2 /* queryparser.lemony: build a Xapian::Query object from a user query string. 3 3 * 4 * Copyright (C) 2004,2005,2006,2007,2008,2009,2010,2011,2012 Olly Betts4 * Copyright (C) 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013 Olly Betts 5 5 * Copyright (C) 2007,2008,2009 Lemur Consulting Ltd 6 6 * Copyright (C) 2010 Adam Sjøgren 7 7 * … … class State { 252 252 } 253 253 254 254 Term * value_range(const string &a, const string &b) { 255 list< ValueRangeProcessor *>::const_iterator i;255 list<Xapian::Internal::opt_intrusive_ptr<Xapian::ValueRangeProcessor> >::const_iterator i; 256 256 for (i = qpi->valrangeprocs.begin(); i != qpi->valrangeprocs.end(); ++i) { 257 257 string start = a; 258 258 string end = b; -
xapian-core/queryparser/queryparser_internal.h
diff --git a/xapian-core/queryparser/queryparser_internal.h b/xapian-core/queryparser/queryparser_internal.h index 11da6fc..7e02532 100644
a b 1 1 /** @file queryparser_internal.h 2 2 * @brief The non-lemon-generated parts of the QueryParser class. 3 3 */ 4 /* Copyright (C) 2005,2006,2007,2010,2011,2012 Olly Betts4 /* Copyright (C) 2005,2006,2007,2010,2011,2012,2013 Olly Betts 5 5 * Copyright (C) 2010 Adam Sjøgren 6 6 * 7 7 * This program is free software; you can redistribute it and/or … … class QueryParser::Internal : public Xapian::Internal::intrusive_base { 82 82 // "foobar" -> "XFOO". FIXME: it does more than this now! 83 83 map<string, FieldInfo> field_map; 84 84 85 list< ValueRangeProcessor *> valrangeprocs;85 list<Xapian::Internal::opt_intrusive_ptr<ValueRangeProcessor> > valrangeprocs; 86 86 87 87 string corrected_query; 88 88 -
xapian-core/tests/api_none.cc
diff --git a/xapian-core/tests/api_none.cc b/xapian-core/tests/api_none.cc index 2f4340f..f6e3e7c 100644
a b 2 2 * @brief tests which don't need a backend 3 3 */ 4 4 /* Copyright (C) 2009 Richard Boulton 5 * Copyright (C) 2009,2010,2011 Olly Betts5 * Copyright (C) 2009,2010,2011,2013 Olly Betts 6 6 * 7 7 * This program is free software; you can redistribute it and/or 8 8 * modify it under the terms of the GNU General Public License as … … DEFINE_TESTCASE(combinewqfnomore1, !backend) { 142 142 TEST_EQUAL(q.get_description(), "Query((beer@1 OR beer@1))"); 143 143 return true; 144 144 } 145 146 struct TestValueRangeProcessor : public Xapian::ValueRangeProcessor { 147 bool & destroyed; 148 149 TestValueRangeProcessor(bool & destroyed_) : destroyed(destroyed_) { 150 destroyed = false; 151 } 152 153 ~TestValueRangeProcessor() { 154 destroyed = true; 155 } 156 157 Xapian::valueno operator()(std::string &, std::string &) { 158 return 42; 159 } 160 }; 161 162 /// Check reference counting of user-subclassable classes. 163 DEFINE_TESTCASE(subclassablerefcount1, !backend) { 164 bool gone_auto, gone; 165 { 166 TestValueRangeProcessor vrp_auto(gone_auto); 167 TEST(!gone_auto); 168 { 169 Xapian::QueryParser qp1; 170 { 171 Xapian::QueryParser qp2; 172 Xapian::ValueRangeProcessor * vrp; 173 vrp = new TestValueRangeProcessor(gone); 174 TEST(!gone); 175 vrp->release(); 176 qp1.add_valuerangeprocessor(vrp); 177 TEST(!gone); 178 qp2.add_valuerangeprocessor(vrp); 179 TEST(!gone); 180 qp2.add_valuerangeprocessor(&vrp_auto); 181 TEST(!gone); 182 TEST(!gone_auto); 183 } 184 TEST(!gone); 185 } 186 TEST(gone); 187 TEST(!gone_auto); 188 } 189 TEST(gone_auto); 190 191 return true; 192 }