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 #define STXXL_VERBOSE_WPOOL(msg) STXXL_VERBOSE1("write_pool[" << static_cast<void *>(this) << "]" << msg)
00028
00029
00030 __STXXL_BEGIN_NAMESPACE
00031
00034
00035
00037 template <class BlockType>
00038 class write_pool : private noncopyable
00039 {
00040 public:
00041 typedef BlockType block_type;
00042 typedef typename block_type::bid_type bid_type;
00043
00044
00045 struct busy_entry
00046 {
00047 block_type * block;
00048 request_ptr req;
00049 bid_type bid;
00050
00051 busy_entry() : block(NULL) { }
00052 busy_entry(const busy_entry & a) : block(a.block), req(a.req), bid(a.bid) { }
00053 busy_entry(block_type * & bl, request_ptr & r, bid_type & bi) :
00054 block(bl), req(r), bid(bi) { }
00055
00056 operator request_ptr () { return req; }
00057 };
00058 typedef typename std::list<block_type *>::iterator free_blocks_iterator;
00059 typedef typename std::list<busy_entry>::iterator busy_blocks_iterator;
00060
00061 protected:
00062
00063 std::list<block_type *> free_blocks;
00064
00065 std::list<busy_entry> busy_blocks;
00066
00067 public:
00070 explicit write_pool(unsigned_type init_size = 1)
00071 {
00072 for (unsigned_type i = 0; i < init_size; ++i)
00073 {
00074 free_blocks.push_back(new block_type);
00075 STXXL_VERBOSE_WPOOL(" create block=" << free_blocks.back());
00076 }
00077 }
00078
00079 void swap(write_pool & obj)
00080 {
00081 std::swap(free_blocks, obj.free_blocks);
00082 std::swap(busy_blocks, obj.busy_blocks);
00083 }
00084
00086 virtual ~write_pool()
00087 {
00088 STXXL_VERBOSE_WPOOL("::~write_pool free_blocks.size()=" << free_blocks.size() <<
00089 " busy_blocks.size()=" << busy_blocks.size());
00090 while (!free_blocks.empty())
00091 {
00092 STXXL_VERBOSE_WPOOL(" delete free block=" << free_blocks.back());
00093 delete free_blocks.back();
00094 free_blocks.pop_back();
00095 }
00096
00097 try
00098 {
00099 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00100 {
00101 i2->req->wait();
00102 STXXL_VERBOSE_WPOOL(" delete busy block=" << free_blocks.back());
00103 delete i2->block;
00104 }
00105 }
00106 catch (...)
00107 { }
00108 }
00109
00111 unsigned_type size() const { return free_blocks.size() + busy_blocks.size(); }
00112
00119 request_ptr write(block_type * & block, bid_type bid)
00120 {
00121 STXXL_VERBOSE_WPOOL("::write: " << block << " @ " << bid);
00122 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00123 {
00124 if (i2->bid == bid) {
00125 assert(i2->block != block);
00126 STXXL_VERBOSE_WPOOL("WAW dependency");
00127
00128 i2->req->cancel();
00129
00130
00131 i2->bid.storage = 0;
00132 }
00133 }
00134 request_ptr result = block->write(bid);
00135 busy_blocks.push_back(busy_entry(block, result, bid));
00136 block = NULL;
00137 return result;
00138 }
00139
00142 block_type * steal()
00143 {
00144 assert(size() > 0);
00145 if (!free_blocks.empty())
00146 {
00147 block_type * p = free_blocks.back();
00148 STXXL_VERBOSE_WPOOL("::steal : " << free_blocks.size() << " free blocks available, serve block=" << p);
00149 free_blocks.pop_back();
00150 return p;
00151 }
00152 STXXL_VERBOSE_WPOOL("::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 check_all_busy();
00159 STXXL_VERBOSE_WPOOL(" serve block=" << p);
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 while (--diff >= 0)
00177 {
00178 free_blocks.push_back(new block_type);
00179 STXXL_VERBOSE_WPOOL(" create block=" << free_blocks.back());
00180 }
00181
00182 return;
00183 }
00184
00185 while (++diff <= 0)
00186 delete steal();
00187 }
00188
00189 _STXXL_DEPRECATED(request_ptr get_request(bid_type bid))
00190 {
00191 busy_blocks_iterator i2 = busy_blocks.begin();
00192 for ( ; i2 != busy_blocks.end(); ++i2)
00193 {
00194 if (i2->bid == bid)
00195 return i2->req;
00196 }
00197 return request_ptr();
00198 }
00199
00200 bool has_request(bid_type bid)
00201 {
00202 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00203 {
00204 if (i2->bid == bid)
00205 return true;
00206 }
00207 return false;
00208 }
00209
00210 _STXXL_DEPRECATED(block_type * steal(bid_type bid))
00211 {
00212 busy_blocks_iterator i2 = busy_blocks.begin();
00213 for ( ; i2 != busy_blocks.end(); ++i2)
00214 {
00215 if (i2->bid == bid)
00216 {
00217 block_type * p = i2->block;
00218 i2->req->wait();
00219 busy_blocks.erase(i2);
00220 return p;
00221 }
00222 }
00223 return NULL;
00224 }
00225
00226
00227 std::pair<block_type *, request_ptr> steal_request(bid_type bid)
00228 {
00229 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00230 {
00231 if (i2->bid == bid)
00232 {
00233
00234 block_type * blk = i2->block;
00235 request_ptr req = i2->req;
00236 busy_blocks.erase(i2);
00237
00238 STXXL_VERBOSE_WPOOL("::steal_request block=" << blk);
00239
00240 return std::pair<block_type *, request_ptr>(blk, req);
00241 }
00242 }
00243 STXXL_VERBOSE_WPOOL("::steal_request NOT FOUND");
00244
00245 return std::pair<block_type *, request_ptr>((block_type *)NULL, request_ptr());
00246 }
00247
00248 void add(block_type * & block)
00249 {
00250 STXXL_VERBOSE_WPOOL("::add " << block);
00251 free_blocks.push_back(block);
00252 block = NULL;
00253 }
00254
00255 protected:
00256 void check_all_busy()
00257 {
00258 busy_blocks_iterator cur = busy_blocks.begin();
00259 int_type cnt = 0;
00260 while (cur != busy_blocks.end())
00261 {
00262 if (cur->req->poll())
00263 {
00264 free_blocks.push_back(cur->block);
00265 cur = busy_blocks.erase(cur);
00266 ++cnt;
00267 continue;
00268 }
00269 ++cur;
00270 }
00271 STXXL_VERBOSE_WPOOL("::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