STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
prefetch_pool.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/mng/prefetch_pool.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2003-2004 Roman Dementiev <[email protected]>
7  * Copyright (C) 2009 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_MNG_PREFETCH_POOL_HEADER
15 #define STXXL_MNG_PREFETCH_POOL_HEADER
16 
17 #include <list>
18 #include <stxxl/bits/config.h>
21 
22 
24 
25 //! \addtogroup schedlayer
26 //! \{
27 
28 //! Implements dynamically resizable prefetching pool.
29 template <class BlockType>
30 class prefetch_pool : private noncopyable
31 {
32 public:
33  typedef BlockType block_type;
34  typedef typename block_type::bid_type bid_type;
35 
36 protected:
37  struct bid_hash
38  {
39  size_t operator () (const bid_type& bid) const
40  {
41  size_t result = size_t(bid.storage) +
42  size_t(bid.offset & 0xffffffff) + size_t(bid.offset >> 32);
43  return result;
44  }
45 #if STXXL_MSVC
46  bool operator () (const bid_type& a, const bid_type& b) const
47  {
48  return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset);
49  }
50  enum
51  { // parameters for hash table
52  bucket_size = 4, // 0 < bucket_size
53  min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N
54  };
55 #endif
56  };
57  typedef std::pair<block_type*, request_ptr> busy_entry;
59  typedef typename std::list<block_type*>::iterator free_blocks_iterator;
60  typedef typename hash_map_type::iterator busy_blocks_iterator;
61 
62  // contains free prefetch blocks
63  std::list<block_type*> free_blocks;
64  // blocks that are in reading or already read but not retrieved by user
66 
68 
69 public:
70  //! Constructs pool.
71  //! \param init_size initial number of blocks in the pool
72  explicit prefetch_pool(unsigned_type init_size = 1) : free_blocks_size(init_size)
73  {
74  unsigned_type i = 0;
75  for ( ; i < init_size; ++i)
76  free_blocks.push_back(new block_type);
77  }
78 
79  void swap(prefetch_pool& obj)
80  {
81  std::swap(free_blocks, obj.free_blocks);
82  std::swap(busy_blocks, obj.busy_blocks);
83  std::swap(free_blocks_size, obj.free_blocks_size);
84  }
85 
86  //! Waits for completion of all ongoing read requests and frees memory.
87  virtual ~prefetch_pool()
88  {
89  while (!free_blocks.empty())
90  {
91  delete free_blocks.back();
92  free_blocks.pop_back();
93  }
94 
95  try
96  {
97  busy_blocks_iterator i2 = busy_blocks.begin();
98  for ( ; i2 != busy_blocks.end(); ++i2)
99  {
100  i2->second.second->wait();
101  delete i2->second.first;
102  }
103  }
104  catch (...)
105  { }
106  }
107 
108  //! Returns number of owned blocks.
110  { return free_blocks_size + busy_blocks.size(); }
111 
112  //! Gives a hint for prefetching a block.
113  //! \param bid address of a block to be prefetched
114  //! \return \c true if there was a free block to do prefetch and prefetching
115  //! was scheduled, \c false otherwise
116  //! \note If there are no free blocks available (all blocks
117  //! are already in reading or read but not retrieved by user calling \c read
118  //! method) calling \c hint function has no effect
119  bool hint(bid_type bid)
120  {
121  // if block is already hinted, no need to hint it again
122  if (in_prefetching(bid)) {
123  STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " was already cached");
124  return true;
125  }
126 
127  if (free_blocks_size) // only if we have a free block
128  {
129  --free_blocks_size;
130  block_type* block = free_blocks.back();
131  free_blocks.pop_back();
132  STXXL_VERBOSE2("prefetch_pool::hint bid=" << bid << " => prefetching");
133  request_ptr req = block->read(bid);
134  busy_blocks[bid] = busy_entry(block, req);
135  return true;
136  }
137  STXXL_VERBOSE2("prefetch_pool::hint bid=" << bid << " => no free blocks for prefetching");
138  return false;
139  }
140 
142  {
143  // if block is already hinted, no need to hint it again
144  if (in_prefetching(bid)) {
145  STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " was already cached");
146  return true;
147  }
148 
149  if (free_blocks_size) // only if we have a free block
150  {
151  --free_blocks_size;
152  block_type* block = free_blocks.back();
153  free_blocks.pop_back();
154  if (w_pool.has_request(bid))
155  {
156  busy_entry wp_request = w_pool.steal_request(bid);
157  STXXL_VERBOSE1("prefetch_pool::hint2 bid=" << bid << " was in write cache at " << wp_request.first);
158  assert(wp_request.first != 0);
159  w_pool.add(block); //in exchange
160  busy_blocks[bid] = wp_request;
161  return true;
162  }
163  STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " => prefetching");
164  request_ptr req = block->read(bid);
165  busy_blocks[bid] = busy_entry(block, req);
166  return true;
167  }
168  STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " => no free blocks for prefetching");
169  return false;
170  }
171 
173  {
174  busy_blocks_iterator cache_el = busy_blocks.find(bid);
175  if (cache_el == busy_blocks.end())
176  return false;
177 
178  // cancel request if it is a read request, there might be
179  // write requests 'stolen' from a write_pool that may not be canceled
180  if (cache_el->second.second->get_type() == request::READ)
181  cache_el->second.second->cancel();
182  // finish the request
183  cache_el->second.second->wait();
184  ++free_blocks_size;
185  free_blocks.push_back(cache_el->second.first);
186  busy_blocks.erase(cache_el);
187  return true;
188  }
189 
191  {
192  return (busy_blocks.find(bid) != busy_blocks.end());
193  }
194 
195  //! Reads block. If this block is cached block is not read but passed from the cache.
196  //! \param block block object, where data to be read to. If block was cached \c block 's
197  //! ownership goes to the pool and block from cache is returned in \c block value.
198  //! \param bid address of the block
199  //! \warning \c block parameter must be allocated dynamically using \c new .
200  //! \return request pointer object of read operation
202  {
203  busy_blocks_iterator cache_el = busy_blocks.find(bid);
204  if (cache_el == busy_blocks.end())
205  {
206  // not cached
207  STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => no copy in cache, retrieving to " << block);
208  return block->read(bid);
209  }
210 
211  // cached
212  STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => copy in cache exists");
213  ++free_blocks_size;
214  free_blocks.push_back(block);
215  block = cache_el->second.first;
216  request_ptr result = cache_el->second.second;
217  busy_blocks.erase(cache_el);
218  return result;
219  }
220 
222  {
223  // try cache
224  busy_blocks_iterator cache_el = busy_blocks.find(bid);
225  if (cache_el != busy_blocks.end())
226  {
227  // cached
228  STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => copy in cache exists");
229  ++free_blocks_size;
230  free_blocks.push_back(block);
231  block = cache_el->second.first;
232  request_ptr result = cache_el->second.second;
233  busy_blocks.erase(cache_el);
234  return result;
235  }
236 
237  // try w_pool cache
238  if (w_pool.has_request(bid))
239  {
240  busy_entry wp_request = w_pool.steal_request(bid);
241  STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " was in write cache at " << wp_request.first);
242  assert(wp_request.first != 0);
243  w_pool.add(block); //in exchange
244  block = wp_request.first;
245  return wp_request.second;
246  }
247 
248  // not cached
249  STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => no copy in cache, retrieving to " << block);
250  return block->read(bid);
251  }
252 
253  //! Resizes size of the pool.
254  //! \param new_size desired size of the pool. If some
255  //! blocks are used for prefetching, these blocks can't be freed.
256  //! Only free blocks (not in prefetching) can be freed by reducing
257  //! the size of the pool calling this method.
258  //! \return new size of the pool
260  {
261  int_type diff = int_type(new_size) - int_type(size());
262  if (diff > 0)
263  {
264  free_blocks_size += diff;
265  while (--diff >= 0)
266  free_blocks.push_back(new block_type);
267 
268 
269  return size();
270  }
271 
272  while (diff < 0 && free_blocks_size > 0)
273  {
274  ++diff;
275  --free_blocks_size;
276  delete free_blocks.back();
277  free_blocks.pop_back();
278  }
279  return size();
280  }
281 };
282 
283 //! \}
284 
286 
287 namespace std {
288 
289 template <class BlockType>
292 {
293  a.swap(b);
294 }
295 
296 } // namespace std
297 
298 #endif // !STXXL_MNG_PREFETCH_POOL_HEADER
299 // vim: et:ts=4:sw=4
bool has_request(bid_type bid)
Definition: write_pool.h:199
hash_map_type busy_blocks
Definition: prefetch_pool.h:65
bool hint(bid_type bid, write_pool< block_type > &w_pool)
request_ptr read(block_type *&block, bid_type bid, write_pool< block_type > &w_pool)
void swap(prefetch_pool &obj)
Definition: prefetch_pool.h:79
bool in_prefetching(bid_type bid)
void add(block_type *&block)
Definition: write_pool.h:247
std::list< block_type * > free_blocks
Definition: prefetch_pool.h:63
block_type::bid_type bid_type
Definition: prefetch_pool.h:34
bool invalidate(bid_type bid)
virtual ~prefetch_pool()
Waits for completion of all ongoing read requests and frees memory.
Definition: prefetch_pool.h:87
hash_map_type::iterator busy_blocks_iterator
Definition: prefetch_pool.h:60
bool hint(bid_type bid)
Gives a hint for prefetching a block.
#define STXXL_VERBOSE2(x)
Definition: verbose.h:107
std::pair< block_type *, request_ptr > steal_request(bid_type bid)
Definition: write_pool.h:226
Implements dynamically resizable buffered writing pool.
Definition: write_pool.h:34
unsigned_type free_blocks_size
Definition: prefetch_pool.h:67
Implements dynamically resizable prefetching pool.
Definition: prefetch_pool.h:30
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
std::list< block_type * >::iterator free_blocks_iterator
Definition: prefetch_pool.h:59
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
unsigned_type size() const
Returns number of owned blocks.
unsigned_type resize(unsigned_type new_size)
Resizes size of the pool.
std::pair< block_type *, request_ptr > busy_entry
Definition: prefetch_pool.h:57
request_ptr read(block_type *&block, bid_type bid)
Reads block. If this block is cached block is not read but passed from the cache. ...
prefetch_pool(unsigned_type init_size=1)
Constructs pool.
Definition: prefetch_pool.h:72
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
compat_hash_map< bid_type, busy_entry, bid_hash >::result hash_map_type
Definition: prefetch_pool.h:58