~ubuntu-branches/ubuntu/wily/ruby-passenger/wily-proposed

« back to all changes in this revision

Viewing changes to ext/boost/thread/sync_queue.hpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2013-11-23 23:50:02 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20131123235002-8fdhsq7afj15o2z2
Tags: 4.0.25-1
* New upstream release.
* Refresh fix_install_path.patch.
* Build for Ruby 2.0 instead of 1.8. (Closes: #725591)
* Add fix_ftbfs_fortify_source.patch.
* Install passenger template files.

Show diffs side-by-side

added added

removed removed

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