stable_vector.hpp 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. // Stable vector.
  11. //
  12. // Copyright 2008 Joaquin M Lopez Munoz.
  13. // Distributed under the Boost Software License, Version 1.0.
  14. // (See accompanying file LICENSE_1_0.txt or copy at
  15. // http://www.boost.org/LICENSE_1_0.txt)
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
  19. #define BOOST_CONTAINER_STABLE_VECTOR_HPP
  20. #if defined(_MSC_VER)
  21. # pragma once
  22. #endif
  23. #include <boost/container/detail/config_begin.hpp>
  24. #include <boost/container/detail/workaround.hpp>
  25. #include <boost/container/container_fwd.hpp>
  26. #include <boost/mpl/bool.hpp>
  27. #include <boost/mpl/not.hpp>
  28. #include <boost/assert.hpp>
  29. #include <boost/container/throw_exception.hpp>
  30. #include <boost/container/detail/allocator_version_traits.hpp>
  31. #include <boost/container/detail/utilities.hpp>
  32. #include <boost/container/detail/iterators.hpp>
  33. #include <boost/container/detail/algorithms.hpp>
  34. #include <boost/container/allocator_traits.hpp>
  35. #include <boost/container/throw_exception.hpp>
  36. #include <boost/intrusive/pointer_traits.hpp>
  37. #include <boost/detail/no_exceptions_support.hpp>
  38. #include <boost/aligned_storage.hpp>
  39. #include <boost/move/utility.hpp>
  40. #include <boost/move/iterator.hpp>
  41. #include <boost/move/detail/move_helpers.hpp>
  42. #include <algorithm> //max
  43. #include <memory>
  44. #include <new> //placement new
  45. ///@cond
  46. #include <boost/container/vector.hpp>
  47. //#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
  48. ///@endcond
  49. namespace boost {
  50. namespace container {
  51. ///@cond
  52. namespace stable_vector_detail{
  53. template <class C>
  54. class clear_on_destroy
  55. {
  56. public:
  57. clear_on_destroy(C &c)
  58. : c_(c), do_clear_(true)
  59. {}
  60. void release()
  61. { do_clear_ = false; }
  62. ~clear_on_destroy()
  63. {
  64. if(do_clear_){
  65. c_.clear();
  66. c_.priv_clear_pool();
  67. }
  68. }
  69. private:
  70. clear_on_destroy(const clear_on_destroy &);
  71. clear_on_destroy &operator=(const clear_on_destroy &);
  72. C &c_;
  73. bool do_clear_;
  74. };
  75. template<typename Pointer>
  76. struct node;
  77. template<class VoidPtr>
  78. struct node_base
  79. {
  80. private:
  81. typedef typename boost::intrusive::
  82. pointer_traits<VoidPtr> void_ptr_traits;
  83. typedef typename void_ptr_traits::
  84. template rebind_pointer
  85. <node_base>::type node_base_ptr;
  86. typedef typename void_ptr_traits::
  87. template rebind_pointer
  88. <node_base_ptr>::type node_base_ptr_ptr;
  89. public:
  90. node_base(const node_base_ptr_ptr &n)
  91. : up(n)
  92. {}
  93. node_base()
  94. : up()
  95. {}
  96. node_base_ptr_ptr up;
  97. };
  98. template<typename Pointer>
  99. struct node
  100. : public node_base
  101. <typename ::boost::intrusive::pointer_traits<Pointer>::template
  102. rebind_pointer<void>::type
  103. >
  104. {
  105. // private:
  106. // node();
  107. public:
  108. typename ::boost::intrusive::pointer_traits<Pointer>::element_type value;
  109. };
  110. template<typename Pointer, bool IsConst>
  111. class iterator
  112. {
  113. typedef boost::intrusive::pointer_traits<Pointer> non_const_ptr_traits;
  114. public:
  115. typedef std::random_access_iterator_tag iterator_category;
  116. typedef typename non_const_ptr_traits::element_type value_type;
  117. typedef typename non_const_ptr_traits::difference_type difference_type;
  118. typedef typename ::boost::container::container_detail::if_c
  119. < IsConst
  120. , typename non_const_ptr_traits::template
  121. rebind_pointer<const value_type>::type
  122. , Pointer
  123. >::type pointer;
  124. typedef typename ::boost::container::container_detail::if_c
  125. < IsConst
  126. , const value_type&
  127. , value_type&
  128. >::type reference;
  129. private:
  130. typedef typename non_const_ptr_traits::template
  131. rebind_pointer<void>::type void_ptr;
  132. typedef node<Pointer> node_type;
  133. typedef node_base<void_ptr> node_base_type;
  134. typedef typename non_const_ptr_traits::template
  135. rebind_pointer<node_type>::type node_ptr;
  136. typedef boost::intrusive::
  137. pointer_traits<node_ptr> node_ptr_traits;
  138. typedef typename non_const_ptr_traits::template
  139. rebind_pointer<node_base_type>::type node_base_ptr;
  140. typedef typename non_const_ptr_traits::template
  141. rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
  142. node_ptr m_pn;
  143. public:
  144. explicit iterator(node_ptr p) BOOST_CONTAINER_NOEXCEPT
  145. : m_pn(p)
  146. {}
  147. iterator() BOOST_CONTAINER_NOEXCEPT
  148. {}
  149. iterator(iterator<Pointer, false> const& other) BOOST_CONTAINER_NOEXCEPT
  150. : m_pn(other.node_pointer())
  151. {}
  152. node_ptr &node_pointer() BOOST_CONTAINER_NOEXCEPT
  153. { return m_pn; }
  154. const node_ptr &node_pointer() const BOOST_CONTAINER_NOEXCEPT
  155. { return m_pn; }
  156. public:
  157. //Pointer like operators
  158. reference operator*() const BOOST_CONTAINER_NOEXCEPT
  159. { return m_pn->value; }
  160. pointer operator->() const BOOST_CONTAINER_NOEXCEPT
  161. {
  162. typedef boost::intrusive::pointer_traits<pointer> ptr_traits;
  163. return ptr_traits::pointer_to(this->operator*());
  164. }
  165. //Increment / Decrement
  166. iterator& operator++() BOOST_CONTAINER_NOEXCEPT
  167. {
  168. if(node_base_ptr_ptr p = this->m_pn->up){
  169. ++p;
  170. this->m_pn = node_ptr_traits::static_cast_from(*p);
  171. }
  172. return *this;
  173. }
  174. iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
  175. { iterator tmp(*this); ++*this; return iterator(tmp); }
  176. iterator& operator--() BOOST_CONTAINER_NOEXCEPT
  177. {
  178. if(node_base_ptr_ptr p = this->m_pn->up){
  179. --p;
  180. this->m_pn = node_ptr_traits::static_cast_from(*p);
  181. }
  182. return *this;
  183. }
  184. iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
  185. { iterator tmp(*this); --*this; return iterator(tmp); }
  186. reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
  187. {
  188. iterator tmp(*this);
  189. tmp += off;
  190. return *tmp;
  191. }
  192. iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
  193. {
  194. if(node_base_ptr_ptr p = this->m_pn->up){
  195. p += off;
  196. this->m_pn = node_ptr_traits::static_cast_from(*p);
  197. }
  198. return *this;
  199. }
  200. friend iterator operator+(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT
  201. {
  202. iterator tmp(left);
  203. tmp += off;
  204. return tmp;
  205. }
  206. friend iterator operator+(difference_type off, const iterator& right) BOOST_CONTAINER_NOEXCEPT
  207. {
  208. iterator tmp(right);
  209. tmp += off;
  210. return tmp;
  211. }
  212. iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
  213. { *this += -off; return *this; }
  214. friend iterator operator-(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT
  215. {
  216. iterator tmp(left);
  217. tmp -= off;
  218. return tmp;
  219. }
  220. friend difference_type operator-(const iterator& left, const iterator& right) BOOST_CONTAINER_NOEXCEPT
  221. { return left.m_pn->up - right.m_pn->up; }
  222. //Comparison operators
  223. friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
  224. { return l.m_pn == r.m_pn; }
  225. friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
  226. { return l.m_pn != r.m_pn; }
  227. friend bool operator< (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
  228. { return l.m_pn->up < r.m_pn->up; }
  229. friend bool operator<= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
  230. { return l.m_pn->up <= r.m_pn->up; }
  231. friend bool operator> (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
  232. { return l.m_pn->up > r.m_pn->up; }
  233. friend bool operator>= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
  234. { return l.m_pn->up >= r.m_pn->up; }
  235. };
  236. template<class VoidPtr, class VoidAllocator>
  237. struct index_traits
  238. {
  239. typedef boost::intrusive::
  240. pointer_traits
  241. <VoidPtr> void_ptr_traits;
  242. typedef stable_vector_detail::
  243. node_base<VoidPtr> node_base_type;
  244. typedef typename void_ptr_traits::template
  245. rebind_pointer<node_base_type>::type node_base_ptr;
  246. typedef typename void_ptr_traits::template
  247. rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
  248. typedef boost::intrusive::
  249. pointer_traits<node_base_ptr> node_base_ptr_traits;
  250. typedef boost::intrusive::
  251. pointer_traits<node_base_ptr_ptr> node_base_ptr_ptr_traits;
  252. typedef typename allocator_traits<VoidAllocator>::
  253. template portable_rebind_alloc
  254. <node_base_ptr>::type node_base_ptr_allocator;
  255. typedef ::boost::container::vector
  256. <node_base_ptr, node_base_ptr_allocator> index_type;
  257. typedef typename index_type::iterator index_iterator;
  258. typedef typename index_type::const_iterator const_index_iterator;
  259. typedef typename index_type::size_type size_type;
  260. static const size_type ExtraPointers = 3;
  261. //Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers:
  262. // back() is this->index.back() - ExtraPointers;
  263. // end node index is *(this->index.end() - 3)
  264. // Node cache first is *(this->index.end() - 2);
  265. // Node cache last is this->index.back();
  266. static node_base_ptr_ptr ptr_to_node_base_ptr(node_base_ptr &n)
  267. { return node_base_ptr_ptr_traits::pointer_to(n); }
  268. static void fix_up_pointers(index_iterator first, index_iterator last)
  269. {
  270. while(first != last){
  271. typedef typename index_type::reference node_base_ptr_ref;
  272. node_base_ptr_ref nbp = *first;
  273. nbp->up = index_traits::ptr_to_node_base_ptr(nbp);
  274. ++first;
  275. }
  276. }
  277. static index_iterator get_fix_up_end(index_type &index)
  278. { return index.end() - (ExtraPointers - 1); }
  279. static void fix_up_pointers_from(index_type & index, index_iterator first)
  280. { index_traits::fix_up_pointers(first, index_traits::get_fix_up_end(index)); }
  281. static void readjust_end_node(index_type &index, node_base_type &end_node)
  282. {
  283. if(!index.empty()){
  284. index_iterator end_node_it(index_traits::get_fix_up_end(index));
  285. node_base_ptr &end_node_idx_ref = *(--end_node_it);
  286. end_node_idx_ref = node_base_ptr_traits::pointer_to(end_node);
  287. end_node.up = node_base_ptr_ptr_traits::pointer_to(end_node_idx_ref);
  288. }
  289. else{
  290. end_node.up = node_base_ptr_ptr();
  291. }
  292. }
  293. static void initialize_end_node(index_type &index, node_base_type &end_node, const size_type index_capacity_if_empty)
  294. {
  295. if(index.empty()){
  296. index.reserve(index_capacity_if_empty + ExtraPointers);
  297. index.resize(ExtraPointers);
  298. node_base_ptr &end_node_ref = *index.data();
  299. end_node_ref = node_base_ptr_traits::pointer_to(end_node);
  300. end_node.up = index_traits::ptr_to_node_base_ptr(end_node_ref);
  301. }
  302. }
  303. #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
  304. static bool invariants(index_type &index)
  305. {
  306. for( index_iterator it = index.begin()
  307. , it_end = index_traits::get_fix_up_end(index)
  308. ; it != it_end
  309. ; ++it){
  310. if((*it)->up != index_traits::ptr_to_node_base_ptr(*it)){
  311. return false;
  312. }
  313. }
  314. return true;
  315. }
  316. #endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
  317. };
  318. } //namespace stable_vector_detail
  319. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  320. #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
  321. #define STABLE_VECTOR_CHECK_INVARIANT \
  322. invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
  323. BOOST_JOIN(check_invariant_,__LINE__).touch();
  324. #else //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
  325. #define STABLE_VECTOR_CHECK_INVARIANT
  326. #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
  327. #endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  328. /// @endcond
  329. //! Originally developed by Joaquin M. Lopez Munoz, stable_vector is a std::vector
  330. //! drop-in replacement implemented as a node container, offering iterator and reference
  331. //! stability.
  332. //!
  333. //! Here are the details taken from the author's blog
  334. //! (<a href="http://bannalia.blogspot.com/2008/09/introducing-stablevector.html" >
  335. //! Introducing stable_vector</a>):
  336. //!
  337. //! We present stable_vector, a fully STL-compliant stable container that provides
  338. //! most of the features of std::vector except element contiguity.
  339. //!
  340. //! General properties: stable_vector satisfies all the requirements of a container,
  341. //! a reversible container and a sequence and provides all the optional operations
  342. //! present in std::vector. Like std::vector, iterators are random access.
  343. //! stable_vector does not provide element contiguity; in exchange for this absence,
  344. //! the container is stable, i.e. references and iterators to an element of a stable_vector
  345. //! remain valid as long as the element is not erased, and an iterator that has been
  346. //! assigned the return value of end() always remain valid until the destruction of
  347. //! the associated stable_vector.
  348. //!
  349. //! Operation complexity: The big-O complexities of stable_vector operations match
  350. //! exactly those of std::vector. In general, insertion/deletion is constant time at
  351. //! the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector
  352. //! does not internally perform any value_type destruction, copy or assignment
  353. //! operations other than those exactly corresponding to the insertion of new
  354. //! elements or deletion of stored elements, which can sometimes compensate in terms
  355. //! of performance for the extra burden of doing more pointer manipulation and an
  356. //! additional allocation per element.
  357. //!
  358. //! Exception safety: As stable_vector does not internally copy elements around, some
  359. //! operations provide stronger exception safety guarantees than in std::vector.
  360. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  361. template <class T, class Allocator = std::allocator<T> >
  362. #else
  363. template <class T, class Allocator>
  364. #endif
  365. class stable_vector
  366. {
  367. ///@cond
  368. typedef allocator_traits<Allocator> allocator_traits_type;
  369. typedef boost::intrusive::
  370. pointer_traits
  371. <typename allocator_traits_type::pointer> ptr_traits;
  372. typedef typename ptr_traits::
  373. template rebind_pointer<void>::type void_ptr;
  374. typedef typename allocator_traits_type::
  375. template portable_rebind_alloc
  376. <void>::type void_allocator_type;
  377. typedef stable_vector_detail::index_traits
  378. <void_ptr, void_allocator_type> index_traits_type;
  379. typedef typename index_traits_type::node_base_type node_base_type;
  380. typedef typename index_traits_type::node_base_ptr node_base_ptr;
  381. typedef typename index_traits_type::
  382. node_base_ptr_ptr node_base_ptr_ptr;
  383. typedef typename index_traits_type::
  384. node_base_ptr_traits node_base_ptr_traits;
  385. typedef typename index_traits_type::
  386. node_base_ptr_ptr_traits node_base_ptr_ptr_traits;
  387. typedef typename index_traits_type::index_type index_type;
  388. typedef typename index_traits_type::index_iterator index_iterator;
  389. typedef typename index_traits_type::
  390. const_index_iterator const_index_iterator;
  391. typedef stable_vector_detail::node
  392. <typename ptr_traits::pointer> node_type;
  393. typedef typename ptr_traits::template
  394. rebind_pointer<node_type>::type node_ptr;
  395. typedef boost::intrusive::
  396. pointer_traits<node_ptr> node_ptr_traits;
  397. typedef typename ptr_traits::template
  398. rebind_pointer<const node_type>::type const_node_ptr;
  399. typedef boost::intrusive::
  400. pointer_traits<const_node_ptr> const_node_ptr_traits;
  401. typedef typename node_ptr_traits::reference node_reference;
  402. typedef typename const_node_ptr_traits::reference const_node_reference;
  403. typedef ::boost::container::container_detail::
  404. integral_constant<unsigned, 1> allocator_v1;
  405. typedef ::boost::container::container_detail::
  406. integral_constant<unsigned, 2> allocator_v2;
  407. typedef ::boost::container::container_detail::integral_constant
  408. <unsigned, boost::container::container_detail::
  409. version<Allocator>::value> alloc_version;
  410. typedef typename allocator_traits_type::
  411. template portable_rebind_alloc
  412. <node_type>::type node_allocator_type;
  413. typedef ::boost::container::container_detail::
  414. allocator_version_traits<node_allocator_type> allocator_version_traits_t;
  415. typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain;
  416. node_ptr allocate_one()
  417. { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
  418. void deallocate_one(const node_ptr &p)
  419. { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
  420. void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m)
  421. { allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); }
  422. void deallocate_individual(multiallocation_chain &holder)
  423. { allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); }
  424. friend class stable_vector_detail::clear_on_destroy<stable_vector>;
  425. typedef stable_vector_detail::iterator
  426. < typename allocator_traits<Allocator>::pointer
  427. , false> iterator_impl;
  428. typedef stable_vector_detail::iterator
  429. < typename allocator_traits<Allocator>::pointer
  430. , false> const_iterator_impl;
  431. ///@endcond
  432. public:
  433. //////////////////////////////////////////////
  434. //
  435. // types
  436. //
  437. //////////////////////////////////////////////
  438. typedef T value_type;
  439. typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
  440. typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
  441. typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
  442. typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
  443. typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
  444. typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
  445. typedef Allocator allocator_type;
  446. typedef node_allocator_type stored_allocator_type;
  447. typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
  448. typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
  449. typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<iterator>) reverse_iterator;
  450. typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
  451. ///@cond
  452. private:
  453. BOOST_COPYABLE_AND_MOVABLE(stable_vector)
  454. static const size_type ExtraPointers = index_traits_type::ExtraPointers;
  455. class insert_rollback;
  456. friend class insert_rollback;
  457. class push_back_rollback;
  458. friend class push_back_rollback;
  459. ///@endcond
  460. public:
  461. //////////////////////////////////////////////
  462. //
  463. // construct/copy/destroy
  464. //
  465. //////////////////////////////////////////////
  466. //! <b>Effects</b>: Default constructs a stable_vector.
  467. //!
  468. //! <b>Throws</b>: If allocator_type's default constructor throws.
  469. //!
  470. //! <b>Complexity</b>: Constant.
  471. stable_vector()
  472. : internal_data(), index()
  473. {
  474. STABLE_VECTOR_CHECK_INVARIANT;
  475. }
  476. //! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
  477. //!
  478. //! <b>Throws</b>: Nothing
  479. //!
  480. //! <b>Complexity</b>: Constant.
  481. explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT
  482. : internal_data(al), index(al)
  483. {
  484. STABLE_VECTOR_CHECK_INVARIANT;
  485. }
  486. //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
  487. //! and inserts n value initialized values.
  488. //!
  489. //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
  490. //! throws or T's default or copy constructor throws.
  491. //!
  492. //! <b>Complexity</b>: Linear to n.
  493. explicit stable_vector(size_type n)
  494. : internal_data(), index()
  495. {
  496. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  497. this->resize(n);
  498. STABLE_VECTOR_CHECK_INVARIANT;
  499. cod.release();
  500. }
  501. //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
  502. //! and inserts n default initialized values.
  503. //!
  504. //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
  505. //! throws or T's default or copy constructor throws.
  506. //!
  507. //! <b>Complexity</b>: Linear to n.
  508. //!
  509. //! <b>Note</b>: Non-standard extension
  510. stable_vector(size_type n, default_init_t)
  511. : internal_data(), index()
  512. {
  513. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  514. this->resize(n, default_init);
  515. STABLE_VECTOR_CHECK_INVARIANT;
  516. cod.release();
  517. }
  518. //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
  519. //! and inserts n copies of value.
  520. //!
  521. //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
  522. //! throws or T's default or copy constructor throws.
  523. //!
  524. //! <b>Complexity</b>: Linear to n.
  525. stable_vector(size_type n, const T& t, const allocator_type& al = allocator_type())
  526. : internal_data(al), index(al)
  527. {
  528. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  529. this->insert(this->cend(), n, t);
  530. STABLE_VECTOR_CHECK_INVARIANT;
  531. cod.release();
  532. }
  533. //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
  534. //! and inserts a copy of the range [first, last) in the stable_vector.
  535. //!
  536. //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
  537. //! throws or T's constructor taking an dereferenced InIt throws.
  538. //!
  539. //! <b>Complexity</b>: Linear to the range [first, last).
  540. template <class InputIterator>
  541. stable_vector(InputIterator first,InputIterator last, const allocator_type& al = allocator_type())
  542. : internal_data(al), index(al)
  543. {
  544. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  545. this->insert(this->cend(), first, last);
  546. STABLE_VECTOR_CHECK_INVARIANT;
  547. cod.release();
  548. }
  549. //! <b>Effects</b>: Copy constructs a stable_vector.
  550. //!
  551. //! <b>Postcondition</b>: x == *this.
  552. //!
  553. //! <b>Complexity</b>: Linear to the elements x contains.
  554. stable_vector(const stable_vector& x)
  555. : internal_data(allocator_traits<node_allocator_type>::
  556. select_on_container_copy_construction(x.priv_node_alloc()))
  557. , index(allocator_traits<allocator_type>::
  558. select_on_container_copy_construction(x.index.get_stored_allocator()))
  559. {
  560. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  561. this->insert(this->cend(), x.begin(), x.end());
  562. STABLE_VECTOR_CHECK_INVARIANT;
  563. cod.release();
  564. }
  565. //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
  566. //!
  567. //! <b>Throws</b>: If allocator_type's copy constructor throws.
  568. //!
  569. //! <b>Complexity</b>: Constant.
  570. stable_vector(BOOST_RV_REF(stable_vector) x)
  571. : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
  572. {
  573. this->priv_swap_members(x);
  574. }
  575. //! <b>Effects</b>: Copy constructs a stable_vector using the specified allocator.
  576. //!
  577. //! <b>Postcondition</b>: x == *this.
  578. //!
  579. //! <b>Complexity</b>: Linear to the elements x contains.
  580. stable_vector(const stable_vector& x, const allocator_type &a)
  581. : internal_data(a), index(a)
  582. {
  583. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  584. this->insert(this->cend(), x.begin(), x.end());
  585. STABLE_VECTOR_CHECK_INVARIANT;
  586. cod.release();
  587. }
  588. //! <b>Effects</b>: Move constructor using the specified allocator.
  589. //! Moves mx's resources to *this.
  590. //!
  591. //! <b>Throws</b>: If allocator_type's copy constructor throws.
  592. //!
  593. //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
  594. stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
  595. : internal_data(a), index(a)
  596. {
  597. if(this->priv_node_alloc() == x.priv_node_alloc()){
  598. this->priv_swap_members(x);
  599. }
  600. else{
  601. stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
  602. this->insert(this->cend(), x.begin(), x.end());
  603. STABLE_VECTOR_CHECK_INVARIANT;
  604. cod.release();
  605. }
  606. }
  607. //! <b>Effects</b>: Destroys the stable_vector. All stored values are destroyed
  608. //! and used memory is deallocated.
  609. //!
  610. //! <b>Throws</b>: Nothing.
  611. //!
  612. //! <b>Complexity</b>: Linear to the number of elements.
  613. ~stable_vector()
  614. {
  615. this->clear();
  616. this->priv_clear_pool();
  617. }
  618. //! <b>Effects</b>: Makes *this contain the same elements as x.
  619. //!
  620. //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
  621. //! of each of x's elements.
  622. //!
  623. //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
  624. //!
  625. //! <b>Complexity</b>: Linear to the number of elements in x.
  626. stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
  627. {
  628. STABLE_VECTOR_CHECK_INVARIANT;
  629. if (&x != this){
  630. node_allocator_type &this_alloc = this->priv_node_alloc();
  631. const node_allocator_type &x_alloc = x.priv_node_alloc();
  632. container_detail::bool_<allocator_traits_type::
  633. propagate_on_container_copy_assignment::value> flag;
  634. if(flag && this_alloc != x_alloc){
  635. this->clear();
  636. this->shrink_to_fit();
  637. }
  638. container_detail::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
  639. container_detail::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
  640. this->assign(x.begin(), x.end());
  641. }
  642. return *this;
  643. }
  644. //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
  645. //!
  646. //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
  647. //! before the function.
  648. //!
  649. //! <b>Throws</b>: If allocator_type's copy constructor throws.
  650. //!
  651. //! <b>Complexity</b>: Linear.
  652. stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
  653. {
  654. if (&x != this){
  655. node_allocator_type &this_alloc = this->priv_node_alloc();
  656. node_allocator_type &x_alloc = x.priv_node_alloc();
  657. //If allocators are equal we can just swap pointers
  658. if(this_alloc == x_alloc){
  659. //Destroy objects but retain memory
  660. this->clear();
  661. this->index = boost::move(x.index);
  662. this->priv_swap_members(x);
  663. //Move allocator if needed
  664. container_detail::bool_<allocator_traits_type::
  665. propagate_on_container_move_assignment::value> flag;
  666. container_detail::move_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
  667. }
  668. //If unequal allocators, then do a one by one move
  669. else{
  670. this->assign( boost::make_move_iterator(x.begin())
  671. , boost::make_move_iterator(x.end()));
  672. }
  673. }
  674. return *this;
  675. }
  676. //! <b>Effects</b>: Assigns the n copies of val to *this.
  677. //!
  678. //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
  679. //!
  680. //! <b>Complexity</b>: Linear to n.
  681. void assign(size_type n, const T& t)
  682. {
  683. typedef constant_iterator<value_type, difference_type> cvalue_iterator;
  684. this->assign(cvalue_iterator(t, n), cvalue_iterator());
  685. }
  686. //! <b>Effects</b>: Assigns the the range [first, last) to *this.
  687. //!
  688. //! <b>Throws</b>: If memory allocation throws or
  689. //! T's constructor from dereferencing InpIt throws.
  690. //!
  691. //! <b>Complexity</b>: Linear to n.
  692. template<typename InputIterator>
  693. void assign(InputIterator first,InputIterator last
  694. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  695. , typename container_detail::enable_if_c
  696. < !container_detail::is_convertible<InputIterator, size_type>::value
  697. >::type * = 0
  698. #endif
  699. )
  700. {
  701. STABLE_VECTOR_CHECK_INVARIANT;
  702. iterator first1 = this->begin();
  703. iterator last1 = this->end();
  704. for ( ; first1 != last1 && first != last; ++first1, ++first)
  705. *first1 = *first;
  706. if (first == last){
  707. this->erase(first1, last1);
  708. }
  709. else{
  710. this->insert(last1, first, last);
  711. }
  712. }
  713. //! <b>Effects</b>: Returns a copy of the internal allocator.
  714. //!
  715. //! <b>Throws</b>: If allocator's copy constructor throws.
  716. //!
  717. //! <b>Complexity</b>: Constant.
  718. allocator_type get_allocator() const
  719. { return this->priv_node_alloc(); }
  720. //! <b>Effects</b>: Returns a reference to the internal allocator.
  721. //!
  722. //! <b>Throws</b>: Nothing
  723. //!
  724. //! <b>Complexity</b>: Constant.
  725. //!
  726. //! <b>Note</b>: Non-standard extension.
  727. const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
  728. { return this->priv_node_alloc(); }
  729. //! <b>Effects</b>: Returns a reference to the internal allocator.
  730. //!
  731. //! <b>Throws</b>: Nothing
  732. //!
  733. //! <b>Complexity</b>: Constant.
  734. //!
  735. //! <b>Note</b>: Non-standard extension.
  736. stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
  737. { return this->priv_node_alloc(); }
  738. //////////////////////////////////////////////
  739. //
  740. // iterators
  741. //
  742. //////////////////////////////////////////////
  743. //! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
  744. //!
  745. //! <b>Throws</b>: Nothing.
  746. //!
  747. //! <b>Complexity</b>: Constant.
  748. iterator begin() BOOST_CONTAINER_NOEXCEPT
  749. { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
  750. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
  751. //!
  752. //! <b>Throws</b>: Nothing.
  753. //!
  754. //! <b>Complexity</b>: Constant.
  755. const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
  756. { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
  757. //! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
  758. //!
  759. //! <b>Throws</b>: Nothing.
  760. //!
  761. //! <b>Complexity</b>: Constant.
  762. iterator end() BOOST_CONTAINER_NOEXCEPT
  763. { return iterator(this->priv_get_end_node()); }
  764. //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
  765. //!
  766. //! <b>Throws</b>: Nothing.
  767. //!
  768. //! <b>Complexity</b>: Constant.
  769. const_iterator end() const BOOST_CONTAINER_NOEXCEPT
  770. { return const_iterator(this->priv_get_end_node()); }
  771. //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
  772. //! of the reversed stable_vector.
  773. //!
  774. //! <b>Throws</b>: Nothing.
  775. //!
  776. //! <b>Complexity</b>: Constant.
  777. reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
  778. { return reverse_iterator(this->end()); }
  779. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
  780. //! of the reversed stable_vector.
  781. //!
  782. //! <b>Throws</b>: Nothing.
  783. //!
  784. //! <b>Complexity</b>: Constant.
  785. const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
  786. { return const_reverse_iterator(this->end()); }
  787. //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
  788. //! of the reversed stable_vector.
  789. //!
  790. //! <b>Throws</b>: Nothing.
  791. //!
  792. //! <b>Complexity</b>: Constant.
  793. reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
  794. { return reverse_iterator(this->begin()); }
  795. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
  796. //! of the reversed stable_vector.
  797. //!
  798. //! <b>Throws</b>: Nothing.
  799. //!
  800. //! <b>Complexity</b>: Constant.
  801. const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
  802. { return const_reverse_iterator(this->begin()); }
  803. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
  804. //!
  805. //! <b>Throws</b>: Nothing.
  806. //!
  807. //! <b>Complexity</b>: Constant.
  808. const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
  809. { return this->begin(); }
  810. //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
  811. //!
  812. //! <b>Throws</b>: Nothing.
  813. //!
  814. //! <b>Complexity</b>: Constant.
  815. const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
  816. { return this->end(); }
  817. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
  818. //! of the reversed stable_vector.
  819. //!
  820. //! <b>Throws</b>: Nothing.
  821. //!
  822. //! <b>Complexity</b>: Constant.
  823. const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
  824. { return this->rbegin(); }
  825. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
  826. //! of the reversed stable_vector.
  827. //!
  828. //! <b>Throws</b>: Nothing.
  829. //!
  830. //! <b>Complexity</b>: Constant.
  831. const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT
  832. { return this->rend(); }
  833. //////////////////////////////////////////////
  834. //
  835. // capacity
  836. //
  837. //////////////////////////////////////////////
  838. //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
  839. //!
  840. //! <b>Throws</b>: Nothing.
  841. //!
  842. //! <b>Complexity</b>: Constant.
  843. bool empty() const BOOST_CONTAINER_NOEXCEPT
  844. { return this->index.size() <= ExtraPointers; }
  845. //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
  846. //!
  847. //! <b>Throws</b>: Nothing.
  848. //!
  849. //! <b>Complexity</b>: Constant.
  850. size_type size() const BOOST_CONTAINER_NOEXCEPT
  851. {
  852. const size_type index_size = this->index.size();
  853. return (index_size - ExtraPointers) & (std::size_t(0u) -std::size_t(index_size != 0));
  854. }
  855. //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
  856. //!
  857. //! <b>Throws</b>: Nothing.
  858. //!
  859. //! <b>Complexity</b>: Constant.
  860. size_type max_size() const BOOST_CONTAINER_NOEXCEPT
  861. { return this->index.max_size() - ExtraPointers; }
  862. //! <b>Effects</b>: Inserts or erases elements at the end such that
  863. //! the size becomes n. New elements are value initialized.
  864. //!
  865. //! <b>Throws</b>: If memory allocation throws, or T's default constructor throws.
  866. //!
  867. //! <b>Complexity</b>: Linear to the difference between size() and new_size.
  868. void resize(size_type n)
  869. {
  870. typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator;
  871. STABLE_VECTOR_CHECK_INVARIANT;
  872. if(n > this->size())
  873. this->insert(this->cend(), value_init_iterator(n - this->size()), value_init_iterator());
  874. else if(n < this->size())
  875. this->erase(this->cbegin() + n, this->cend());
  876. }
  877. //! <b>Effects</b>: Inserts or erases elements at the end such that
  878. //! the size becomes n. New elements are default initialized.
  879. //!
  880. //! <b>Throws</b>: If memory allocation throws, or T's default constructor throws.
  881. //!
  882. //! <b>Complexity</b>: Linear to the difference between size() and new_size.
  883. //!
  884. //! <b>Note</b>: Non-standard extension
  885. void resize(size_type n, default_init_t)
  886. {
  887. typedef default_init_construct_iterator<value_type, difference_type> default_init_iterator;
  888. STABLE_VECTOR_CHECK_INVARIANT;
  889. if(n > this->size())
  890. this->insert(this->cend(), default_init_iterator(n - this->size()), default_init_iterator());
  891. else if(n < this->size())
  892. this->erase(this->cbegin() + n, this->cend());
  893. }
  894. //! <b>Effects</b>: Inserts or erases elements at the end such that
  895. //! the size becomes n. New elements are copy constructed from x.
  896. //!
  897. //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
  898. //!
  899. //! <b>Complexity</b>: Linear to the difference between size() and new_size.
  900. void resize(size_type n, const T& t)
  901. {
  902. STABLE_VECTOR_CHECK_INVARIANT;
  903. if(n > this->size())
  904. this->insert(this->cend(), n - this->size(), t);
  905. else if(n < this->size())
  906. this->erase(this->cbegin() + n, this->cend());
  907. }
  908. //! <b>Effects</b>: Number of elements for which memory has been allocated.
  909. //! capacity() is always greater than or equal to size().
  910. //!
  911. //! <b>Throws</b>: Nothing.
  912. //!
  913. //! <b>Complexity</b>: Constant.
  914. size_type capacity() const BOOST_CONTAINER_NOEXCEPT
  915. {
  916. const size_type index_size = this->index.size();
  917. BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
  918. const size_type bucket_extra_capacity = this->index.capacity()- index_size;
  919. const size_type node_extra_capacity = this->internal_data.pool_size;
  920. const size_type extra_capacity = (bucket_extra_capacity < node_extra_capacity)
  921. ? bucket_extra_capacity : node_extra_capacity;
  922. const size_type index_offset =
  923. (ExtraPointers + extra_capacity) & (size_type(0u) - size_type(index_size != 0));
  924. return index_size - index_offset;
  925. }
  926. //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
  927. //! effect. Otherwise, it is a request for allocation of additional memory.
  928. //! If the request is successful, then capacity() is greater than or equal to
  929. //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
  930. //!
  931. //! <b>Throws</b>: If memory allocation allocation throws.
  932. void reserve(size_type n)
  933. {
  934. STABLE_VECTOR_CHECK_INVARIANT;
  935. if(n > this->max_size()){
  936. throw_length_error("stable_vector::reserve max_size() exceeded");
  937. }
  938. size_type sz = this->size();
  939. size_type old_capacity = this->capacity();
  940. if(n > old_capacity){
  941. index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
  942. const void * old_ptr = &index[0];
  943. this->index.reserve(n + ExtraPointers);
  944. bool realloced = &index[0] != old_ptr;
  945. //Fix the pointers for the newly allocated buffer
  946. if(realloced){
  947. index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
  948. }
  949. //Now fill pool if data is not enough
  950. if((n - sz) > this->internal_data.pool_size){
  951. this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
  952. }
  953. }
  954. }
  955. //! <b>Effects</b>: Tries to deallocate the excess of memory created
  956. //! with previous allocations. The size of the stable_vector is unchanged
  957. //!
  958. //! <b>Throws</b>: If memory allocation throws.
  959. //!
  960. //! <b>Complexity</b>: Linear to size().
  961. void shrink_to_fit()
  962. {
  963. if(this->capacity()){
  964. //First empty allocated node pool
  965. this->priv_clear_pool();
  966. //If empty completely destroy the index, let's recover default-constructed state
  967. if(this->empty()){
  968. this->index.clear();
  969. this->index.shrink_to_fit();
  970. this->internal_data.end_node.up = node_base_ptr_ptr();
  971. }
  972. //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
  973. else{
  974. const void* old_ptr = &index[0];
  975. this->index.shrink_to_fit();
  976. bool realloced = &index[0] != old_ptr;
  977. //Fix the pointers for the newly allocated buffer
  978. if(realloced){
  979. index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
  980. }
  981. }
  982. }
  983. }
  984. //////////////////////////////////////////////
  985. //
  986. // element access
  987. //
  988. //////////////////////////////////////////////
  989. //! <b>Requires</b>: !empty()
  990. //!
  991. //! <b>Effects</b>: Returns a reference to the first
  992. //! element of the container.
  993. //!
  994. //! <b>Throws</b>: Nothing.
  995. //!
  996. //! <b>Complexity</b>: Constant.
  997. reference front() BOOST_CONTAINER_NOEXCEPT
  998. { return static_cast<node_reference>(*this->index.front()).value; }
  999. //! <b>Requires</b>: !empty()
  1000. //!
  1001. //! <b>Effects</b>: Returns a const reference to the first
  1002. //! element of the container.
  1003. //!
  1004. //! <b>Throws</b>: Nothing.
  1005. //!
  1006. //! <b>Complexity</b>: Constant.
  1007. const_reference front() const BOOST_CONTAINER_NOEXCEPT
  1008. { return static_cast<const_node_reference>(*this->index.front()).value; }
  1009. //! <b>Requires</b>: !empty()
  1010. //!
  1011. //! <b>Effects</b>: Returns a reference to the last
  1012. //! element of the container.
  1013. //!
  1014. //! <b>Throws</b>: Nothing.
  1015. //!
  1016. //! <b>Complexity</b>: Constant.
  1017. reference back() BOOST_CONTAINER_NOEXCEPT
  1018. { return static_cast<node_reference>(*this->index[this->size()-1u]).value; }
  1019. //! <b>Requires</b>: !empty()
  1020. //!
  1021. //! <b>Effects</b>: Returns a const reference to the last
  1022. //! element of the container.
  1023. //!
  1024. //! <b>Throws</b>: Nothing.
  1025. //!
  1026. //! <b>Complexity</b>: Constant.
  1027. const_reference back() const BOOST_CONTAINER_NOEXCEPT
  1028. { return static_cast<const_node_reference>(*this->index[this->size()-1u]).value; }
  1029. //! <b>Requires</b>: size() > n.
  1030. //!
  1031. //! <b>Effects</b>: Returns a reference to the nth element
  1032. //! from the beginning of the container.
  1033. //!
  1034. //! <b>Throws</b>: Nothing.
  1035. //!
  1036. //! <b>Complexity</b>: Constant.
  1037. reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
  1038. {
  1039. BOOST_ASSERT(n < this->size());
  1040. return static_cast<node_reference>(*this->index[n]).value;
  1041. }
  1042. //! <b>Requires</b>: size() > n.
  1043. //!
  1044. //! <b>Effects</b>: Returns a const reference to the nth element
  1045. //! from the beginning of the container.
  1046. //!
  1047. //! <b>Throws</b>: Nothing.
  1048. //!
  1049. //! <b>Complexity</b>: Constant.
  1050. const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
  1051. {
  1052. BOOST_ASSERT(n < this->size());
  1053. return static_cast<const_node_reference>(*this->index[n]).value;
  1054. }
  1055. //! <b>Requires</b>: size() > n.
  1056. //!
  1057. //! <b>Effects</b>: Returns a reference to the nth element
  1058. //! from the beginning of the container.
  1059. //!
  1060. //! <b>Throws</b>: std::range_error if n >= size()
  1061. //!
  1062. //! <b>Complexity</b>: Constant.
  1063. reference at(size_type n)
  1064. {
  1065. if(n >= this->size()){
  1066. throw_out_of_range("vector::at invalid subscript");
  1067. }
  1068. return operator[](n);
  1069. }
  1070. //! <b>Requires</b>: size() > n.
  1071. //!
  1072. //! <b>Effects</b>: Returns a const reference to the nth element
  1073. //! from the beginning of the container.
  1074. //!
  1075. //! <b>Throws</b>: std::range_error if n >= size()
  1076. //!
  1077. //! <b>Complexity</b>: Constant.
  1078. const_reference at(size_type n)const
  1079. {
  1080. if(n >= this->size()){
  1081. throw_out_of_range("vector::at invalid subscript");
  1082. }
  1083. return operator[](n);
  1084. }
  1085. //////////////////////////////////////////////
  1086. //
  1087. // modifiers
  1088. //
  1089. //////////////////////////////////////////////
  1090. #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1091. //! <b>Effects</b>: Inserts an object of type T constructed with
  1092. //! std::forward<Args>(args)... in the end of the stable_vector.
  1093. //!
  1094. //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
  1095. //!
  1096. //! <b>Complexity</b>: Amortized constant time.
  1097. template<class ...Args>
  1098. void emplace_back(Args &&...args)
  1099. {
  1100. typedef emplace_functor<Args...> EmplaceFunctor;
  1101. typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
  1102. EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
  1103. this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
  1104. }
  1105. //! <b>Requires</b>: position must be a valid iterator of *this.
  1106. //!
  1107. //! <b>Effects</b>: Inserts an object of type T constructed with
  1108. //! std::forward<Args>(args)... before position
  1109. //!
  1110. //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
  1111. //!
  1112. //! <b>Complexity</b>: If position is end(), amortized constant time
  1113. //! Linear time otherwise.
  1114. template<class ...Args>
  1115. iterator emplace(const_iterator position, Args && ...args)
  1116. {
  1117. //Just call more general insert(pos, size, value) and return iterator
  1118. size_type pos_n = position - cbegin();
  1119. typedef emplace_functor<Args...> EmplaceFunctor;
  1120. typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
  1121. EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
  1122. this->insert(position, EmplaceIterator(ef), EmplaceIterator());
  1123. return iterator(this->begin() + pos_n);
  1124. }
  1125. #else
  1126. #define BOOST_PP_LOCAL_MACRO(n) \
  1127. BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
  1128. void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  1129. { \
  1130. typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
  1131. BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
  1132. EmplaceFunctor; \
  1133. typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator; \
  1134. EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
  1135. BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
  1136. BOOST_PP_RPAREN_IF(n); \
  1137. this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator()); \
  1138. } \
  1139. \
  1140. BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
  1141. iterator emplace(const_iterator pos \
  1142. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  1143. { \
  1144. typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
  1145. BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
  1146. EmplaceFunctor; \
  1147. typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator; \
  1148. EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
  1149. BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
  1150. BOOST_PP_RPAREN_IF(n); \
  1151. size_type pos_n = pos - this->cbegin(); \
  1152. this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
  1153. return iterator(this->begin() + pos_n); \
  1154. } \
  1155. //!
  1156. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  1157. #include BOOST_PP_LOCAL_ITERATE()
  1158. #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
  1159. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1160. //! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector.
  1161. //!
  1162. //! <b>Throws</b>: If memory allocation throws or
  1163. //! T's copy constructor throws.
  1164. //!
  1165. //! <b>Complexity</b>: Amortized constant time.
  1166. void push_back(const T &x);
  1167. //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
  1168. //! and moves the resources of mx to this new element.
  1169. //!
  1170. //! <b>Throws</b>: If memory allocation throws.
  1171. //!
  1172. //! <b>Complexity</b>: Amortized constant time.
  1173. void push_back(T &&x);
  1174. #else
  1175. BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
  1176. #endif
  1177. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1178. //! <b>Requires</b>: position must be a valid iterator of *this.
  1179. //!
  1180. //! <b>Effects</b>: Insert a copy of x before position.
  1181. //!
  1182. //! <b>Returns</b>: An iterator to the inserted element.
  1183. //!
  1184. //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
  1185. //!
  1186. //! <b>Complexity</b>: If position is end(), amortized constant time
  1187. //! Linear time otherwise.
  1188. iterator insert(const_iterator position, const T &x);
  1189. //! <b>Requires</b>: position must be a valid iterator of *this.
  1190. //!
  1191. //! <b>Effects</b>: Insert a new element before position with mx's resources.
  1192. //!
  1193. //! <b>Returns</b>: an iterator to the inserted element.
  1194. //!
  1195. //! <b>Throws</b>: If memory allocation throws.
  1196. //!
  1197. //! <b>Complexity</b>: If position is end(), amortized constant time
  1198. //! Linear time otherwise.
  1199. iterator insert(const_iterator position, T &&x);
  1200. #else
  1201. BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
  1202. #endif
  1203. //! <b>Requires</b>: pos must be a valid iterator of *this.
  1204. //!
  1205. //! <b>Effects</b>: Insert n copies of x before position.
  1206. //!
  1207. //! <b>Returns</b>: an iterator to the first inserted element or position if n is 0.
  1208. //!
  1209. //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
  1210. //!
  1211. //! <b>Complexity</b>: Linear to n.
  1212. iterator insert(const_iterator position, size_type n, const T& t)
  1213. {
  1214. STABLE_VECTOR_CHECK_INVARIANT;
  1215. typedef constant_iterator<value_type, difference_type> cvalue_iterator;
  1216. return this->insert(position, cvalue_iterator(t, n), cvalue_iterator());
  1217. }
  1218. //! <b>Requires</b>: pos must be a valid iterator of *this.
  1219. //!
  1220. //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
  1221. //!
  1222. //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
  1223. //!
  1224. //! <b>Throws</b>: If memory allocation throws, T's constructor from a
  1225. //! dereferenced InpIt throws or T's copy constructor throws.
  1226. //!
  1227. //! <b>Complexity</b>: Linear to std::distance [first, last).
  1228. template <class InputIterator>
  1229. iterator insert(const_iterator position, InputIterator first, InputIterator last
  1230. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1231. , typename container_detail::enable_if_c
  1232. < !container_detail::is_convertible<InputIterator, size_type>::value
  1233. && container_detail::is_input_iterator<InputIterator>::value
  1234. >::type * = 0
  1235. #endif
  1236. )
  1237. {
  1238. STABLE_VECTOR_CHECK_INVARIANT;
  1239. const size_type pos_n = position - this->cbegin();
  1240. for(; first != last; ++first){
  1241. this->emplace(position, *first);
  1242. }
  1243. return this->begin() + pos_n;
  1244. }
  1245. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1246. template <class FwdIt>
  1247. iterator insert(const_iterator position, FwdIt first, FwdIt last
  1248. , typename container_detail::enable_if_c
  1249. < !container_detail::is_convertible<FwdIt, size_type>::value
  1250. && !container_detail::is_input_iterator<FwdIt>::value
  1251. >::type * = 0
  1252. )
  1253. {
  1254. const size_type num_new = static_cast<size_type>(std::distance(first, last));
  1255. const size_type pos = static_cast<size_type>(position - this->cbegin());
  1256. if(num_new){
  1257. //Fills the node pool and inserts num_new null pointers in pos.
  1258. //If a new buffer was needed fixes up pointers up to pos so
  1259. //past-new nodes are not aligned until the end of this function
  1260. //or in a rollback in case of exception
  1261. index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(pos, num_new));
  1262. const index_iterator it_past_new(it_past_newly_constructed + num_new);
  1263. {
  1264. //Prepare rollback
  1265. insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
  1266. while(first != last){
  1267. const node_ptr p = this->priv_get_from_pool();
  1268. BOOST_ASSERT(!!p);
  1269. //Put it in the index so rollback can return it in pool if construct_in_place throws
  1270. *it_past_newly_constructed = p;
  1271. //Constructs and fixes up pointers This can throw
  1272. this->priv_build_node_from_it(p, it_past_newly_constructed, first);
  1273. ++first;
  1274. ++it_past_newly_constructed;
  1275. }
  1276. //rollback.~insert_rollback() called in case of exception
  1277. }
  1278. //Fix up pointers for past-new nodes (new nodes were fixed during construction) and
  1279. //nodes before insertion position in priv_insert_forward_non_templated(...)
  1280. index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
  1281. }
  1282. return this->begin() + pos;
  1283. }
  1284. #endif
  1285. //! <b>Effects</b>: Removes the last element from the stable_vector.
  1286. //!
  1287. //! <b>Throws</b>: Nothing.
  1288. //!
  1289. //! <b>Complexity</b>: Constant time.
  1290. void pop_back() BOOST_CONTAINER_NOEXCEPT
  1291. { this->erase(--this->cend()); }
  1292. //! <b>Effects</b>: Erases the element at position pos.
  1293. //!
  1294. //! <b>Throws</b>: Nothing.
  1295. //!
  1296. //! <b>Complexity</b>: Linear to the elements between pos and the
  1297. //! last element. Constant if pos is the last element.
  1298. iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
  1299. {
  1300. STABLE_VECTOR_CHECK_INVARIANT;
  1301. const size_type d = position - this->cbegin();
  1302. index_iterator it = this->index.begin() + d;
  1303. this->priv_delete_node(position.node_pointer());
  1304. it = this->index.erase(it);
  1305. index_traits_type::fix_up_pointers_from(this->index, it);
  1306. return iterator(node_ptr_traits::static_cast_from(*it));
  1307. }
  1308. //! <b>Effects</b>: Erases the elements pointed by [first, last).
  1309. //!
  1310. //! <b>Throws</b>: Nothing.
  1311. //!
  1312. //! <b>Complexity</b>: Linear to the distance between first and last
  1313. //! plus linear to the elements between pos and the last element.
  1314. iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
  1315. {
  1316. STABLE_VECTOR_CHECK_INVARIANT;
  1317. const const_iterator cbeg(this->cbegin());
  1318. const size_type d1 = static_cast<size_type>(first - cbeg),
  1319. d2 = static_cast<size_type>(last - cbeg);
  1320. size_type d_dif = d2 - d1;
  1321. if(d_dif){
  1322. multiallocation_chain holder;
  1323. const index_iterator it1(this->index.begin() + d1);
  1324. const index_iterator it2(it1 + d_dif);
  1325. index_iterator it(it1);
  1326. while(d_dif--){
  1327. node_base_ptr &nb = *it;
  1328. ++it;
  1329. node_type &n = *node_ptr_traits::static_cast_from(nb);
  1330. this->priv_destroy_node(n);
  1331. holder.push_back(node_ptr_traits::pointer_to(n));
  1332. }
  1333. this->priv_put_in_pool(holder);
  1334. const index_iterator e = this->index.erase(it1, it2);
  1335. index_traits_type::fix_up_pointers_from(this->index, e);
  1336. }
  1337. return iterator(last.node_pointer());
  1338. }
  1339. //! <b>Effects</b>: Swaps the contents of *this and x.
  1340. //!
  1341. //! <b>Throws</b>: Nothing.
  1342. //!
  1343. //! <b>Complexity</b>: Constant.
  1344. void swap(stable_vector & x)
  1345. {
  1346. STABLE_VECTOR_CHECK_INVARIANT;
  1347. container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
  1348. container_detail::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
  1349. //vector's allocator is swapped here
  1350. this->index.swap(x.index);
  1351. this->priv_swap_members(x);
  1352. }
  1353. //! <b>Effects</b>: Erases all the elements of the stable_vector.
  1354. //!
  1355. //! <b>Throws</b>: Nothing.
  1356. //!
  1357. //! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
  1358. void clear() BOOST_CONTAINER_NOEXCEPT
  1359. { this->erase(this->cbegin(),this->cend()); }
  1360. /// @cond
  1361. private:
  1362. class insert_rollback
  1363. {
  1364. public:
  1365. insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
  1366. : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
  1367. {}
  1368. ~insert_rollback()
  1369. {
  1370. if(m_it_past_constructed != m_it_past_new){
  1371. m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
  1372. index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
  1373. index_traits_type::fix_up_pointers_from(m_sv.index, e);
  1374. }
  1375. }
  1376. private:
  1377. stable_vector &m_sv;
  1378. index_iterator &m_it_past_constructed;
  1379. const index_iterator &m_it_past_new;
  1380. };
  1381. class push_back_rollback
  1382. {
  1383. public:
  1384. push_back_rollback(stable_vector &sv, const node_ptr &p)
  1385. : m_sv(sv), m_p(p)
  1386. {}
  1387. ~push_back_rollback()
  1388. {
  1389. if(m_p){
  1390. m_sv.priv_put_in_pool(m_p);
  1391. }
  1392. }
  1393. void release()
  1394. { m_p = node_ptr(); }
  1395. private:
  1396. stable_vector &m_sv;
  1397. node_ptr m_p;
  1398. };
  1399. index_iterator priv_insert_forward_non_templated(size_type pos, size_type num_new)
  1400. {
  1401. index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
  1402. //Now try to fill the pool with new data
  1403. if(this->internal_data.pool_size < num_new){
  1404. this->priv_increase_pool(num_new - this->internal_data.pool_size);
  1405. }
  1406. //Now try to make room in the vector
  1407. const node_base_ptr_ptr old_buffer = this->index.data();
  1408. this->index.insert(this->index.begin() + pos, num_new, node_ptr());
  1409. bool new_buffer = this->index.data() != old_buffer;
  1410. //Fix the pointers for the newly allocated buffer
  1411. const index_iterator index_beg = this->index.begin();
  1412. if(new_buffer){
  1413. index_traits_type::fix_up_pointers(index_beg, index_beg + pos);
  1414. }
  1415. return index_beg + pos;
  1416. }
  1417. bool priv_capacity_bigger_than_size() const
  1418. {
  1419. return this->index.capacity() > this->index.size() &&
  1420. this->internal_data.pool_size > 0;
  1421. }
  1422. template <class U>
  1423. void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
  1424. {
  1425. if(this->priv_capacity_bigger_than_size()){
  1426. //Enough memory in the pool and in the index
  1427. const node_ptr p = this->priv_get_from_pool();
  1428. BOOST_ASSERT(!!p);
  1429. {
  1430. push_back_rollback rollback(*this, p);
  1431. //This might throw
  1432. this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
  1433. rollback.release();
  1434. }
  1435. //This can't throw as there is room for a new elements in the index
  1436. index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
  1437. index_traits_type::fix_up_pointers_from(this->index, new_index);
  1438. }
  1439. else{
  1440. this->insert(this->cend(), ::boost::forward<U>(x));
  1441. }
  1442. }
  1443. iterator priv_insert(const_iterator position, const value_type &t)
  1444. {
  1445. typedef constant_iterator<value_type, difference_type> cvalue_iterator;
  1446. return this->insert(position, cvalue_iterator(t, 1), cvalue_iterator());
  1447. }
  1448. iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x)
  1449. {
  1450. typedef repeat_iterator<T, difference_type> repeat_it;
  1451. typedef boost::move_iterator<repeat_it> repeat_move_it;
  1452. //Just call more general insert(pos, size, value) and return iterator
  1453. return this->insert(position, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
  1454. }
  1455. void priv_clear_pool()
  1456. {
  1457. if(!this->index.empty() && this->index.back()){
  1458. node_base_ptr &pool_first_ref = *(this->index.end() - 2);
  1459. node_base_ptr &pool_last_ref = this->index.back();
  1460. multiallocation_chain holder;
  1461. holder.incorporate_after( holder.before_begin()
  1462. , node_ptr_traits::static_cast_from(pool_first_ref)
  1463. , node_ptr_traits::static_cast_from(pool_last_ref)
  1464. , internal_data.pool_size);
  1465. this->deallocate_individual(holder);
  1466. pool_first_ref = pool_last_ref = 0;
  1467. this->internal_data.pool_size = 0;
  1468. }
  1469. }
  1470. void priv_increase_pool(size_type n)
  1471. {
  1472. node_base_ptr &pool_first_ref = *(this->index.end() - 2);
  1473. node_base_ptr &pool_last_ref = this->index.back();
  1474. multiallocation_chain holder;
  1475. holder.incorporate_after( holder.before_begin()
  1476. , node_ptr_traits::static_cast_from(pool_first_ref)
  1477. , node_ptr_traits::static_cast_from(pool_last_ref)
  1478. , internal_data.pool_size);
  1479. multiallocation_chain m;
  1480. this->allocate_individual(n, m);
  1481. holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
  1482. this->internal_data.pool_size += n;
  1483. std::pair<node_ptr, node_ptr> data(holder.extract_data());
  1484. pool_first_ref = data.first;
  1485. pool_last_ref = data.second;
  1486. }
  1487. void priv_put_in_pool(const node_ptr &p)
  1488. {
  1489. node_base_ptr &pool_first_ref = *(this->index.end()-2);
  1490. node_base_ptr &pool_last_ref = this->index.back();
  1491. multiallocation_chain holder;
  1492. holder.incorporate_after( holder.before_begin()
  1493. , node_ptr_traits::static_cast_from(pool_first_ref)
  1494. , node_ptr_traits::static_cast_from(pool_last_ref)
  1495. , internal_data.pool_size);
  1496. holder.push_front(p);
  1497. ++this->internal_data.pool_size;
  1498. std::pair<node_ptr, node_ptr> ret(holder.extract_data());
  1499. pool_first_ref = ret.first;
  1500. pool_last_ref = ret.second;
  1501. }
  1502. void priv_put_in_pool(multiallocation_chain &ch)
  1503. {
  1504. node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
  1505. node_base_ptr &pool_last_ref = this->index.back();
  1506. ch.incorporate_after( ch.before_begin()
  1507. , node_ptr_traits::static_cast_from(pool_first_ref)
  1508. , node_ptr_traits::static_cast_from(pool_last_ref)
  1509. , internal_data.pool_size);
  1510. this->internal_data.pool_size = ch.size();
  1511. const std::pair<node_ptr, node_ptr> ret(ch.extract_data());
  1512. pool_first_ref = ret.first;
  1513. pool_last_ref = ret.second;
  1514. }
  1515. node_ptr priv_get_from_pool()
  1516. {
  1517. //Precondition: index is not empty
  1518. BOOST_ASSERT(!this->index.empty());
  1519. node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
  1520. node_base_ptr &pool_last_ref = this->index.back();
  1521. multiallocation_chain holder;
  1522. holder.incorporate_after( holder.before_begin()
  1523. , node_ptr_traits::static_cast_from(pool_first_ref)
  1524. , node_ptr_traits::static_cast_from(pool_last_ref)
  1525. , internal_data.pool_size);
  1526. node_ptr ret = holder.pop_front();
  1527. --this->internal_data.pool_size;
  1528. if(!internal_data.pool_size){
  1529. pool_first_ref = pool_last_ref = node_ptr();
  1530. }
  1531. else{
  1532. const std::pair<node_ptr, node_ptr> data(holder.extract_data());
  1533. pool_first_ref = data.first;
  1534. pool_last_ref = data.second;
  1535. }
  1536. return ret;
  1537. }
  1538. node_ptr priv_get_end_node() const
  1539. {
  1540. return node_ptr_traits::pointer_to
  1541. (static_cast<node_type&>(const_cast<node_base_type&>(this->internal_data.end_node)));
  1542. }
  1543. void priv_destroy_node(const node_type &n)
  1544. {
  1545. allocator_traits<node_allocator_type>::
  1546. destroy(this->priv_node_alloc(), container_detail::addressof(n.value));
  1547. static_cast<const node_base_type*>(&n)->~node_base_type();
  1548. }
  1549. void priv_delete_node(const node_ptr &n)
  1550. {
  1551. this->priv_destroy_node(*n);
  1552. this->priv_put_in_pool(n);
  1553. }
  1554. template<class Iterator>
  1555. void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
  1556. {
  1557. //This can throw
  1558. boost::container::construct_in_place
  1559. ( this->priv_node_alloc()
  1560. , container_detail::addressof(p->value)
  1561. , it);
  1562. //This does not throw
  1563. ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)))
  1564. node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
  1565. }
  1566. template<class ValueConvertible>
  1567. void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
  1568. {
  1569. //This can throw
  1570. boost::container::allocator_traits<node_allocator_type>::construct
  1571. ( this->priv_node_alloc()
  1572. , container_detail::addressof(p->value)
  1573. , ::boost::forward<ValueConvertible>(value_convertible));
  1574. //This does not throw
  1575. ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p))) node_base_type;
  1576. }
  1577. void priv_swap_members(stable_vector &x)
  1578. {
  1579. boost::container::swap_dispatch(this->internal_data.pool_size, x.internal_data.pool_size);
  1580. index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
  1581. index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
  1582. }
  1583. #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
  1584. bool priv_invariant()const
  1585. {
  1586. index_type & index_ref = const_cast<index_type&>(this->index);
  1587. if(index.empty())
  1588. return !this->capacity() && !this->size();
  1589. if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
  1590. return false;
  1591. }
  1592. if(!index_traits_type::invariants(index_ref)){
  1593. return false;
  1594. }
  1595. size_type n = this->capacity() - this->size();
  1596. node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
  1597. node_base_ptr &pool_last_ref = index_ref.back();
  1598. multiallocation_chain holder;
  1599. holder.incorporate_after( holder.before_begin()
  1600. , node_ptr_traits::static_cast_from(pool_first_ref)
  1601. , node_ptr_traits::static_cast_from(pool_last_ref)
  1602. , internal_data.pool_size);
  1603. typename multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
  1604. size_type num_pool = 0;
  1605. while(beg != end){
  1606. ++num_pool;
  1607. ++beg;
  1608. }
  1609. return n >= num_pool && num_pool == internal_data.pool_size;
  1610. }
  1611. class invariant_checker
  1612. {
  1613. invariant_checker(const invariant_checker &);
  1614. invariant_checker & operator=(const invariant_checker &);
  1615. const stable_vector* p;
  1616. public:
  1617. invariant_checker(const stable_vector& v):p(&v){}
  1618. ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
  1619. void touch(){}
  1620. };
  1621. #endif
  1622. class ebo_holder
  1623. : public node_allocator_type
  1624. {
  1625. private:
  1626. BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
  1627. public:
  1628. template<class AllocatorRLValue>
  1629. explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
  1630. : node_allocator_type(boost::forward<AllocatorRLValue>(a))
  1631. , pool_size(0)
  1632. , end_node()
  1633. {}
  1634. ebo_holder()
  1635. : node_allocator_type()
  1636. , pool_size(0)
  1637. , end_node()
  1638. {}
  1639. size_type pool_size;
  1640. node_base_type end_node;
  1641. } internal_data;
  1642. node_allocator_type &priv_node_alloc() { return internal_data; }
  1643. const node_allocator_type &priv_node_alloc() const { return internal_data; }
  1644. index_type index;
  1645. /// @endcond
  1646. };
  1647. template <typename T,typename Allocator>
  1648. bool operator==(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
  1649. {
  1650. return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
  1651. }
  1652. template <typename T,typename Allocator>
  1653. bool operator< (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
  1654. {
  1655. return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
  1656. }
  1657. template <typename T,typename Allocator>
  1658. bool operator!=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
  1659. {
  1660. return !(x==y);
  1661. }
  1662. template <typename T,typename Allocator>
  1663. bool operator> (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
  1664. {
  1665. return y<x;
  1666. }
  1667. template <typename T,typename Allocator>
  1668. bool operator>=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
  1669. {
  1670. return !(x<y);
  1671. }
  1672. template <typename T,typename Allocator>
  1673. bool operator<=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
  1674. {
  1675. return !(x>y);
  1676. }
  1677. // specialized algorithms:
  1678. template <typename T, typename Allocator>
  1679. void swap(stable_vector<T,Allocator>& x,stable_vector<T,Allocator>& y)
  1680. {
  1681. x.swap(y);
  1682. }
  1683. /// @cond
  1684. #undef STABLE_VECTOR_CHECK_INVARIANT
  1685. /// @endcond
  1686. /*
  1687. //!has_trivial_destructor_after_move<> == true_type
  1688. //!specialization for optimizations
  1689. template <class T, class Allocator>
  1690. struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
  1691. : public has_trivial_destructor_after_move<Allocator>::value
  1692. {};
  1693. */
  1694. }}
  1695. #include <boost/container/detail/config_end.hpp>
  1696. #endif //BOOST_CONTAINER_STABLE_VECTOR_HPP