annotate DEPENDENCIES/generic/include/boost/thread/sync_queue.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 #ifndef BOOST_THREAD_SYNC_QUEUE_HPP
Chris@16 2 #define BOOST_THREAD_SYNC_QUEUE_HPP
Chris@16 3
Chris@16 4 //////////////////////////////////////////////////////////////////////////////
Chris@16 5 //
Chris@16 6 // (C) Copyright Vicente J. Botet Escriba 2013. Distributed under the Boost
Chris@16 7 // Software License, Version 1.0. (See accompanying file
Chris@16 8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //
Chris@16 10 // See http://www.boost.org/libs/thread for documentation.
Chris@16 11 //
Chris@16 12 //////////////////////////////////////////////////////////////////////////////
Chris@16 13
Chris@16 14 #include <boost/thread/detail/config.hpp>
Chris@16 15 #include <boost/thread/condition_variable.hpp>
Chris@16 16 #include <boost/thread/mutex.hpp>
Chris@16 17 #include <boost/thread/detail/move.hpp>
Chris@16 18 #include <boost/throw_exception.hpp>
Chris@16 19 #include <boost/smart_ptr/shared_ptr.hpp>
Chris@16 20 #include <boost/smart_ptr/make_shared.hpp>
Chris@16 21
Chris@16 22 #include <boost/thread/sync_bounded_queue.hpp>
Chris@16 23 #include <boost/container/deque.hpp>
Chris@16 24
Chris@16 25 #include <boost/config/abi_prefix.hpp>
Chris@16 26
Chris@16 27 namespace boost
Chris@16 28 {
Chris@16 29
Chris@16 30
Chris@16 31 template <typename ValueType>
Chris@16 32 class sync_queue
Chris@16 33 {
Chris@16 34 public:
Chris@16 35 typedef ValueType value_type;
Chris@16 36 typedef std::size_t size_type;
Chris@16 37
Chris@16 38 // Constructors/Assignment/Destructors
Chris@16 39 BOOST_THREAD_NO_COPYABLE(sync_queue)
Chris@16 40 inline sync_queue();
Chris@16 41 //template <typename Range>
Chris@16 42 //inline explicit sync_queue(Range range);
Chris@16 43 inline ~sync_queue();
Chris@16 44
Chris@16 45 // Observers
Chris@16 46 inline bool empty() const;
Chris@16 47 inline bool full() const;
Chris@16 48 inline size_type size() const;
Chris@16 49 inline bool closed() const;
Chris@16 50
Chris@16 51 // Modifiers
Chris@16 52 inline void close();
Chris@16 53
Chris@16 54 inline void push(const value_type& x);
Chris@16 55 inline void push(BOOST_THREAD_RV_REF(value_type) x);
Chris@16 56 inline bool try_push(const value_type& x);
Chris@16 57 inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
Chris@16 58 inline bool try_push(no_block_tag, const value_type& x);
Chris@16 59 inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
Chris@16 60
Chris@16 61 // Observers/Modifiers
Chris@16 62 inline void pull(value_type&);
Chris@16 63 inline void pull(ValueType& elem, bool & closed);
Chris@16 64 // enable_if is_nothrow_copy_movable<value_type>
Chris@16 65 inline value_type pull();
Chris@16 66 inline shared_ptr<ValueType> ptr_pull();
Chris@16 67 inline bool try_pull(value_type&);
Chris@16 68 inline bool try_pull(no_block_tag,value_type&);
Chris@16 69 inline shared_ptr<ValueType> try_pull();
Chris@16 70
Chris@16 71 private:
Chris@16 72 mutable mutex mtx_;
Chris@16 73 condition_variable not_empty_;
Chris@16 74 size_type waiting_empty_;
Chris@16 75 boost::container::deque<ValueType> data_;
Chris@16 76 bool closed_;
Chris@16 77
Chris@16 78 inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
Chris@16 79 {
Chris@16 80 return data_.empty();
Chris@16 81 }
Chris@16 82 inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
Chris@16 83 {
Chris@16 84 return data_.empty();
Chris@16 85 }
Chris@16 86
Chris@16 87 inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
Chris@16 88 {
Chris@16 89 return data_.size();
Chris@16 90 }
Chris@16 91
Chris@16 92 inline void throw_if_closed(unique_lock<mutex>&);
Chris@16 93
Chris@16 94 inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
Chris@16 95 inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
Chris@16 96 inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
Chris@16 97 inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
Chris@16 98
Chris@16 99 inline void wait_until_not_empty(unique_lock<mutex>& lk);
Chris@16 100 inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
Chris@16 101
Chris@16 102 inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
Chris@16 103 {
Chris@16 104 if (waiting_empty_ > 0)
Chris@16 105 {
Chris@16 106 --waiting_empty_;
Chris@16 107 lk.unlock();
Chris@16 108 not_empty_.notify_one();
Chris@16 109 }
Chris@16 110 }
Chris@16 111
Chris@16 112 inline void pull(value_type& elem, unique_lock<mutex>& )
Chris@16 113 {
Chris@16 114 elem = boost::move(data_.front());
Chris@16 115 data_.pop_front();
Chris@16 116 }
Chris@16 117 inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
Chris@16 118 {
Chris@16 119 shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_.front()));
Chris@16 120 data_.pop_front();
Chris@16 121 return res;
Chris@16 122 }
Chris@16 123
Chris@16 124 inline void push(const value_type& elem, unique_lock<mutex>& lk)
Chris@16 125 {
Chris@16 126 data_.push_back(elem);
Chris@16 127 notify_not_empty_if_needed(lk);
Chris@16 128 }
Chris@16 129
Chris@16 130 inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
Chris@16 131 {
Chris@16 132 data_.push(boost::move(elem));
Chris@16 133 notify_not_empty_if_needed(lk);
Chris@16 134 }
Chris@16 135 };
Chris@16 136
Chris@16 137 template <typename ValueType>
Chris@16 138 sync_queue<ValueType>::sync_queue() :
Chris@16 139 waiting_empty_(0), data_(), closed_(false)
Chris@16 140 {
Chris@16 141 BOOST_ASSERT(data_.empty());
Chris@16 142 }
Chris@16 143
Chris@16 144 // template <typename ValueType>
Chris@16 145 // template <typename Range>
Chris@16 146 // explicit sync_queue<ValueType>::sync_queue(Range range) :
Chris@16 147 // waiting_empty_(0), data_(), closed_(false)
Chris@16 148 // {
Chris@16 149 // try
Chris@16 150 // {
Chris@16 151 // typedef typename Range::iterator iterator_t;
Chris@16 152 // iterator_t first = boost::begin(range);
Chris@16 153 // iterator_t end = boost::end(range);
Chris@16 154 // for (iterator_t cur = first; cur != end; ++cur)
Chris@16 155 // {
Chris@16 156 // data_.push(boost::move(*cur));;
Chris@16 157 // }
Chris@16 158 // notify_not_empty_if_needed(lk);
Chris@16 159 // }
Chris@16 160 // catch (...)
Chris@16 161 // {
Chris@16 162 // delete[] data_;
Chris@16 163 // }
Chris@16 164 // }
Chris@16 165
Chris@16 166 template <typename ValueType>
Chris@16 167 sync_queue<ValueType>::~sync_queue()
Chris@16 168 {
Chris@16 169 }
Chris@16 170
Chris@16 171 template <typename ValueType>
Chris@16 172 void sync_queue<ValueType>::close()
Chris@16 173 {
Chris@16 174 {
Chris@16 175 lock_guard<mutex> lk(mtx_);
Chris@16 176 closed_ = true;
Chris@16 177 }
Chris@16 178 not_empty_.notify_all();
Chris@16 179 }
Chris@16 180
Chris@16 181 template <typename ValueType>
Chris@16 182 bool sync_queue<ValueType>::closed() const
Chris@16 183 {
Chris@16 184 lock_guard<mutex> lk(mtx_);
Chris@16 185 return closed_;
Chris@16 186 }
Chris@16 187
Chris@16 188 template <typename ValueType>
Chris@16 189 bool sync_queue<ValueType>::empty() const
Chris@16 190 {
Chris@16 191 lock_guard<mutex> lk(mtx_);
Chris@16 192 return empty(lk);
Chris@16 193 }
Chris@16 194 template <typename ValueType>
Chris@16 195 bool sync_queue<ValueType>::full() const
Chris@16 196 {
Chris@16 197 return false;
Chris@16 198 }
Chris@16 199
Chris@16 200 template <typename ValueType>
Chris@16 201 typename sync_queue<ValueType>::size_type sync_queue<ValueType>::size() const
Chris@16 202 {
Chris@16 203 lock_guard<mutex> lk(mtx_);
Chris@16 204 return size(lk);
Chris@16 205 }
Chris@16 206
Chris@16 207
Chris@16 208 template <typename ValueType>
Chris@16 209 bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
Chris@16 210 {
Chris@16 211 if (empty(lk))
Chris@16 212 {
Chris@16 213 throw_if_closed(lk);
Chris@16 214 return false;
Chris@16 215 }
Chris@16 216 pull(elem, lk);
Chris@16 217 return true;
Chris@16 218 }
Chris@16 219 template <typename ValueType>
Chris@16 220 shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
Chris@16 221 {
Chris@16 222 if (empty(lk))
Chris@16 223 {
Chris@16 224 throw_if_closed(lk);
Chris@16 225 return shared_ptr<ValueType>();
Chris@16 226 }
Chris@16 227 return ptr_pull(lk);
Chris@16 228 }
Chris@16 229
Chris@16 230 template <typename ValueType>
Chris@16 231 bool sync_queue<ValueType>::try_pull(ValueType& elem)
Chris@16 232 {
Chris@16 233 try
Chris@16 234 {
Chris@16 235 unique_lock<mutex> lk(mtx_);
Chris@16 236 return try_pull(elem, lk);
Chris@16 237 }
Chris@16 238 catch (...)
Chris@16 239 {
Chris@16 240 close();
Chris@16 241 throw;
Chris@16 242 }
Chris@16 243 }
Chris@16 244
Chris@16 245 template <typename ValueType>
Chris@16 246 bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
Chris@16 247 {
Chris@16 248 try
Chris@16 249 {
Chris@16 250 unique_lock<mutex> lk(mtx_, try_to_lock);
Chris@16 251 if (!lk.owns_lock())
Chris@16 252 {
Chris@16 253 return false;
Chris@16 254 }
Chris@16 255 return try_pull(elem, lk);
Chris@16 256 }
Chris@16 257 catch (...)
Chris@16 258 {
Chris@16 259 close();
Chris@16 260 throw;
Chris@16 261 }
Chris@16 262 }
Chris@16 263 template <typename ValueType>
Chris@16 264 boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
Chris@16 265 {
Chris@16 266 try
Chris@16 267 {
Chris@16 268 unique_lock<mutex> lk(mtx_);
Chris@16 269 return try_pull(lk);
Chris@16 270 }
Chris@16 271 catch (...)
Chris@16 272 {
Chris@16 273 close();
Chris@16 274 throw;
Chris@16 275 }
Chris@16 276 }
Chris@16 277
Chris@16 278 template <typename ValueType>
Chris@16 279 void sync_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
Chris@16 280 {
Chris@16 281 if (closed_)
Chris@16 282 {
Chris@16 283 BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
Chris@16 284 }
Chris@16 285 }
Chris@16 286
Chris@16 287 template <typename ValueType>
Chris@16 288 void sync_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
Chris@16 289 {
Chris@16 290 for (;;)
Chris@16 291 {
Chris@16 292 if (! empty(lk)) break;
Chris@16 293 throw_if_closed(lk);
Chris@16 294 ++waiting_empty_;
Chris@16 295 not_empty_.wait(lk);
Chris@16 296 }
Chris@16 297 }
Chris@16 298 template <typename ValueType>
Chris@16 299 void sync_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
Chris@16 300 {
Chris@16 301 for (;;)
Chris@16 302 {
Chris@16 303 if (! empty(lk)) break;
Chris@16 304 if (closed_) {closed=true; return;}
Chris@16 305 ++waiting_empty_;
Chris@16 306 not_empty_.wait(lk);
Chris@16 307 }
Chris@16 308 closed=false;
Chris@16 309 }
Chris@16 310
Chris@16 311 template <typename ValueType>
Chris@16 312 void sync_queue<ValueType>::pull(ValueType& elem)
Chris@16 313 {
Chris@16 314 try
Chris@16 315 {
Chris@16 316 unique_lock<mutex> lk(mtx_);
Chris@16 317 wait_until_not_empty(lk);
Chris@16 318 pull(elem, lk);
Chris@16 319 }
Chris@16 320 catch (...)
Chris@16 321 {
Chris@16 322 close();
Chris@16 323 throw;
Chris@16 324 }
Chris@16 325 }
Chris@16 326 template <typename ValueType>
Chris@16 327 void sync_queue<ValueType>::pull(ValueType& elem, bool & closed)
Chris@16 328 {
Chris@16 329 try
Chris@16 330 {
Chris@16 331 unique_lock<mutex> lk(mtx_);
Chris@16 332 wait_until_not_empty(lk, closed);
Chris@16 333 if (closed) {return;}
Chris@16 334 pull(elem, lk);
Chris@16 335 }
Chris@16 336 catch (...)
Chris@16 337 {
Chris@16 338 close();
Chris@16 339 throw;
Chris@16 340 }
Chris@16 341 }
Chris@16 342
Chris@16 343 // enable if ValueType is nothrow movable
Chris@16 344 template <typename ValueType>
Chris@16 345 ValueType sync_queue<ValueType>::pull()
Chris@16 346 {
Chris@16 347 try
Chris@16 348 {
Chris@16 349 value_type elem;
Chris@16 350 pull(elem);
Chris@16 351 return boost::move(elem);
Chris@16 352 }
Chris@16 353 catch (...)
Chris@16 354 {
Chris@16 355 close();
Chris@16 356 throw;
Chris@16 357 }
Chris@16 358 }
Chris@16 359 template <typename ValueType>
Chris@16 360 boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
Chris@16 361 {
Chris@16 362 try
Chris@16 363 {
Chris@16 364 unique_lock<mutex> lk(mtx_);
Chris@16 365 wait_until_not_empty(lk);
Chris@16 366 return ptr_pull(lk);
Chris@16 367 }
Chris@16 368 catch (...)
Chris@16 369 {
Chris@16 370 close();
Chris@16 371 throw;
Chris@16 372 }
Chris@16 373 }
Chris@16 374
Chris@16 375 template <typename ValueType>
Chris@16 376 bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
Chris@16 377 {
Chris@16 378 throw_if_closed(lk);
Chris@16 379 push(elem, lk);
Chris@16 380 return true;
Chris@16 381 }
Chris@16 382
Chris@16 383 template <typename ValueType>
Chris@16 384 bool sync_queue<ValueType>::try_push(const ValueType& elem)
Chris@16 385 {
Chris@16 386 try
Chris@16 387 {
Chris@16 388 unique_lock<mutex> lk(mtx_);
Chris@16 389 return try_push(elem, lk);
Chris@16 390 }
Chris@16 391 catch (...)
Chris@16 392 {
Chris@16 393 close();
Chris@16 394 throw;
Chris@16 395 }
Chris@16 396 }
Chris@16 397
Chris@16 398 template <typename ValueType>
Chris@16 399 bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
Chris@16 400 {
Chris@16 401 try
Chris@16 402 {
Chris@16 403 unique_lock<mutex> lk(mtx_, try_to_lock);
Chris@16 404 if (!lk.owns_lock()) return false;
Chris@16 405 return try_push(elem, lk);
Chris@16 406 }
Chris@16 407 catch (...)
Chris@16 408 {
Chris@16 409 close();
Chris@16 410 throw;
Chris@16 411 }
Chris@16 412 }
Chris@16 413
Chris@16 414 template <typename ValueType>
Chris@16 415 void sync_queue<ValueType>::push(const ValueType& elem)
Chris@16 416 {
Chris@16 417 try
Chris@16 418 {
Chris@16 419 unique_lock<mutex> lk(mtx_);
Chris@16 420 throw_if_closed(lk);
Chris@16 421 push(elem, lk);
Chris@16 422 }
Chris@16 423 catch (...)
Chris@16 424 {
Chris@16 425 close();
Chris@16 426 throw;
Chris@16 427 }
Chris@16 428 }
Chris@16 429
Chris@16 430 template <typename ValueType>
Chris@16 431 bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
Chris@16 432 {
Chris@16 433 throw_if_closed(lk);
Chris@16 434 push(boost::forward<ValueType>(elem), lk);
Chris@16 435 return true;
Chris@16 436 }
Chris@16 437
Chris@16 438 template <typename ValueType>
Chris@16 439 bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
Chris@16 440 {
Chris@16 441 try
Chris@16 442 {
Chris@16 443 unique_lock<mutex> lk(mtx_);
Chris@16 444 return try_push(elem, lk);
Chris@16 445 }
Chris@16 446 catch (...)
Chris@16 447 {
Chris@16 448 close();
Chris@16 449 throw;
Chris@16 450 }
Chris@16 451 }
Chris@16 452
Chris@16 453 template <typename ValueType>
Chris@16 454 bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
Chris@16 455 {
Chris@16 456 try
Chris@16 457 {
Chris@16 458 unique_lock<mutex> lk(mtx_, try_to_lock);
Chris@16 459 if (!lk.owns_lock())
Chris@16 460 {
Chris@16 461 return false;
Chris@16 462 }
Chris@16 463 return try_push(elem, lk);
Chris@16 464 }
Chris@16 465 catch (...)
Chris@16 466 {
Chris@16 467 close();
Chris@16 468 throw;
Chris@16 469 }
Chris@16 470 }
Chris@16 471
Chris@16 472 template <typename ValueType>
Chris@16 473 void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
Chris@16 474 {
Chris@16 475 try
Chris@16 476 {
Chris@16 477 unique_lock<mutex> lk(mtx_);
Chris@16 478 throw_if_closed(lk);
Chris@16 479 push(elem, lk);
Chris@16 480 }
Chris@16 481 catch (...)
Chris@16 482 {
Chris@16 483 close();
Chris@16 484 throw;
Chris@16 485 }
Chris@16 486 }
Chris@16 487
Chris@16 488 template <typename ValueType>
Chris@16 489 sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
Chris@16 490 {
Chris@16 491 sbq.push(boost::forward<ValueType>(elem));
Chris@16 492 return sbq;
Chris@16 493 }
Chris@16 494
Chris@16 495 template <typename ValueType>
Chris@16 496 sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
Chris@16 497 {
Chris@16 498 sbq.push(elem);
Chris@16 499 return sbq;
Chris@16 500 }
Chris@16 501
Chris@16 502 template <typename ValueType>
Chris@16 503 sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
Chris@16 504 {
Chris@16 505 sbq.pull(elem);
Chris@16 506 return sbq;
Chris@16 507 }
Chris@16 508
Chris@16 509 }
Chris@16 510
Chris@16 511 #include <boost/config/abi_suffix.hpp>
Chris@16 512
Chris@16 513 #endif