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