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/mng/mng.h>
00023
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
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
00066
00067 unsigned_type free_blocks_size, busy_blocks_size;
00068
00069 public:
00072 explicit write_pool(unsigned_type init_size = 1) : free_blocks_size(init_size), busy_blocks_size(0)
00073 {
00074 unsigned_type i = 0;
00075 for ( ; i < init_size; ++i)
00076 free_blocks.push_back(new block_type);
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 std::swap(free_blocks_size, obj.free_blocks_size);
00084 std::swap(busy_blocks_size, busy_blocks_size);
00085 }
00086
00088 virtual ~write_pool()
00089 {
00090 STXXL_VERBOSE2("write_pool::~write_pool free_blocks_size: " <<
00091 free_blocks_size << " busy_blocks_size: " << busy_blocks_size);
00092 while (!free_blocks.empty())
00093 {
00094 delete free_blocks.back();
00095 free_blocks.pop_back();
00096 }
00097
00098 try
00099 {
00100 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00101 {
00102 i2->req->wait();
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 for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2)
00122 {
00123 if (i2->bid == bid && i2->block != block) {
00124 STXXL_VERBOSE1("WAW dependency");
00125 }
00126 }
00127 request_ptr result = block->write(bid);
00128 ++busy_blocks_size;
00129 busy_blocks.push_back(busy_entry(block, result, bid));
00130 return result;
00131 }
00132
00135 block_type * steal()
00136 {
00137 assert(size() > 0);
00138 if (free_blocks_size)
00139 {
00140 STXXL_VERBOSE1("write_pool::steal : " << free_blocks_size << " free blocks available");
00141 --free_blocks_size;
00142 block_type * p = free_blocks.back();
00143 free_blocks.pop_back();
00144 return p;
00145 }
00146 STXXL_VERBOSE1("write_pool::steal : all " << busy_blocks_size << " are busy");
00147 busy_blocks_iterator completed = wait_any(busy_blocks.begin(), busy_blocks.end());
00148 assert(completed != busy_blocks.end());
00149 assert(completed->req->poll());
00150 block_type * p = completed->block;
00151 busy_blocks.erase(completed);
00152 --busy_blocks_size;
00153 check_all_busy();
00154 return p;
00155 }
00156
00157
00158 __STXXL_DEPRECATED(block_type * get())
00159 {
00160 return steal();
00161 }
00162
00165 void resize(unsigned_type new_size)
00166 {
00167 int_type diff = int_type(new_size) - int_type(size());
00168 if (diff > 0)
00169 {
00170 free_blocks_size += diff;
00171 while (--diff >= 0)
00172 free_blocks.push_back(new block_type);
00173
00174
00175 return;
00176 }
00177
00178 while (++diff <= 0)
00179 delete steal();
00180 }
00181
00182 request_ptr get_request(bid_type bid)
00183 {
00184 busy_blocks_iterator i2 = busy_blocks.begin();
00185 for ( ; i2 != busy_blocks.end(); ++i2)
00186 {
00187 if (i2->bid == bid)
00188 return i2->req;
00189 }
00190 return request_ptr();
00191 }
00192
00193
00194 block_type * steal(bid_type bid)
00195 {
00196 busy_blocks_iterator i2 = busy_blocks.begin();
00197 for ( ; i2 != busy_blocks.end(); ++i2)
00198 {
00199 if (i2->bid == bid)
00200 {
00201 block_type * p = i2->block;
00202 i2->req->wait();
00203 busy_blocks.erase(i2);
00204 --busy_blocks_size;
00205 return p;
00206 }
00207 }
00208 return NULL;
00209 }
00210
00211 void add(block_type * block)
00212 {
00213 free_blocks.push_back(block);
00214 ++free_blocks_size;
00215 }
00216
00217 protected:
00218 void check_all_busy()
00219 {
00220 busy_blocks_iterator cur = busy_blocks.begin();
00221 int_type cnt = 0;
00222 #if STXXL_VERBOSE_LEVEL > 0
00223 int_type busy_blocks_size_old = busy_blocks_size;
00224 #endif
00225 for ( ; cur != busy_blocks.end(); ++cur)
00226 {
00227 if (cur->req->poll())
00228 {
00229 free_blocks.push_back(cur->block);
00230 busy_blocks.erase(cur);
00231 cur = busy_blocks.begin();
00232 ++cnt;
00233 --busy_blocks_size;
00234 ++free_blocks_size;
00235 if (busy_blocks.empty())
00236 break;
00237 }
00238 }
00239 STXXL_VERBOSE1("write_pool::check_all_busy : " << cnt <<
00240 " are completed out of " << busy_blocks_size_old << " busy blocks");
00241 }
00242 };
00243
00245
00246 __STXXL_END_NAMESPACE
00247
00248
00249 namespace std
00250 {
00251 template <class BlockType>
00252 void swap(stxxl::write_pool<BlockType> & a,
00253 stxxl::write_pool<BlockType> & b)
00254 {
00255 a.swap(b);
00256 }
00257 }
00258
00259 #endif // !STXXL_WRITE_POOL_HEADER