STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
block_prefetcher.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/mng/block_prefetcher.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002-2004 Roman Dementiev <[email protected]>
7  * Copyright (C) 2009, 2010 Johannes Singler <[email protected]>
8  * Copyright (C) 2009 Andreas Beckmann <[email protected]>
9  *
10  * Distributed under the Boost Software License, Version 1.0.
11  * (See accompanying file LICENSE_1_0.txt or copy at
12  * http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
15 #ifndef STXXL_MNG_BLOCK_PREFETCHER_HEADER
16 #define STXXL_MNG_BLOCK_PREFETCHER_HEADER
17 
18 #include <vector>
19 #include <queue>
20 
22 #include <stxxl/bits/io/request.h>
23 #include <stxxl/bits/io/iostats.h>
24 #include <stxxl/bits/noncopyable.h>
25 
26 
28 
29 //! \addtogroup schedlayer
30 //! \{
31 
32 
34 {
37 
38 public:
40  : switch_(switch__), on_compl(on_compl)
41  { }
42 
43  void operator () (request* req)
44  {
45  on_compl(req); //call before setting switch to on, otherwise, user has no way to wait for the completion handler to be executed
46  switch_.on();
47  }
48 };
49 
50 //! Encapsulates asynchronous prefetching engine.
51 //!
52 //! \c block_prefetcher overlaps I/Os with consumption of read data.
53 //! Utilizes optimal asynchronous prefetch scheduling (by Peter Sanders et.al.)
54 template <typename block_type, typename bid_iterator_type>
56 {
57  typedef typename block_type::bid_type bid_type;
58 
59 protected:
60  bid_iterator_type consume_seq_begin;
61  bid_iterator_type consume_seq_end;
63 
65 
68 
70 
71  block_type* read_buffers;
74 
77 
79 
80  block_type * wait(int_type iblock)
81  {
82  STXXL_VERBOSE1("block_prefetcher: waiting block " << iblock);
83  {
84  stats::scoped_wait_timer wait_timer(stats::WAIT_OP_READ);
85 
86  completed[iblock].wait_for_on();
87  }
88  STXXL_VERBOSE1("block_prefetcher: finished waiting block " << iblock);
89  int_type ibuffer = pref_buffer[iblock];
90  STXXL_VERBOSE1("block_prefetcher: returning buffer " << ibuffer);
91  assert(ibuffer >= 0 && ibuffer < nreadblocks);
92  return (read_buffers + ibuffer);
93  }
94 
95 public:
96  //! Constructs an object and immediately starts prefetching.
97  //! \param _cons_begin \c bid_iterator pointing to the \c bid of the first block to be consumed
98  //! \param _cons_end \c bid_iterator pointing to the \c bid of the ( \b last + 1 ) block of consumption sequence
99  //! \param _pref_seq gives the prefetch order, is a pointer to the integer array that contains
100  //! the indices of the blocks in the consumption sequence
101  //! \param _prefetch_buf_size amount of prefetch buffers to use
102  //! \param do_after_fetch unknown
104  bid_iterator_type _cons_begin,
105  bid_iterator_type _cons_end,
106  int_type* _pref_seq,
107  int_type _prefetch_buf_size,
109  ) :
110  consume_seq_begin(_cons_begin),
111  consume_seq_end(_cons_end),
112  seq_length(_cons_end - _cons_begin),
113  prefetch_seq(_pref_seq),
114  nextread(STXXL_MIN(unsigned_type(_prefetch_buf_size), seq_length)),
115  nextconsume(0),
116  nreadblocks(nextread),
117  do_after_fetch(do_after_fetch)
118  {
119  STXXL_VERBOSE1("block_prefetcher: seq_length=" << seq_length);
120  STXXL_VERBOSE1("block_prefetcher: _prefetch_buf_size=" << _prefetch_buf_size);
121  assert(seq_length > 0);
122  assert(_prefetch_buf_size > 0);
123  int_type i;
124  read_buffers = new block_type[nreadblocks];
125  read_reqs = new request_ptr[nreadblocks];
126  read_bids = new bid_type[nreadblocks];
127  pref_buffer = new int_type[seq_length];
128 
129  std::fill(pref_buffer, pref_buffer + seq_length, -1);
130 
131  completed = new onoff_switch[seq_length];
132 
133  for (i = 0; i < nreadblocks; ++i)
134  {
135  assert(prefetch_seq[i] < int_type(seq_length));
136  assert(prefetch_seq[i] >= 0);
137  read_bids[i] = *(consume_seq_begin + prefetch_seq[i]);
138  STXXL_VERBOSE1("block_prefetcher: reading block " << i <<
139  " prefetch_seq[" << i << "]=" << prefetch_seq[i] <<
140  " @ " << &read_buffers[i] <<
141  " @ " << read_bids[i]);
142  read_reqs[i] = read_buffers[i].read(
143  read_bids[i],
144  set_switch_handler(*(completed + prefetch_seq[i]), do_after_fetch));
145  pref_buffer[prefetch_seq[i]] = i;
146  }
147  }
148  //! Pulls next unconsumed block from the consumption sequence.
149  //! \return Pointer to the already prefetched block from the internal buffer pool
150  block_type * pull_block()
151  {
152  STXXL_VERBOSE1("block_prefetcher: pulling a block");
153  return wait(nextconsume++);
154  }
155  //! Exchanges buffers between prefetcher and application.
156  //! \param buffer pointer to the consumed buffer. After call if return value is true \c buffer
157  //! contains valid pointer to the next unconsumed prefetched buffer.
158  //! \remark parameter \c buffer must be value returned by \c pull_block() or \c block_consumed() methods
159  //! \return \c false if there are no blocks to prefetch left, \c true if consumption sequence is not emptied
160  bool block_consumed(block_type*& buffer)
161  {
162  int_type ibuffer = buffer - read_buffers;
163  STXXL_VERBOSE1("block_prefetcher: buffer " << ibuffer << " consumed");
164  if (read_reqs[ibuffer].valid())
165  read_reqs[ibuffer]->wait();
166 
167  read_reqs[ibuffer] = NULL;
168 
169  if (nextread < seq_length)
170  {
171  assert(ibuffer >= 0 && ibuffer < nreadblocks);
172  int_type next_2_prefetch = prefetch_seq[nextread++];
173  STXXL_VERBOSE1("block_prefetcher: prefetching block " << next_2_prefetch);
174 
175  assert((next_2_prefetch < int_type(seq_length)) && (next_2_prefetch >= 0));
176  assert(!completed[next_2_prefetch].is_on());
177 
178  pref_buffer[next_2_prefetch] = ibuffer;
179  read_bids[ibuffer] = *(consume_seq_begin + next_2_prefetch);
180  read_reqs[ibuffer] = read_buffers[ibuffer].read(
181  read_bids[ibuffer],
182  set_switch_handler(*(completed + next_2_prefetch), do_after_fetch)
183  );
184  }
185 
186  if (nextconsume >= seq_length)
187  return false;
188 
189 
190  buffer = wait(nextconsume++);
191 
192  return true;
193  }
194 
195  //! No more consumable blocks available, but can't delete the prefetcher,
196  //! because not all blocks may have been returned, yet.
197  bool empty() const
198  {
199  return nextconsume >= seq_length;
200  }
201 
202  //! Index of the next element in the consume sequence.
204  {
205  return nextconsume;
206  }
207 
208  //! Frees used memory.
210  {
211  for (int_type i = 0; i < nreadblocks; ++i)
212  if (read_reqs[i].valid())
213  read_reqs[i]->wait();
214 
215 
216  delete[] read_reqs;
217  delete[] read_bids;
218  delete[] completed;
219  delete[] pref_buffer;
220  delete[] read_buffers;
221  }
222 };
223 
224 //! \}
225 
227 
228 #endif // !STXXL_MNG_BLOCK_PREFETCHER_HEADER
const Tp & STXXL_MIN(const Tp &a, const Tp &b)
Definition: utils.h:147
Default completion handler class.
block_type::bid_type bid_type
Completion handler class (Loki-style).
completion_handler do_after_fetch
bool empty() const
No more consumable blocks available, but can&#39;t delete the prefetcher, because not all blocks may have...
block_type * pull_block()
Pulls next unconsumed block from the consumption sequence.
block_type * wait(int_type iblock)
completion_handler on_compl
bool block_consumed(block_type *&buffer)
Exchanges buffers between prefetcher and application.
bid_iterator_type consume_seq_begin
const int_type nreadblocks
Encapsulates asynchronous prefetching engine.
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
unsigned_type pos() const
Index of the next element in the consume sequence.
~block_prefetcher()
Frees used memory.
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
block_prefetcher(bid_iterator_type _cons_begin, bid_iterator_type _cons_end, int_type *_pref_seq, int_type _prefetch_buf_size, completion_handler do_after_fetch=default_completion_handler())
Constructs an object and immediately starts prefetching.
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
Request with basic properties like file and offset.
Definition: request.h:39
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
bid_iterator_type consume_seq_end
set_switch_handler(onoff_switch &switch__, const completion_handler &on_compl)