Stxxl  1.2.1
write_pool.h
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 <dementiev@mpi-sb.mpg.de>
7  *
8  * Distributed under the Boost Software License, Version 1.0.
9  * (See accompanying file LICENSE_1_0.txt or copy at
10  * http://www.boost.org/LICENSE_1_0.txt)
11  **************************************************************************/
12 
13 #ifndef STXXL_WRITE_POOL_HEADER
14 #define STXXL_WRITE_POOL_HEADER
15 
16 #include <list>
17 
18 #ifdef STXXL_BOOST_CONFIG
19  #include <boost/config.hpp>
20 #endif
21 
22 #include <stxxl/bits/mng/mng.h>
23 //#include <stxxl/bits/compat_hash_map.h>
24 
25 
26 __STXXL_BEGIN_NAMESPACE
27 
30 
31 
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  {
43  block_type * block;
44  request_ptr req;
45  bid_type bid;
46 
47  busy_entry() : block(NULL) { }
48  busy_entry(const busy_entry & a) : block(a.block), req(a.req), bid(a.bid) { }
49  busy_entry(block_type * & bl, request_ptr & r, bid_type & bi) :
50  block(bl), req(r), bid(bi) { }
51 
52  operator request_ptr () { return req; }
53  };
54  //typedef typename compat_hash_map < bid_type, request_ptr , bid_hash >::result hash_map_type;
55  //typedef typename hash_map_type::iterator block_track_iterator;
56  typedef typename std::list<block_type *>::iterator free_blocks_iterator;
57  typedef typename std::list<busy_entry>::iterator busy_blocks_iterator;
58 
59 protected:
60  // contains free write blocks
61  std::list<block_type *> free_blocks;
62  // blocks that are in writing
63  std::list<busy_entry> busy_blocks;
64 
65  //hash_map_type block_track;
66 
67  unsigned_type free_blocks_size, busy_blocks_size;
68 
69 public:
72  explicit write_pool(unsigned_type init_size = 1) : free_blocks_size(init_size), busy_blocks_size(0)
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(write_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  std::swap(busy_blocks_size, busy_blocks_size);
85  }
86 
88  virtual ~write_pool()
89  {
90  STXXL_VERBOSE2("write_pool::~write_pool free_blocks_size: " <<
91  free_blocks_size << " busy_blocks_size: " << busy_blocks_size);
92  while (!free_blocks.empty())
93  {
94  delete free_blocks.back();
95  free_blocks.pop_back();
96  }
97 
98  try
99  {
100  for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
101  {
102  i2->req->wait();
103  delete i2->block;
104  }
105  }
106  catch (...)
107  { }
108  }
109 
111  unsigned_type size() const { return free_blocks_size + busy_blocks_size; }
112 
119  request_ptr write(block_type * block, bid_type bid)
120  {
121  for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
122  {
123  if (i2->bid == bid && i2->block != block) {
124  STXXL_VERBOSE1("WAW dependency");
125  }
126  }
127  request_ptr result = block->write(bid);
128  ++busy_blocks_size;
129  busy_blocks.push_back(busy_entry(block, result, bid));
130  return result;
131  }
132 
135  block_type * steal()
136  {
137  assert(size() > 0);
138  if (free_blocks_size)
139  {
140  STXXL_VERBOSE1("write_pool::steal : " << free_blocks_size << " free blocks available");
141  --free_blocks_size;
142  block_type * p = free_blocks.back();
143  free_blocks.pop_back();
144  return p;
145  }
146  STXXL_VERBOSE1("write_pool::steal : all " << busy_blocks_size << " are busy");
147  busy_blocks_iterator completed = wait_any(busy_blocks.begin(), busy_blocks.end());
148  assert(completed != busy_blocks.end()); // we got something reasonable from wait_any
149  assert(completed->req->poll()); // and it is *really* completed
150  block_type * p = completed->block;
151  busy_blocks.erase(completed);
152  --busy_blocks_size;
153  check_all_busy(); // for debug
154  return p;
155  }
156 
157  // deprecated name for the steal()
158  __STXXL_DEPRECATED(block_type * get())
159  {
160  return steal();
161  }
162 
165  void resize(unsigned_type new_size)
166  {
167  int_type diff = int_type(new_size) - int_type(size());
168  if (diff > 0)
169  {
170  free_blocks_size += diff;
171  while (--diff >= 0)
172  free_blocks.push_back(new block_type);
173 
174 
175  return;
176  }
177 
178  while (++diff <= 0)
179  delete steal();
180  }
181 
182  request_ptr get_request(bid_type bid)
183  {
184  busy_blocks_iterator i2 = busy_blocks.begin();
185  for ( ; i2 != busy_blocks.end(); ++i2)
186  {
187  if (i2->bid == bid)
188  return i2->req;
189  }
190  return request_ptr();
191  }
192 
193 
194  block_type * steal(bid_type bid)
195  {
196  busy_blocks_iterator i2 = busy_blocks.begin();
197  for ( ; i2 != busy_blocks.end(); ++i2)
198  {
199  if (i2->bid == bid)
200  {
201  block_type * p = i2->block;
202  i2->req->wait();
203  busy_blocks.erase(i2);
204  --busy_blocks_size;
205  return p;
206  }
207  }
208  return NULL;
209  }
210 
211  void add(block_type * block)
212  {
213  free_blocks.push_back(block);
214  ++free_blocks_size;
215  }
216 
217 protected:
218  void check_all_busy()
219  {
220  busy_blocks_iterator cur = busy_blocks.begin();
221  int_type cnt = 0;
222 #if STXXL_VERBOSE_LEVEL > 0
223  int_type busy_blocks_size_old = busy_blocks_size;
224 #endif
225  for ( ; cur != busy_blocks.end(); ++cur)
226  {
227  if (cur->req->poll())
228  {
229  free_blocks.push_back(cur->block);
230  busy_blocks.erase(cur);
231  cur = busy_blocks.begin();
232  ++cnt;
233  --busy_blocks_size;
234  ++free_blocks_size;
235  if (busy_blocks.empty())
236  break;
237  }
238  }
239  STXXL_VERBOSE1("write_pool::check_all_busy : " << cnt <<
240  " are completed out of " << busy_blocks_size_old << " busy blocks");
241  }
242 };
243 
245 
246 __STXXL_END_NAMESPACE
247 
248 
249 namespace std
250 {
251  template <class BlockType>
252  void swap(stxxl::write_pool<BlockType> & a,
253  stxxl::write_pool<BlockType> & b)
254  {
255  a.swap(b);
256  }
257 }
258 
259 #endif // !STXXL_WRITE_POOL_HEADER