Stxxl
1.2.1
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/mng/write_pool.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2003-2004 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * 00008 * Distributed under the Boost Software License, Version 1.0. 00009 * (See accompanying file LICENSE_1_0.txt or copy at 00010 * http://www.boost.org/LICENSE_1_0.txt) 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 //#include <stxxl/bits/compat_hash_map.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 // a hack to make wait_any work with busy_entry type 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 compat_hash_map < bid_type, request_ptr , bid_hash >::result hash_map_type; 00055 //typedef typename hash_map_type::iterator block_track_iterator; 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 // contains free write blocks 00061 std::list<block_type *> free_blocks; 00062 // blocks that are in writing 00063 std::list<busy_entry> busy_blocks; 00064 00065 //hash_map_type block_track; 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()); // we got something reasonable from wait_any 00149 assert(completed->req->poll()); // and it is *really* completed 00150 block_type * p = completed->block; 00151 busy_blocks.erase(completed); 00152 --busy_blocks_size; 00153 check_all_busy(); // for debug 00154 return p; 00155 } 00156 00157 // deprecated name for the steal() 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