STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
queue.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/containers/queue.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2005 Roman Dementiev <[email protected]>
7  * Copyright (C) 2009, 2010 Andreas Beckmann <[email protected]>
8  *
9  * Distributed under the Boost Software License, Version 1.0.
10  * (See accompanying file LICENSE_1_0.txt or copy at
11  * http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
14 #ifndef STXXL_CONTAINERS_QUEUE_HEADER
15 #define STXXL_CONTAINERS_QUEUE_HEADER
16 
17 #include <vector>
18 #include <queue>
19 #include <deque>
20 
21 #include <stxxl/bits/deprecated.h>
29 
30 
32 
33 #ifndef STXXL_VERBOSE_QUEUE
34 #define STXXL_VERBOSE_QUEUE STXXL_VERBOSE2
35 #endif
36 
37 //! \addtogroup stlcont
38 //! \{
39 
40 //! External FIFO queue container. \n
41 //! <b> Introduction </b> to queue container: see \ref tutorial_queue tutorial\n
42 //! <b> Design and Internals </b> of queue container: see \ref design_queue.
43 //!
44 //! \tparam ValueType type of the contained objects (POD with no references to internal memory)
45 //! \tparam BlockSize size of the external memory block in bytes, default is \c STXXL_DEFAULT_BLOCK_SIZE(ValueType)
46 //! \tparam AllocStr parallel disk allocation strategy, default is \c STXXL_DEFAULT_ALLOC_STRATEGY
47 //! \tparam SizeType size data type, default is \c stxxl::uint64
48 template <class ValueType,
49  unsigned BlockSize = STXXL_DEFAULT_BLOCK_SIZE(ValueType),
50  class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY,
51  class SizeType = stxxl::uint64>
52 class queue : private noncopyable
53 {
54 public:
55  typedef ValueType value_type;
56  typedef AllocStr alloc_strategy_type;
57  typedef SizeType size_type;
58  enum {
59  block_size = BlockSize
60  };
61 
64 
65 private:
67 
77  std::deque<bid_type> bids;
80 
81 public:
82  //! \name Constructors/Destructors
83  //! \{
84 
85  //! Constructs empty queue with own write and prefetch block pool.
86  //!
87  //! \param D number of parallel disks, defaulting to the configured number of scratch disks,
88  //! memory consumption will be 2 * D + 2 blocks
89  //! (first and last block, D blocks as write cache, D block for prefetching)
90  explicit queue(int_type D = -1) :
91  m_size(0),
92  delete_pool(true),
93  alloc_count(0),
94  bm(block_manager::get_instance())
95  {
96  if (D < 1)
97  D = config::get_instance()->disks_number();
98  STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(D)");
99  pool = new pool_type(D, D + 2);
100  init();
101  }
102 
103  //! Constructs empty queue with own write and prefetch block pool.
104  //!
105  //! \param w_pool_size number of blocks in the write pool, must be at least 2, recommended at least 3
106  //! \param p_pool_size number of blocks in the prefetch pool, recommended at least 1
107  //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side),
108  //! default is number of block in the prefetch pool
109  explicit queue(unsigned_type w_pool_size, unsigned_type p_pool_size, int blocks2prefetch_ = -1) :
110  m_size(0),
111  delete_pool(true),
112  alloc_count(0),
113  bm(block_manager::get_instance())
114  {
115  STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(sizes)");
116  pool = new pool_type(p_pool_size, w_pool_size);
117  init(blocks2prefetch_);
118  }
119 
120  //! Constructs empty queue.
121  //!
122  //! \param w_pool write pool
123  //! \param p_pool prefetch pool
124  //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side),
125  //! default is number of blocks in the prefetch pool
126  //! \warning Number of blocks in the write pool must be at least 2, recommended at least 3
127  //! \warning Number of blocks in the prefetch pool recommended at least 1
129  queue(write_pool<block_type>& w_pool, prefetch_pool<block_type>& p_pool, int blocks2prefetch_ = -1)) :
130  m_size(0),
131  delete_pool(true),
132  alloc_count(0),
133  bm(block_manager::get_instance())
134  {
135  STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(pools)");
136  pool = new pool_type(p_pool, w_pool);
137  init(blocks2prefetch_);
138  }
139 
140  //! Constructs empty queue.
141  //!
142  //! \param pool_ block write/prefetch pool
143  //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side),
144  //! default is number of blocks in the prefetch pool
145  //! \warning Number of blocks in the write pool must be at least 2, recommended at least 3
146  //! \warning Number of blocks in the prefetch pool recommended at least 1
147  queue(pool_type& pool_, int blocks2prefetch_ = -1) :
148  m_size(0),
149  delete_pool(false),
150  pool(&pool_),
151  alloc_count(0),
152  bm(block_manager::get_instance())
153  {
154  STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(pool)");
155  init(blocks2prefetch_);
156  }
157 
158  //! \}
159 
160  //! \name Modifiers
161  //! \{
162 
163  void swap(queue& obj)
164  {
165  std::swap(m_size, obj.m_size);
166  std::swap(delete_pool, obj.delete_pool);
167  std::swap(pool, obj.pool);
168  std::swap(front_block, obj.front_block);
169  std::swap(back_block, obj.back_block);
170  std::swap(front_element, obj.front_element);
171  std::swap(back_element, obj.back_element);
172  std::swap(alloc_strategy, obj.alloc_strategy);
173  std::swap(alloc_count, obj.alloc_count);
174  std::swap(bids, obj.bids);
175  std::swap(bm, obj.bm);
176  std::swap(blocks2prefetch, obj.blocks2prefetch);
177  }
178 
179  //! \}
180 
181 private:
182  void init(int blocks2prefetch_ = -1)
183  {
184  if (pool->size_write() < 2) {
185  STXXL_ERRMSG("queue: invalid configuration, not enough blocks (" << pool->size_write() <<
186  ") in write pool, at least 2 are needed, resizing to 3");
187  pool->resize_write(3);
188  }
189 
190  if (pool->size_write() < 3) {
191  STXXL_MSG("queue: inefficient configuration, no blocks for buffered writing available");
192  }
193 
194  if (pool->size_prefetch() < 1) {
195  STXXL_MSG("queue: inefficient configuration, no blocks for prefetching available");
196  }
197 
198  front_block = back_block = pool->steal();
199  back_element = back_block->begin() - 1;
200  front_element = back_block->begin();
201  set_prefetch_aggr(blocks2prefetch_);
202  }
203 
204 public:
205  //! \name Miscellaneous
206  //! \{
207 
208  //! Defines the number of blocks to prefetch (\c front side).
209  //! This method should be called whenever the prefetch pool is resized
210  //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side),
211  //! a negative value means to use the number of blocks in the prefetch pool
212  void set_prefetch_aggr(int_type blocks2prefetch_)
213  {
214  if (blocks2prefetch_ < 0)
215  blocks2prefetch = pool->size_prefetch();
216  else
217  blocks2prefetch = blocks2prefetch_;
218  }
219 
220  //! Returns the number of blocks prefetched from the \c front side.
222  {
223  return blocks2prefetch;
224  }
225  //! \}
226 
227  //! \name Modifiers
228  //! \{
229 
230  //! Adds an element in the queue.
231  void push(const value_type& val)
232  {
233  if (UNLIKELY(back_element == back_block->begin() + (block_type::size - 1)))
234  {
235  // back block is filled
236  if (front_block == back_block)
237  { // can not write the back block because it
238  // is the same as the front block, must keep it memory
239  STXXL_VERBOSE1("queue::push Case 1");
240  }
241  else if (size() < 2 * block_type::size)
242  {
243  STXXL_VERBOSE1("queue::push Case 1.5");
244  // only two blocks with a gap in the beginning, move elements within memory
245  assert(bids.empty());
246  size_t gap = front_element - front_block->begin();
247  assert(gap > 0);
248  std::copy(front_element, front_block->end(), front_block->begin());
249  std::copy(back_block->begin(), back_block->begin() + gap, front_block->begin() + (block_type::size - gap));
250  std::copy(back_block->begin() + gap, back_block->end(), back_block->begin());
251  front_element -= gap;
252  back_element -= gap;
253 
254  ++back_element;
255  *back_element = val;
256  ++m_size;
257  return;
258  }
259  else
260  {
261  STXXL_VERBOSE1("queue::push Case 2");
262  // write the back block
263  // need to allocate new block
264  bid_type newbid;
265 
266  bm->new_block(alloc_strategy, newbid, alloc_count++);
267 
268  STXXL_VERBOSE_QUEUE("queue[" << this << "]: push block " << back_block << " @ " << FMT_BID(newbid));
269  bids.push_back(newbid);
270  pool->write(back_block, newbid);
271  if (bids.size() <= blocks2prefetch) {
272  STXXL_VERBOSE1("queue::push Case Hints");
273  pool->hint(newbid);
274  }
275  }
276  back_block = pool->steal();
277 
278  back_element = back_block->begin();
279  *back_element = val;
280  ++m_size;
281  return;
282  }
283  ++back_element;
284  *back_element = val;
285  ++m_size;
286  }
287 
288  //! Removes element from the queue.
289  void pop()
290  {
291  assert(!empty());
292 
293  if (UNLIKELY(front_element == front_block->begin() + (block_type::size - 1)))
294  {
295  // if there is only one block, it implies ...
296  if (back_block == front_block)
297  {
298  STXXL_VERBOSE1("queue::pop Case 3");
299  assert(size() == 1);
300  assert(back_element == front_element);
301  assert(bids.empty());
302  // reset everything
303  back_element = back_block->begin() - 1;
304  front_element = back_block->begin();
305  m_size = 0;
306  return;
307  }
308 
309  --m_size;
310  if (m_size <= block_type::size)
311  {
312  STXXL_VERBOSE1("queue::pop Case 4");
313  assert(bids.empty());
314  // the back_block is the next block
315  pool->add(front_block);
316  front_block = back_block;
317  front_element = back_block->begin();
318  return;
319  }
320  STXXL_VERBOSE1("queue::pop Case 5");
321 
322  assert(!bids.empty());
323  request_ptr req = pool->read(front_block, bids.front());
324  STXXL_VERBOSE_QUEUE("queue[" << this << "]: pop block " << front_block << " @ " << FMT_BID(bids.front()));
325 
326  // give prefetching hints
327  for (unsigned_type i = 0; i < blocks2prefetch && i < bids.size() - 1; ++i)
328  {
329  STXXL_VERBOSE1("queue::pop Case Hints");
330  pool->hint(bids[i + 1]);
331  }
332 
333  front_element = front_block->begin();
334  req->wait();
335 
336  bm->delete_block(bids.front());
337  bids.pop_front();
338  return;
339  }
340 
341  ++front_element;
342  --m_size;
343  }
344  //! \}
345 
346  //! \name Operators
347  //! \{
348 
349  //! Returns a mutable reference at the back of the queue.
351  {
352  assert(!empty());
353  return *back_element;
354  }
355 
356  //! Returns a const reference at the back of the queue.
357  const value_type & back() const
358  {
359  assert(!empty());
360  return *back_element;
361  }
362 
363  //! Returns a mutable reference at the front of the queue.
365  {
366  assert(!empty());
367  return *front_element;
368  }
369 
370  //! Returns a const reference at the front of the queue.
371  const value_type & front() const
372  {
373  assert(!empty());
374  return *front_element;
375  }
376 
377  //! \}
378 
379  //! \name Constructors/Destructors
380  //! \{
381 
383  {
384  if (front_block != back_block)
385  pool->add(back_block);
386  pool->add(front_block);
387 
388  if (delete_pool)
389  {
390  delete pool;
391  }
392 
393  if (!bids.empty())
394  bm->delete_blocks(bids.begin(), bids.end());
395  }
396 
397  //! \}
398 
399  //! \name Capacity
400  //! \{
401 
402  //! Returns the size of the queue.
403  size_type size() const
404  {
405  return m_size;
406  }
407 
408  //! Returns \c true if queue is empty.
409  bool empty() const
410  {
411  return (m_size == 0);
412  }
413 
414  //! \}
415 };
416 
417 //! \}
418 
420 
421 #endif // !STXXL_CONTAINERS_QUEUE_HEADER
422 // vim: et:ts=4:sw=4
const value_type & back() const
Returns a const reference at the back of the queue.
Definition: queue.h:357
queue(pool_type &pool_, int blocks2prefetch_=-1)
Constructs empty queue.
Definition: queue.h:147
#define STXXL_DEFAULT_BLOCK_SIZE(type)
value_type * back_element
Definition: queue.h:74
Block manager class.
Definition: block_manager.h:63
#define STXXL_VERBOSE_QUEUE
Definition: queue.h:34
void swap(queue &obj)
Definition: queue.h:163
unsigned_type alloc_count
Definition: queue.h:76
unsigned long long int uint64
Definition: types.h:41
alloc_strategy_type alloc_strategy
Definition: queue.h:75
bool empty() const
Returns true if queue is empty.
Definition: queue.h:409
External FIFO queue container. Introduction to queue container: see STXXL Queue tutorial Design a...
Definition: queue.h:52
typed_block< block_size, value_type > block_type
Definition: queue.h:62
#define STXXL_DEFAULT_ALLOC_STRATEGY
Definition: block_alloc.h:259
read_write_pool< block_type > pool_type
Definition: queue.h:66
queue(write_pool< block_type > &w_pool, prefetch_pool< block_type > &p_pool, int blocks2prefetch_=-1)
Constructs empty queue.
Definition: queue.h:129
block_type * front_block
Definition: queue.h:71
void push(const value_type &val)
Adds an element in the queue.
Definition: queue.h:231
SizeType size_type
Definition: queue.h:57
#define STXXL_DEPRECATED(x)
Definition: deprecated.h:30
Implements dynamically resizable buffered writing pool.
Definition: write_pool.h:34
value_type & front()
Returns a mutable reference at the front of the queue.
Definition: queue.h:364
size_type m_size
Definition: queue.h:68
Implements dynamically resizable prefetching pool.
Definition: prefetch_pool.h:30
Block containing elements of fixed length.
Definition: typed_block.h:238
AllocStr alloc_strategy_type
Definition: queue.h:56
const value_type & front() const
Returns a const reference at the front of the queue.
Definition: queue.h:371
BID< block_size > bid_type
Definition: queue.h:63
Implements dynamically resizable buffered writing and prefetched reading pool.
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
pool_type * pool
Definition: queue.h:70
value_type & back()
Returns a mutable reference at the back of the queue.
Definition: queue.h:350
#define UNLIKELY(c)
Definition: utils.h:226
value_type * front_element
Definition: queue.h:73
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void init(int blocks2prefetch_=-1)
Definition: queue.h:182
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
size_type size() const
Returns the size of the queue.
Definition: queue.h:403
block_type * back_block
Definition: queue.h:72
void set_prefetch_aggr(int_type blocks2prefetch_)
Defines the number of blocks to prefetch (front side). This method should be called whenever the pref...
Definition: queue.h:212
queue(unsigned_type w_pool_size, unsigned_type p_pool_size, int blocks2prefetch_=-1)
Constructs empty queue with own write and prefetch block pool.
Definition: queue.h:109
#define STXXL_ERRMSG(x)
Definition: verbose.h:79
void pop()
Removes element from the queue.
Definition: queue.h:289
block_manager * bm
Definition: queue.h:78
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
unsigned_type blocks2prefetch
Definition: queue.h:79
#define STXXL_MSG(x)
Definition: verbose.h:72
std::deque< bid_type > bids
Definition: queue.h:77
queue(int_type D=-1)
Constructs empty queue with own write and prefetch block pool.
Definition: queue.h:90
ValueType value_type
Definition: queue.h:55
unsigned_type get_prefetch_aggr() const
Returns the number of blocks prefetched from the front side.
Definition: queue.h:221
#define FMT_BID(_bid_)
Definition: bid.h:30
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
bool delete_pool
Definition: queue.h:69