annotate DEPENDENCIES/generic/include/boost/lockfree/detail/freelist.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // lock-free freelist
Chris@16 2 //
Chris@16 3 // Copyright (C) 2008-2013 Tim Blechmann
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_LOCKFREE_FREELIST_HPP_INCLUDED
Chris@16 10 #define BOOST_LOCKFREE_FREELIST_HPP_INCLUDED
Chris@16 11
Chris@16 12 #include <limits>
Chris@16 13 #include <memory>
Chris@16 14
Chris@16 15 #include <boost/array.hpp>
Chris@16 16 #include <boost/config.hpp>
Chris@16 17 #include <boost/cstdint.hpp>
Chris@16 18 #include <boost/noncopyable.hpp>
Chris@16 19 #include <boost/static_assert.hpp>
Chris@16 20
Chris@16 21 #include <boost/lockfree/detail/atomic.hpp>
Chris@16 22 #include <boost/lockfree/detail/parameter.hpp>
Chris@16 23 #include <boost/lockfree/detail/tagged_ptr.hpp>
Chris@16 24
Chris@16 25 #if defined(_MSC_VER)
Chris@16 26 #pragma warning(push)
Chris@16 27 #pragma warning(disable: 4100) // unreferenced formal parameter
Chris@16 28 #pragma warning(disable: 4127) // conditional expression is constant
Chris@16 29 #endif
Chris@16 30
Chris@16 31 namespace boost {
Chris@16 32 namespace lockfree {
Chris@16 33 namespace detail {
Chris@16 34
Chris@16 35 template <typename T,
Chris@16 36 typename Alloc = std::allocator<T>
Chris@16 37 >
Chris@16 38 class freelist_stack:
Chris@16 39 Alloc
Chris@16 40 {
Chris@16 41 struct freelist_node
Chris@16 42 {
Chris@16 43 tagged_ptr<freelist_node> next;
Chris@16 44 };
Chris@16 45
Chris@16 46 typedef tagged_ptr<freelist_node> tagged_node_ptr;
Chris@16 47
Chris@16 48 public:
Chris@16 49 typedef tagged_ptr<T> tagged_node_handle;
Chris@16 50
Chris@16 51 template <typename Allocator>
Chris@16 52 freelist_stack (Allocator const & alloc, std::size_t n = 0):
Chris@16 53 Alloc(alloc),
Chris@16 54 pool_(tagged_node_ptr(NULL))
Chris@16 55 {
Chris@16 56 for (std::size_t i = 0; i != n; ++i) {
Chris@16 57 T * node = Alloc::allocate(1);
Chris@16 58 #ifdef BOOST_LOCKFREE_FREELIST_INIT_RUNS_DTOR
Chris@16 59 destruct<false>(node);
Chris@16 60 #else
Chris@16 61 deallocate<false>(node);
Chris@16 62 #endif
Chris@16 63 }
Chris@16 64 }
Chris@16 65
Chris@16 66 template <bool ThreadSafe>
Chris@16 67 void reserve (std::size_t count)
Chris@16 68 {
Chris@16 69 for (std::size_t i = 0; i != count; ++i) {
Chris@16 70 T * node = Alloc::allocate(1);
Chris@16 71 deallocate<ThreadSafe>(node);
Chris@16 72 }
Chris@16 73 }
Chris@16 74
Chris@16 75 template <bool ThreadSafe, bool Bounded>
Chris@16 76 T * construct (void)
Chris@16 77 {
Chris@16 78 T * node = allocate<ThreadSafe, Bounded>();
Chris@16 79 if (node)
Chris@16 80 new(node) T();
Chris@16 81 return node;
Chris@16 82 }
Chris@16 83
Chris@16 84 template <bool ThreadSafe, bool Bounded, typename ArgumentType>
Chris@16 85 T * construct (ArgumentType const & arg)
Chris@16 86 {
Chris@16 87 T * node = allocate<ThreadSafe, Bounded>();
Chris@16 88 if (node)
Chris@16 89 new(node) T(arg);
Chris@16 90 return node;
Chris@16 91 }
Chris@16 92
Chris@16 93 template <bool ThreadSafe, bool Bounded, typename ArgumentType1, typename ArgumentType2>
Chris@16 94 T * construct (ArgumentType1 const & arg1, ArgumentType2 const & arg2)
Chris@16 95 {
Chris@16 96 T * node = allocate<ThreadSafe, Bounded>();
Chris@16 97 if (node)
Chris@16 98 new(node) T(arg1, arg2);
Chris@16 99 return node;
Chris@16 100 }
Chris@16 101
Chris@16 102 template <bool ThreadSafe>
Chris@16 103 void destruct (tagged_node_handle tagged_ptr)
Chris@16 104 {
Chris@16 105 T * n = tagged_ptr.get_ptr();
Chris@16 106 n->~T();
Chris@16 107 deallocate<ThreadSafe>(n);
Chris@16 108 }
Chris@16 109
Chris@16 110 template <bool ThreadSafe>
Chris@16 111 void destruct (T * n)
Chris@16 112 {
Chris@16 113 n->~T();
Chris@16 114 deallocate<ThreadSafe>(n);
Chris@16 115 }
Chris@16 116
Chris@16 117 ~freelist_stack(void)
Chris@16 118 {
Chris@16 119 tagged_node_ptr current = pool_.load();
Chris@16 120
Chris@16 121 while (current) {
Chris@16 122 freelist_node * current_ptr = current.get_ptr();
Chris@16 123 if (current_ptr)
Chris@16 124 current = current_ptr->next;
Chris@16 125 Alloc::deallocate((T*)current_ptr, 1);
Chris@16 126 }
Chris@16 127 }
Chris@16 128
Chris@16 129 bool is_lock_free(void) const
Chris@16 130 {
Chris@16 131 return pool_.is_lock_free();
Chris@16 132 }
Chris@16 133
Chris@16 134 T * get_handle(T * pointer) const
Chris@16 135 {
Chris@16 136 return pointer;
Chris@16 137 }
Chris@16 138
Chris@16 139 T * get_handle(tagged_node_handle const & handle) const
Chris@16 140 {
Chris@16 141 return get_pointer(handle);
Chris@16 142 }
Chris@16 143
Chris@16 144 T * get_pointer(tagged_node_handle const & tptr) const
Chris@16 145 {
Chris@16 146 return tptr.get_ptr();
Chris@16 147 }
Chris@16 148
Chris@16 149 T * get_pointer(T * pointer) const
Chris@16 150 {
Chris@16 151 return pointer;
Chris@16 152 }
Chris@16 153
Chris@16 154 T * null_handle(void) const
Chris@16 155 {
Chris@16 156 return NULL;
Chris@16 157 }
Chris@16 158
Chris@16 159 protected: // allow use from subclasses
Chris@16 160 template <bool ThreadSafe, bool Bounded>
Chris@16 161 T * allocate (void)
Chris@16 162 {
Chris@16 163 if (ThreadSafe)
Chris@16 164 return allocate_impl<Bounded>();
Chris@16 165 else
Chris@16 166 return allocate_impl_unsafe<Bounded>();
Chris@16 167 }
Chris@16 168
Chris@16 169 private:
Chris@16 170 template <bool Bounded>
Chris@16 171 T * allocate_impl (void)
Chris@16 172 {
Chris@16 173 tagged_node_ptr old_pool = pool_.load(memory_order_consume);
Chris@16 174
Chris@16 175 for(;;) {
Chris@16 176 if (!old_pool.get_ptr()) {
Chris@16 177 if (!Bounded)
Chris@16 178 return Alloc::allocate(1);
Chris@16 179 else
Chris@16 180 return 0;
Chris@16 181 }
Chris@16 182
Chris@16 183 freelist_node * new_pool_ptr = old_pool->next.get_ptr();
Chris@16 184 tagged_node_ptr new_pool (new_pool_ptr, old_pool.get_next_tag());
Chris@16 185
Chris@16 186 if (pool_.compare_exchange_weak(old_pool, new_pool)) {
Chris@16 187 void * ptr = old_pool.get_ptr();
Chris@16 188 return reinterpret_cast<T*>(ptr);
Chris@16 189 }
Chris@16 190 }
Chris@16 191 }
Chris@16 192
Chris@16 193 template <bool Bounded>
Chris@16 194 T * allocate_impl_unsafe (void)
Chris@16 195 {
Chris@16 196 tagged_node_ptr old_pool = pool_.load(memory_order_relaxed);
Chris@16 197
Chris@16 198 if (!old_pool.get_ptr()) {
Chris@16 199 if (!Bounded)
Chris@16 200 return Alloc::allocate(1);
Chris@16 201 else
Chris@16 202 return 0;
Chris@16 203 }
Chris@16 204
Chris@16 205 freelist_node * new_pool_ptr = old_pool->next.get_ptr();
Chris@16 206 tagged_node_ptr new_pool (new_pool_ptr, old_pool.get_next_tag());
Chris@16 207
Chris@16 208 pool_.store(new_pool, memory_order_relaxed);
Chris@16 209 void * ptr = old_pool.get_ptr();
Chris@16 210 return reinterpret_cast<T*>(ptr);
Chris@16 211 }
Chris@16 212
Chris@16 213 protected:
Chris@16 214 template <bool ThreadSafe>
Chris@16 215 void deallocate (T * n)
Chris@16 216 {
Chris@16 217 if (ThreadSafe)
Chris@16 218 deallocate_impl(n);
Chris@16 219 else
Chris@16 220 deallocate_impl_unsafe(n);
Chris@16 221 }
Chris@16 222
Chris@16 223 private:
Chris@16 224 void deallocate_impl (T * n)
Chris@16 225 {
Chris@16 226 void * node = n;
Chris@16 227 tagged_node_ptr old_pool = pool_.load(memory_order_consume);
Chris@16 228 freelist_node * new_pool_ptr = reinterpret_cast<freelist_node*>(node);
Chris@16 229
Chris@16 230 for(;;) {
Chris@16 231 tagged_node_ptr new_pool (new_pool_ptr, old_pool.get_tag());
Chris@16 232 new_pool->next.set_ptr(old_pool.get_ptr());
Chris@16 233
Chris@16 234 if (pool_.compare_exchange_weak(old_pool, new_pool))
Chris@16 235 return;
Chris@16 236 }
Chris@16 237 }
Chris@16 238
Chris@16 239 void deallocate_impl_unsafe (T * n)
Chris@16 240 {
Chris@16 241 void * node = n;
Chris@16 242 tagged_node_ptr old_pool = pool_.load(memory_order_relaxed);
Chris@16 243 freelist_node * new_pool_ptr = reinterpret_cast<freelist_node*>(node);
Chris@16 244
Chris@16 245 tagged_node_ptr new_pool (new_pool_ptr, old_pool.get_tag());
Chris@16 246 new_pool->next.set_ptr(old_pool.get_ptr());
Chris@16 247
Chris@16 248 pool_.store(new_pool, memory_order_relaxed);
Chris@16 249 }
Chris@16 250
Chris@16 251 atomic<tagged_node_ptr> pool_;
Chris@16 252 };
Chris@16 253
Chris@16 254 class tagged_index
Chris@16 255 {
Chris@16 256 public:
Chris@16 257 typedef boost::uint16_t tag_t;
Chris@16 258 typedef boost::uint16_t index_t;
Chris@16 259
Chris@16 260 /** uninitialized constructor */
Chris@16 261 tagged_index(void) BOOST_NOEXCEPT //: index(0), tag(0)
Chris@16 262 {}
Chris@16 263
Chris@16 264 /** copy constructor */
Chris@16 265 #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
Chris@16 266 tagged_index(tagged_index const & rhs):
Chris@16 267 index(rhs.index), tag(rhs.tag)
Chris@16 268 {}
Chris@16 269 #else
Chris@16 270 tagged_index(tagged_index const & rhs) = default;
Chris@16 271 #endif
Chris@16 272
Chris@16 273 explicit tagged_index(index_t i, tag_t t = 0):
Chris@16 274 index(i), tag(t)
Chris@16 275 {}
Chris@16 276
Chris@16 277 /** index access */
Chris@16 278 /* @{ */
Chris@16 279 index_t get_index() const
Chris@16 280 {
Chris@16 281 return index;
Chris@16 282 }
Chris@16 283
Chris@16 284 void set_index(index_t i)
Chris@16 285 {
Chris@16 286 index = i;
Chris@16 287 }
Chris@16 288 /* @} */
Chris@16 289
Chris@16 290 /** tag access */
Chris@16 291 /* @{ */
Chris@16 292 tag_t get_tag() const
Chris@16 293 {
Chris@16 294 return tag;
Chris@16 295 }
Chris@16 296
Chris@16 297 tag_t get_next_tag() const
Chris@16 298 {
Chris@16 299 tag_t next = (get_tag() + 1) & (std::numeric_limits<tag_t>::max)();
Chris@16 300 return next;
Chris@16 301 }
Chris@16 302
Chris@16 303 void set_tag(tag_t t)
Chris@16 304 {
Chris@16 305 tag = t;
Chris@16 306 }
Chris@16 307 /* @} */
Chris@16 308
Chris@16 309 bool operator==(tagged_index const & rhs) const
Chris@16 310 {
Chris@16 311 return (index == rhs.index) && (tag == rhs.tag);
Chris@16 312 }
Chris@16 313
Chris@16 314 bool operator!=(tagged_index const & rhs) const
Chris@16 315 {
Chris@16 316 return !operator==(rhs);
Chris@16 317 }
Chris@16 318
Chris@16 319 protected:
Chris@16 320 index_t index;
Chris@16 321 tag_t tag;
Chris@16 322 };
Chris@16 323
Chris@16 324 template <typename T,
Chris@16 325 std::size_t size>
Chris@16 326 struct compiletime_sized_freelist_storage
Chris@16 327 {
Chris@16 328 // array-based freelists only support a 16bit address space.
Chris@16 329 BOOST_STATIC_ASSERT(size < 65536);
Chris@16 330
Chris@16 331 boost::array<char, size * sizeof(T)> data;
Chris@16 332
Chris@16 333 // unused ... only for API purposes
Chris@16 334 template <typename Allocator>
Chris@16 335 compiletime_sized_freelist_storage(Allocator const & /* alloc */, std::size_t /* count */)
Chris@16 336 {}
Chris@16 337
Chris@16 338 T * nodes(void) const
Chris@16 339 {
Chris@16 340 return reinterpret_cast<T*>(const_cast<char*>(data.data()));
Chris@16 341 }
Chris@16 342
Chris@16 343 std::size_t node_count(void) const
Chris@16 344 {
Chris@16 345 return size;
Chris@16 346 }
Chris@16 347 };
Chris@16 348
Chris@16 349 template <typename T,
Chris@16 350 typename Alloc = std::allocator<T> >
Chris@16 351 struct runtime_sized_freelist_storage:
Chris@16 352 Alloc
Chris@16 353 {
Chris@16 354 T * nodes_;
Chris@16 355 std::size_t node_count_;
Chris@16 356
Chris@16 357 template <typename Allocator>
Chris@16 358 runtime_sized_freelist_storage(Allocator const & alloc, std::size_t count):
Chris@16 359 Alloc(alloc), node_count_(count)
Chris@16 360 {
Chris@16 361 if (count > 65535)
Chris@16 362 boost::throw_exception(std::runtime_error("boost.lockfree: freelist size is limited to a maximum of 65535 objects"));
Chris@16 363 nodes_ = Alloc::allocate(count);
Chris@16 364 }
Chris@16 365
Chris@16 366 ~runtime_sized_freelist_storage(void)
Chris@16 367 {
Chris@16 368 Alloc::deallocate(nodes_, node_count_);
Chris@16 369 }
Chris@16 370
Chris@16 371 T * nodes(void) const
Chris@16 372 {
Chris@16 373 return nodes_;
Chris@16 374 }
Chris@16 375
Chris@16 376 std::size_t node_count(void) const
Chris@16 377 {
Chris@16 378 return node_count_;
Chris@16 379 }
Chris@16 380 };
Chris@16 381
Chris@16 382
Chris@16 383 template <typename T,
Chris@16 384 typename NodeStorage = runtime_sized_freelist_storage<T>
Chris@16 385 >
Chris@16 386 class fixed_size_freelist:
Chris@16 387 NodeStorage
Chris@16 388 {
Chris@16 389 struct freelist_node
Chris@16 390 {
Chris@16 391 tagged_index next;
Chris@16 392 };
Chris@16 393
Chris@16 394 typedef tagged_index::index_t index_t;
Chris@16 395
Chris@16 396 void initialize(void)
Chris@16 397 {
Chris@16 398 T * nodes = NodeStorage::nodes();
Chris@16 399 for (std::size_t i = 0; i != NodeStorage::node_count(); ++i) {
Chris@16 400 tagged_index * next_index = reinterpret_cast<tagged_index*>(nodes + i);
Chris@16 401 next_index->set_index(null_handle());
Chris@16 402
Chris@16 403 #ifdef BOOST_LOCKFREE_FREELIST_INIT_RUNS_DTOR
Chris@16 404 destruct<false>(nodes + i);
Chris@16 405 #else
Chris@16 406 deallocate<false>(static_cast<index_t>(i));
Chris@16 407 #endif
Chris@16 408 }
Chris@16 409 }
Chris@16 410
Chris@16 411 public:
Chris@16 412 typedef tagged_index tagged_node_handle;
Chris@16 413
Chris@16 414 template <typename Allocator>
Chris@16 415 fixed_size_freelist (Allocator const & alloc, std::size_t count):
Chris@16 416 NodeStorage(alloc, count),
Chris@16 417 pool_(tagged_index(static_cast<index_t>(count), 0))
Chris@16 418 {
Chris@16 419 initialize();
Chris@16 420 }
Chris@16 421
Chris@16 422 fixed_size_freelist (void):
Chris@16 423 pool_(tagged_index(NodeStorage::node_count(), 0))
Chris@16 424 {
Chris@16 425 initialize();
Chris@16 426 }
Chris@16 427
Chris@16 428 template <bool ThreadSafe, bool Bounded>
Chris@16 429 T * construct (void)
Chris@16 430 {
Chris@16 431 index_t node_index = allocate<ThreadSafe>();
Chris@16 432 if (node_index == null_handle())
Chris@16 433 return NULL;
Chris@16 434
Chris@16 435 T * node = NodeStorage::nodes() + node_index;
Chris@16 436 new(node) T();
Chris@16 437 return node;
Chris@16 438 }
Chris@16 439
Chris@16 440 template <bool ThreadSafe, bool Bounded, typename ArgumentType>
Chris@16 441 T * construct (ArgumentType const & arg)
Chris@16 442 {
Chris@16 443 index_t node_index = allocate<ThreadSafe>();
Chris@16 444 if (node_index == null_handle())
Chris@16 445 return NULL;
Chris@16 446
Chris@16 447 T * node = NodeStorage::nodes() + node_index;
Chris@16 448 new(node) T(arg);
Chris@16 449 return node;
Chris@16 450 }
Chris@16 451
Chris@16 452 template <bool ThreadSafe, bool Bounded, typename ArgumentType1, typename ArgumentType2>
Chris@16 453 T * construct (ArgumentType1 const & arg1, ArgumentType2 const & arg2)
Chris@16 454 {
Chris@16 455 index_t node_index = allocate<ThreadSafe>();
Chris@16 456 if (node_index == null_handle())
Chris@16 457 return NULL;
Chris@16 458
Chris@16 459 T * node = NodeStorage::nodes() + node_index;
Chris@16 460 new(node) T(arg1, arg2);
Chris@16 461 return node;
Chris@16 462 }
Chris@16 463
Chris@16 464 template <bool ThreadSafe>
Chris@16 465 void destruct (tagged_node_handle tagged_index)
Chris@16 466 {
Chris@16 467 index_t index = tagged_index.get_index();
Chris@16 468 T * n = NodeStorage::nodes() + index;
Chris@16 469 n->~T();
Chris@16 470 deallocate<ThreadSafe>(index);
Chris@16 471 }
Chris@16 472
Chris@16 473 template <bool ThreadSafe>
Chris@16 474 void destruct (T * n)
Chris@16 475 {
Chris@16 476 n->~T();
Chris@16 477 deallocate<ThreadSafe>(n - NodeStorage::nodes());
Chris@16 478 }
Chris@16 479
Chris@16 480 bool is_lock_free(void) const
Chris@16 481 {
Chris@16 482 return pool_.is_lock_free();
Chris@16 483 }
Chris@16 484
Chris@16 485 index_t null_handle(void) const
Chris@16 486 {
Chris@16 487 return static_cast<index_t>(NodeStorage::node_count());
Chris@16 488 }
Chris@16 489
Chris@16 490 index_t get_handle(T * pointer) const
Chris@16 491 {
Chris@16 492 if (pointer == NULL)
Chris@16 493 return null_handle();
Chris@16 494 else
Chris@16 495 return static_cast<index_t>(pointer - NodeStorage::nodes());
Chris@16 496 }
Chris@16 497
Chris@16 498 index_t get_handle(tagged_node_handle const & handle) const
Chris@16 499 {
Chris@16 500 return handle.get_index();
Chris@16 501 }
Chris@16 502
Chris@16 503 T * get_pointer(tagged_node_handle const & tptr) const
Chris@16 504 {
Chris@16 505 return get_pointer(tptr.get_index());
Chris@16 506 }
Chris@16 507
Chris@16 508 T * get_pointer(index_t index) const
Chris@16 509 {
Chris@16 510 if (index == null_handle())
Chris@16 511 return 0;
Chris@16 512 else
Chris@16 513 return NodeStorage::nodes() + index;
Chris@16 514 }
Chris@16 515
Chris@16 516 T * get_pointer(T * ptr) const
Chris@16 517 {
Chris@16 518 return ptr;
Chris@16 519 }
Chris@16 520
Chris@16 521 protected: // allow use from subclasses
Chris@16 522 template <bool ThreadSafe>
Chris@16 523 index_t allocate (void)
Chris@16 524 {
Chris@16 525 if (ThreadSafe)
Chris@16 526 return allocate_impl();
Chris@16 527 else
Chris@16 528 return allocate_impl_unsafe();
Chris@16 529 }
Chris@16 530
Chris@16 531 private:
Chris@16 532 index_t allocate_impl (void)
Chris@16 533 {
Chris@16 534 tagged_index old_pool = pool_.load(memory_order_consume);
Chris@16 535
Chris@16 536 for(;;) {
Chris@16 537 index_t index = old_pool.get_index();
Chris@16 538 if (index == null_handle())
Chris@16 539 return index;
Chris@16 540
Chris@16 541 T * old_node = NodeStorage::nodes() + index;
Chris@16 542 tagged_index * next_index = reinterpret_cast<tagged_index*>(old_node);
Chris@16 543
Chris@16 544 tagged_index new_pool(next_index->get_index(), old_pool.get_next_tag());
Chris@16 545
Chris@16 546 if (pool_.compare_exchange_weak(old_pool, new_pool))
Chris@16 547 return old_pool.get_index();
Chris@16 548 }
Chris@16 549 }
Chris@16 550
Chris@16 551 index_t allocate_impl_unsafe (void)
Chris@16 552 {
Chris@16 553 tagged_index old_pool = pool_.load(memory_order_consume);
Chris@16 554
Chris@16 555 index_t index = old_pool.get_index();
Chris@16 556 if (index == null_handle())
Chris@16 557 return index;
Chris@16 558
Chris@16 559 T * old_node = NodeStorage::nodes() + index;
Chris@16 560 tagged_index * next_index = reinterpret_cast<tagged_index*>(old_node);
Chris@16 561
Chris@16 562 tagged_index new_pool(next_index->get_index(), old_pool.get_next_tag());
Chris@16 563
Chris@16 564 pool_.store(new_pool, memory_order_relaxed);
Chris@16 565 return old_pool.get_index();
Chris@16 566 }
Chris@16 567
Chris@16 568 template <bool ThreadSafe>
Chris@16 569 void deallocate (index_t index)
Chris@16 570 {
Chris@16 571 if (ThreadSafe)
Chris@16 572 deallocate_impl(index);
Chris@16 573 else
Chris@16 574 deallocate_impl_unsafe(index);
Chris@16 575 }
Chris@16 576
Chris@16 577 void deallocate_impl (index_t index)
Chris@16 578 {
Chris@16 579 freelist_node * new_pool_node = reinterpret_cast<freelist_node*>(NodeStorage::nodes() + index);
Chris@16 580 tagged_index old_pool = pool_.load(memory_order_consume);
Chris@16 581
Chris@16 582 for(;;) {
Chris@16 583 tagged_index new_pool (index, old_pool.get_tag());
Chris@16 584 new_pool_node->next.set_index(old_pool.get_index());
Chris@16 585
Chris@16 586 if (pool_.compare_exchange_weak(old_pool, new_pool))
Chris@16 587 return;
Chris@16 588 }
Chris@16 589 }
Chris@16 590
Chris@16 591 void deallocate_impl_unsafe (index_t index)
Chris@16 592 {
Chris@16 593 freelist_node * new_pool_node = reinterpret_cast<freelist_node*>(NodeStorage::nodes() + index);
Chris@16 594 tagged_index old_pool = pool_.load(memory_order_consume);
Chris@16 595
Chris@16 596 tagged_index new_pool (index, old_pool.get_tag());
Chris@16 597 new_pool_node->next.set_index(old_pool.get_index());
Chris@16 598
Chris@16 599 pool_.store(new_pool);
Chris@16 600 }
Chris@16 601
Chris@16 602 atomic<tagged_index> pool_;
Chris@16 603 };
Chris@16 604
Chris@16 605 template <typename T,
Chris@16 606 typename Alloc,
Chris@16 607 bool IsCompileTimeSized,
Chris@16 608 bool IsFixedSize,
Chris@16 609 std::size_t Capacity
Chris@16 610 >
Chris@16 611 struct select_freelist
Chris@16 612 {
Chris@16 613 typedef typename mpl::if_c<IsCompileTimeSized,
Chris@16 614 compiletime_sized_freelist_storage<T, Capacity>,
Chris@16 615 runtime_sized_freelist_storage<T, Alloc>
Chris@16 616 >::type fixed_sized_storage_type;
Chris@16 617
Chris@16 618 typedef typename mpl::if_c<IsCompileTimeSized || IsFixedSize,
Chris@16 619 fixed_size_freelist<T, fixed_sized_storage_type>,
Chris@16 620 freelist_stack<T, Alloc>
Chris@16 621 >::type type;
Chris@16 622 };
Chris@16 623
Chris@16 624 template <typename T, bool IsNodeBased>
Chris@16 625 struct select_tagged_handle
Chris@16 626 {
Chris@16 627 typedef typename mpl::if_c<IsNodeBased,
Chris@16 628 tagged_ptr<T>,
Chris@16 629 tagged_index
Chris@16 630 >::type tagged_handle_type;
Chris@16 631
Chris@16 632 typedef typename mpl::if_c<IsNodeBased,
Chris@16 633 T*,
Chris@16 634 typename tagged_index::index_t
Chris@16 635 >::type handle_type;
Chris@16 636 };
Chris@16 637
Chris@16 638
Chris@16 639 } /* namespace detail */
Chris@16 640 } /* namespace lockfree */
Chris@16 641 } /* namespace boost */
Chris@16 642
Chris@16 643 #if defined(_MSC_VER)
Chris@16 644 #pragma warning(pop)
Chris@16 645 #endif
Chris@16 646
Chris@16 647
Chris@16 648 #endif /* BOOST_LOCKFREE_FREELIST_HPP_INCLUDED */