Stxxl  1.3.2
block_prefetcher.h
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_BLOCK_PREFETCHER_HEADER
16 #define STXXL_BLOCK_PREFETCHER_HEADER
17 
18 #include <vector>
19 #include <queue>
20 
21 #include <stxxl/bits/common/switch.h>
22 #include <stxxl/bits/io/request_ptr.h>
23 #include <stxxl/bits/io/iostats.h>
24 
25 
26 __STXXL_BEGIN_NAMESPACE
27 
30 
31 
32 class set_switch_handler
33 {
34  onoff_switch & switch_;
35  completion_handler on_compl;
36 
37 public:
38  set_switch_handler(onoff_switch & switch__, const completion_handler & on_compl)
39  : switch_(switch__), on_compl(on_compl)
40  { }
41 
42  void operator () (request * req)
43  {
44  on_compl(req); //call before setting switch to on, otherwise, user has no way to wait for the completion handler to be executed
45  switch_.on();
46  }
47 };
48 
53 template <typename block_type, typename bid_iterator_type>
55 {
56  block_prefetcher() { }
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;
62  unsigned_type seq_length;
63 
64  int_type * prefetch_seq;
65 
66  unsigned_type nextread;
67  unsigned_type nextconsume;
68 
69  const int_type nreadblocks;
70 
71  block_type * read_buffers;
72  request_ptr * read_reqs;
73  bid_type * read_bids;
74 
75  onoff_switch * completed;
76  int_type * pref_buffer;
77 
78  completion_handler do_after_fetch;
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:
103  bid_iterator_type _cons_begin,
104  bid_iterator_type _cons_end,
105  int_type * _pref_seq,
106  int_type _prefetch_buf_size,
108  ) :
109  consume_seq_begin(_cons_begin),
110  consume_seq_end(_cons_end),
111  seq_length(_cons_end - _cons_begin),
112  prefetch_seq(_pref_seq),
113  nextread(STXXL_MIN(unsigned_type(_prefetch_buf_size), seq_length)),
114  nextconsume(0),
115  nreadblocks(nextread),
116  do_after_fetch(do_after_fetch)
117  {
118  STXXL_VERBOSE1("block_prefetcher: seq_length=" << seq_length);
119  STXXL_VERBOSE1("block_prefetcher: _prefetch_buf_size=" << _prefetch_buf_size);
120  assert(seq_length > 0);
121  assert(_prefetch_buf_size > 0);
122  int_type i;
123  read_buffers = new block_type[nreadblocks];
124  read_reqs = new request_ptr[nreadblocks];
125  read_bids = new bid_type[nreadblocks];
126  pref_buffer = new int_type[seq_length];
127 
128  std::fill(pref_buffer, pref_buffer + seq_length, -1);
129 
130  completed = new onoff_switch[seq_length];
131 
132  for (i = 0; i < nreadblocks; ++i)
133  {
134  assert(prefetch_seq[i] < int_type(seq_length));
135  assert(prefetch_seq[i] >= 0);
136  read_bids[i] = *(consume_seq_begin + prefetch_seq[i]);
137  STXXL_VERBOSE1("block_prefetcher: reading block " << i <<
138  " prefetch_seq[" << i << "]=" << prefetch_seq[i] <<
139  " @ " << &read_buffers[i] <<
140  " @ " << read_bids[i]);
141  read_reqs[i] = read_buffers[i].read(
142  read_bids[i],
143  set_switch_handler(*(completed + prefetch_seq[i]), do_after_fetch));
144  pref_buffer[prefetch_seq[i]] = i;
145  }
146  }
149  block_type * pull_block()
150  {
151  STXXL_VERBOSE1("block_prefetcher: pulling a block");
152  return wait(nextconsume++);
153  }
159  bool block_consumed(block_type * & buffer)
160  {
161  int_type ibuffer = buffer - read_buffers;
162  STXXL_VERBOSE1("block_prefetcher: buffer " << ibuffer << " consumed");
163  if (read_reqs[ibuffer].valid())
164  read_reqs[ibuffer]->wait();
165 
166  read_reqs[ibuffer] = NULL;
167 
168  if (nextread < seq_length)
169  {
170  assert(ibuffer >= 0 && ibuffer < nreadblocks);
171  int_type next_2_prefetch = prefetch_seq[nextread++];
172  STXXL_VERBOSE1("block_prefetcher: prefetching block " << next_2_prefetch);
173 
174  assert((next_2_prefetch < int_type(seq_length)) && (next_2_prefetch >= 0));
175  assert(!completed[next_2_prefetch].is_on());
176 
177  pref_buffer[next_2_prefetch] = ibuffer;
178  read_bids[ibuffer] = *(consume_seq_begin + next_2_prefetch);
179  read_reqs[ibuffer] = read_buffers[ibuffer].read(
180  read_bids[ibuffer],
181  set_switch_handler(*(completed + next_2_prefetch), do_after_fetch)
182  );
183  }
184 
185  if (nextconsume >= seq_length)
186  return false;
187 
188 
189  buffer = wait(nextconsume++);
190 
191  return true;
192  }
193 
194  // no more consumable blocks available, but can't delete the prefetcher,
195  // because not all blocks may have been returned, yet
196  bool empty() const
197  {
198  return nextconsume >= seq_length;
199  }
200 
201  // index of the next element in the consume sequence
202  unsigned_type pos() const
203  {
204  return nextconsume;
205  }
206 
209  {
210  for (int_type i = 0; i < nreadblocks; ++i)
211  if (read_reqs[i].valid())
212  read_reqs[i]->wait();
213 
214 
215  delete[] read_reqs;
216  delete[] read_bids;
217  delete[] completed;
218  delete[] pref_buffer;
219  delete[] read_buffers;
220  }
221 };
222 
224 
225 __STXXL_END_NAMESPACE
226 
227 #endif // !STXXL_BLOCK_PREFETCHER_HEADER
bool block_consumed(block_type *&buffer)
Exchanges buffers between prefetcher and application.
Definition: block_prefetcher.h:159
Default completion handler class.
Definition: completion_handler.h:94
Request with basic properties like file and offset.
Definition: request.h:39
Completion handler class (Loki-style)
Definition: completion_handler.h:63
block_type * pull_block()
Pulls next unconsumed block from the consumption sequence.
Definition: block_prefetcher.h:149
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.
Definition: block_prefetcher.h:102
Implemented as reference counting smart pointer.
Definition: request_ptr.h:34
Encapsulates asynchronous prefetching engine.
Definition: block_prefetcher.h:54
virtual void wait(bool measure_time=true)=0
Suspends calling thread until completion of the request.
~block_prefetcher()
Frees used memory.
Definition: block_prefetcher.h:208