STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
write_pool.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/mng/write_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_WRITE_POOL_HEADER
15 #define STXXL_MNG_WRITE_POOL_HEADER
16 
17 #include <list>
18 #include <stxxl/bits/config.h>
19 #include <stxxl/bits/noncopyable.h>
20 #include <stxxl/bits/deprecated.h>
22 
23 #define STXXL_VERBOSE_WPOOL(msg) STXXL_VERBOSE1("write_pool[" << static_cast<void*>(this) << "]" << msg)
24 
25 
27 
28 //! \addtogroup schedlayer
29 //! \{
30 
31 
32 //! Implements dynamically resizable buffered writing pool.
33 template <class BlockType>
34 class write_pool : private noncopyable
35 {
36 public:
37  typedef BlockType block_type;
38  typedef typename block_type::bid_type bid_type;
39 
40  // a hack to make wait_any work with busy_entry type
41  struct busy_entry
42  {
46 
47  busy_entry() : block(NULL) { }
48  busy_entry(const busy_entry& a) : block(a.block), req(a.req), bid(a.bid) { }
50  block(bl), req(r), bid(bi) { }
51 
52  operator request_ptr () { return req; }
53  };
54  typedef typename std::list<block_type*>::iterator free_blocks_iterator;
55  typedef typename std::list<busy_entry>::iterator busy_blocks_iterator;
56 
57 protected:
58  // contains free write blocks
59  std::list<block_type*> free_blocks;
60  // blocks that are in writing
61  std::list<busy_entry> busy_blocks;
62 
63 public:
64  //! Constructs pool.
65  //! \param init_size initial number of blocks in the pool
66  explicit write_pool(unsigned_type init_size = 1)
67  {
68  for (unsigned_type i = 0; i < init_size; ++i)
69  {
70  free_blocks.push_back(new block_type);
71  STXXL_VERBOSE_WPOOL(" create block=" << free_blocks.back());
72  }
73  }
74 
75  void swap(write_pool& obj)
76  {
77  std::swap(free_blocks, obj.free_blocks);
78  std::swap(busy_blocks, obj.busy_blocks);
79  }
80 
81  //! Waits for completion of all ongoing write requests and frees memory.
82  virtual ~write_pool()
83  {
84  STXXL_VERBOSE_WPOOL("::~write_pool free_blocks.size()=" << free_blocks.size() <<
85  " busy_blocks.size()=" << busy_blocks.size());
86  while (!free_blocks.empty())
87  {
88  STXXL_VERBOSE_WPOOL(" delete free block=" << free_blocks.back());
89  delete free_blocks.back();
90  free_blocks.pop_back();
91  }
92 
93  try
94  {
95  for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
96  {
97  i2->req->wait();
98  if (free_blocks.empty())
99  STXXL_VERBOSE_WPOOL(" delete busy block=(empty)");
100  else
101  STXXL_VERBOSE_WPOOL(" delete busy block=" << free_blocks.back());
102  delete i2->block;
103  }
104  }
105  catch (...)
106  { }
107  }
108 
109  //! Returns number of owned blocks.
110  unsigned_type size() const { return free_blocks.size() + busy_blocks.size(); }
111 
112  //! Passes a block to the pool for writing.
113  //! \param block block to write. Ownership of the block goes to the pool.
114  //! \c block must be allocated dynamically with using \c new .
115  //! \param bid location, where to write
116  //! \warning \c block must be allocated dynamically with using \c new .
117  //! \return request object of the write operation
119  {
120  STXXL_VERBOSE_WPOOL("::write: " << block << " @ " << bid);
121  for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
122  {
123  if (i2->bid == bid) {
124  assert(i2->block != block);
125  STXXL_VERBOSE_WPOOL("WAW dependency");
126  // try to cancel the obsolete request
127  i2->req->cancel();
128  // invalidate the bid of the stale write request,
129  // prevents prefetch_pool from stealing a stale block
130  i2->bid.storage = 0;
131  }
132  }
133  request_ptr result = block->write(bid);
134  busy_blocks.push_back(busy_entry(block, result, bid));
135  block = NULL; // prevent caller from using the block any further
136  return result;
137  }
138 
139  //! Take out a block from the pool.
140  //! \return pointer to the block. Ownership of the block goes to the caller.
142  {
143  assert(size() > 0);
144  if (!free_blocks.empty())
145  {
146  block_type* p = free_blocks.back();
147  STXXL_VERBOSE_WPOOL("::steal : " << free_blocks.size() << " free blocks available, serve block=" << p);
148  free_blocks.pop_back();
149  return p;
150  }
151  STXXL_VERBOSE_WPOOL("::steal : all " << busy_blocks.size() << " are busy");
152  busy_blocks_iterator completed = wait_any(busy_blocks.begin(), busy_blocks.end());
153  assert(completed != busy_blocks.end()); // we got something reasonable from wait_any
154  assert(completed->req->poll()); // and it is *really* completed
155  block_type* p = completed->block;
156  busy_blocks.erase(completed);
157  check_all_busy(); // for debug
158  STXXL_VERBOSE_WPOOL(" serve block=" << p);
159  return p;
160  }
161 
162  // deprecated name for the steal()
164  {
165  return steal();
166  }
167 
168  //! Resizes size of the pool.
169  //! \param new_size new size of the pool after the call
170  void resize(unsigned_type new_size)
171  {
172  int_type diff = int_type(new_size) - int_type(size());
173  if (diff > 0)
174  {
175  while (--diff >= 0)
176  {
177  free_blocks.push_back(new block_type);
178  STXXL_VERBOSE_WPOOL(" create block=" << free_blocks.back());
179  }
180 
181  return;
182  }
183 
184  while (++diff <= 0)
185  delete steal();
186  }
187 
189  {
190  busy_blocks_iterator i2 = busy_blocks.begin();
191  for ( ; i2 != busy_blocks.end(); ++i2)
192  {
193  if (i2->bid == bid)
194  return i2->req;
195  }
196  return request_ptr();
197  }
198 
200  {
201  for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
202  {
203  if (i2->bid == bid)
204  return true;
205  }
206  return false;
207  }
208 
210  {
211  busy_blocks_iterator i2 = busy_blocks.begin();
212  for ( ; i2 != busy_blocks.end(); ++i2)
213  {
214  if (i2->bid == bid)
215  {
216  block_type* p = i2->block;
217  i2->req->wait();
218  busy_blocks.erase(i2);
219  return p;
220  }
221  }
222  return NULL;
223  }
224 
225  // returns a block and a (potentially unfinished) I/O request associated with it
226  std::pair<block_type*, request_ptr> steal_request(bid_type bid)
227  {
228  for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
229  {
230  if (i2->bid == bid)
231  {
232  // remove busy block from list, request has not yet been waited for!
233  block_type* blk = i2->block;
234  request_ptr req = i2->req;
235  busy_blocks.erase(i2);
236 
237  STXXL_VERBOSE_WPOOL("::steal_request block=" << blk);
238  // hand over block and (unfinished) request to caller
239  return std::pair<block_type*, request_ptr>(blk, req);
240  }
241  }
242  STXXL_VERBOSE_WPOOL("::steal_request NOT FOUND");
243  // not matching request found, return a dummy
244  return std::pair<block_type*, request_ptr>((block_type*)NULL, request_ptr());
245  }
246 
247  void add(block_type*& block)
248  {
249  STXXL_VERBOSE_WPOOL("::add " << block);
250  free_blocks.push_back(block);
251  block = NULL; // prevent caller from using the block any further
252  }
253 
254 protected:
256  {
257  busy_blocks_iterator cur = busy_blocks.begin();
258  int_type cnt = 0;
259  while (cur != busy_blocks.end())
260  {
261  if (cur->req->poll())
262  {
263  free_blocks.push_back(cur->block);
264  cur = busy_blocks.erase(cur);
265  ++cnt;
266  continue;
267  }
268  ++cur;
269  }
270  STXXL_VERBOSE_WPOOL("::check_all_busy : " << cnt <<
271  " are completed out of " << busy_blocks.size() + cnt << " busy blocks");
272  }
273 };
274 
275 //! \}
276 
278 
279 
280 namespace std {
281 
282 template <class BlockType>
283 void swap(stxxl::write_pool<BlockType>& a,
285 {
286  a.swap(b);
287 }
288 
289 } // namespace std
290 
291 #endif // !STXXL_MNG_WRITE_POOL_HEADER
292 // vim: et:ts=4:sw=4
bool has_request(bid_type bid)
Definition: write_pool.h:199
void add(block_type *&block)
Definition: write_pool.h:247
virtual ~write_pool()
Waits for completion of all ongoing write requests and frees memory.
Definition: write_pool.h:82
Definition: write_pool.h:41
block_type * steal()
Take out a block from the pool.
Definition: write_pool.h:141
bid_type bid
Definition: write_pool.h:45
counting_ptr< request > request_ptr
A reference counting pointer for request.
Definition: request.h:112
std::list< busy_entry >::iterator busy_blocks_iterator
Definition: write_pool.h:55
write_pool(unsigned_type init_size=1)
Constructs pool.
Definition: write_pool.h:66
#define STXXL_VERBOSE_WPOOL(msg)
Definition: write_pool.h:23
std::list< busy_entry > busy_blocks
Definition: write_pool.h:61
#define STXXL_DEPRECATED(x)
Definition: deprecated.h:30
block_type * block
Definition: write_pool.h:43
busy_entry()
Definition: write_pool.h:47
void resize(unsigned_type new_size)
Resizes size of the pool.
Definition: write_pool.h:170
request_ptr get_request(bid_type bid)
Definition: write_pool.h:188
std::pair< block_type *, request_ptr > steal_request(bid_type bid)
Definition: write_pool.h:226
BlockType block_type
Definition: write_pool.h:37
Implements dynamically resizable buffered writing pool.
Definition: write_pool.h:34
block_type::bid_type bid_type
Definition: write_pool.h:38
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
void check_all_busy()
Definition: write_pool.h:255
std::list< block_type * > free_blocks
Definition: write_pool.h:59
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
block_type * steal(bid_type bid)
Definition: write_pool.h:209
request_ptr write(block_type *&block, bid_type bid)
Passes a block to the pool for writing.
Definition: write_pool.h:118
std::list< block_type * >::iterator free_blocks_iterator
Definition: write_pool.h:54
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
busy_entry(const busy_entry &a)
Definition: write_pool.h:48
request_iterator_ wait_any(request_iterator_ reqs_begin, request_iterator_ reqs_end)
Suspends calling thread until any of requests is completed.
unsigned_type size() const
Returns number of owned blocks.
Definition: write_pool.h:110
request_ptr req
Definition: write_pool.h:44
busy_entry(block_type *&bl, request_ptr &r, bid_type &bi)
Definition: write_pool.h:49
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
void swap(write_pool &obj)
Definition: write_pool.h:75