00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef STXXL_WRITE_POOL_HEADER
00014 #define STXXL_WRITE_POOL_HEADER
00015
00016 #include <list>
00017
00018 #ifdef STXXL_BOOST_CONFIG
00019 #include <boost/config.hpp>
00020 #endif
00021
00022 #include <stxxl/bits/noncopyable.h>
00023 #include <stxxl/bits/io/request.h>
00024
00025
00026 __STXXL_BEGIN_NAMESPACE
00027
00030
00031
00033 template <class BlockType>
00034 class write_pool : private noncopyable
00035 {
00036 public:
00037 typedef BlockType block_type;
00038 typedef typename block_type::bid_type bid_type;
00039
00040
00041 struct busy_entry
00042 {
00043 block_type * block;
00044 request_ptr req;
00045 bid_type bid;
00046
00047 busy_entry() : block(NULL) { }
00048 busy_entry(const busy_entry & a) : block(a.block), req(a.req), bid(a.bid) { }
00049 busy_entry(block_type * & bl, request_ptr & r, bid_type & bi) :
00050 block(bl), req(r), bid(bi) { }
00051
00052 operator request_ptr () { return req; }
00053 };
00054 typedef typename std::list<block_type *>::iterator free_blocks_iterator;
00055 typedef typename std::list<busy_entry>::iterator busy_blocks_iterator;
00056
00057 protected:
00058
00059 std::list<block_type *> free_blocks;
00060
00061 std::list<busy_entry> busy_blocks;
00062
00063 unsigned_type free_blocks_size, busy_blocks_size;
00064
00065 public:
00068 explicit write_pool(unsigned_type init_size = 1) : free_blocks_size(init_size), busy_blocks_size(0)
00069 {
00070 unsigned_type i = 0;
00071 for ( ; i < init_size; ++i)
00072 free_blocks.push_back(new block_type);
00073 }
00074
00075 void swap(write_pool & obj)
00076 {
00077 std::swap(free_blocks, obj.free_blocks);
00078 std::swap(busy_blocks, obj.busy_blocks);
00079 std::swap(free_blocks_size, obj.free_blocks_size);
00080 std::swap(busy_blocks_size, busy_blocks_size);
00081 }
00082
00084 virtual ~write_pool()
00085 {
00086 STXXL_VERBOSE2("write_pool::~write_pool free_blocks_size: " <<
00087 free_blocks_size << " busy_blocks_size: " << busy_blocks_size);
00088 while (!free_blocks.empty())
00089 {
00090 delete free_blocks.back();
00091 free_blocks.pop_back();
00092 }
00093
00094 try
00095 {
00096 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00097 {
00098 i2->req->wait();
00099 delete i2->block;
00100 }
00101 }
00102 catch (...)
00103 { }
00104 }
00105
00107 unsigned_type size() const { return free_blocks_size + busy_blocks_size; }
00108
00115 request_ptr write(block_type * & block, bid_type bid)
00116 {
00117 STXXL_VERBOSE1("write_pool::write: " << block << " @ " << bid);
00118 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00119 {
00120 if (i2->bid == bid) {
00121 assert(i2->block != block);
00122 STXXL_VERBOSE1("WAW dependency");
00123
00124 i2->req->cancel();
00125
00126
00127 i2->bid.storage = 0;
00128 }
00129 }
00130 request_ptr result = block->write(bid);
00131 ++busy_blocks_size;
00132 busy_blocks.push_back(busy_entry(block, result, bid));
00133 block = NULL;
00134 return result;
00135 }
00136
00139 block_type * steal()
00140 {
00141 assert(size() > 0);
00142 if (free_blocks_size)
00143 {
00144 STXXL_VERBOSE1("write_pool::steal : " << free_blocks_size << " free blocks available");
00145 --free_blocks_size;
00146 block_type * p = free_blocks.back();
00147 free_blocks.pop_back();
00148 return p;
00149 }
00150 STXXL_VERBOSE1("write_pool::steal : all " << busy_blocks_size << " are busy");
00151 busy_blocks_iterator completed = wait_any(busy_blocks.begin(), busy_blocks.end());
00152 assert(completed != busy_blocks.end());
00153 assert(completed->req->poll());
00154 block_type * p = completed->block;
00155 busy_blocks.erase(completed);
00156 --busy_blocks_size;
00157 check_all_busy();
00158 return p;
00159 }
00160
00161
00162 _STXXL_DEPRECATED(block_type * get())
00163 {
00164 return steal();
00165 }
00166
00169 void resize(unsigned_type new_size)
00170 {
00171 int_type diff = int_type(new_size) - int_type(size());
00172 if (diff > 0)
00173 {
00174 free_blocks_size += diff;
00175 while (--diff >= 0)
00176 free_blocks.push_back(new block_type);
00177
00178 return;
00179 }
00180
00181 while (++diff <= 0)
00182 delete steal();
00183 }
00184
00185 _STXXL_DEPRECATED(request_ptr get_request(bid_type bid))
00186 {
00187 busy_blocks_iterator i2 = busy_blocks.begin();
00188 for ( ; i2 != busy_blocks.end(); ++i2)
00189 {
00190 if (i2->bid == bid)
00191 return i2->req;
00192 }
00193 return request_ptr();
00194 }
00195
00196 bool has_request(bid_type bid)
00197 {
00198 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00199 {
00200 if (i2->bid == bid)
00201 return true;
00202 }
00203 return false;
00204 }
00205
00206 _STXXL_DEPRECATED(block_type * steal(bid_type bid))
00207 {
00208 busy_blocks_iterator i2 = busy_blocks.begin();
00209 for ( ; i2 != busy_blocks.end(); ++i2)
00210 {
00211 if (i2->bid == bid)
00212 {
00213 block_type * p = i2->block;
00214 i2->req->wait();
00215 busy_blocks.erase(i2);
00216 --busy_blocks_size;
00217 return p;
00218 }
00219 }
00220 return NULL;
00221 }
00222
00223
00224 std::pair<block_type *, request_ptr> steal_request(bid_type bid)
00225 {
00226 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00227 {
00228 if (i2->bid == bid)
00229 {
00230
00231 block_type * blk = i2->block;
00232 request_ptr req = i2->req;
00233 busy_blocks.erase(i2);
00234 --busy_blocks_size;
00235
00236
00237 return std::pair<block_type *, request_ptr>(blk, req);
00238 }
00239 }
00240
00241 return std::pair<block_type *, request_ptr>((block_type *)NULL, request_ptr());
00242 }
00243
00244 void add(block_type * & block)
00245 {
00246 free_blocks.push_back(block);
00247 ++free_blocks_size;
00248 block = NULL;
00249 }
00250
00251 protected:
00252 void check_all_busy()
00253 {
00254 busy_blocks_iterator cur = busy_blocks.begin();
00255 int_type cnt = 0;
00256 while (cur != busy_blocks.end())
00257 {
00258 if (cur->req->poll())
00259 {
00260 free_blocks.push_back(cur->block);
00261 cur = busy_blocks.erase(cur);
00262 ++cnt;
00263 --busy_blocks_size;
00264 ++free_blocks_size;
00265 continue;
00266 }
00267 ++cur;
00268 }
00269 STXXL_VERBOSE1("write_pool::check_all_busy : " << cnt <<
00270 " are completed out of " << busy_blocks_size + cnt << " busy blocks");
00271 }
00272 };
00273
00275
00276 __STXXL_END_NAMESPACE
00277
00278
00279 namespace std
00280 {
00281 template <class BlockType>
00282 void swap(stxxl::write_pool<BlockType> & a,
00283 stxxl::write_pool<BlockType> & b)
00284 {
00285 a.swap(b);
00286 }
00287 }
00288
00289 #endif // !STXXL_WRITE_POOL_HEADER
00290