• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List

write_pool.h

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 <[email protected]>
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/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     // 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 std::list<block_type *>::iterator free_blocks_iterator;
00055     typedef typename std::list<busy_entry>::iterator busy_blocks_iterator;
00056 
00057 protected:
00058     // contains free write blocks
00059     std::list<block_type *> free_blocks;
00060     // blocks that are in writing
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                 // try to cancel the obsolete request
00124                 i2->req->cancel();
00125                 // invalidate the bid of the stale write request,
00126                 // prevents prefetch_pool from stealing a stale block
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; // prevent caller from using the block any further
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()); // we got something reasonable from wait_any
00153         assert(completed->req->poll());         // and it is *really* completed
00154         block_type * p = completed->block;
00155         busy_blocks.erase(completed);
00156         --busy_blocks_size;
00157         check_all_busy();                       // for debug
00158         return p;
00159     }
00160 
00161     // deprecated name for the steal()
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     // returns a block and a (potentially unfinished) I/O request associated with it
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                 // remove busy block from list, request has not yet been waited for!
00231                 block_type * blk = i2->block;
00232                 request_ptr req = i2->req;
00233                 busy_blocks.erase(i2);
00234                 --busy_blocks_size;
00235 
00236                 // hand over block and (unfinished) request to caller
00237                 return std::pair<block_type *, request_ptr>(blk, req);
00238             }
00239         }
00240         // not matching request found, return a dummy
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; // prevent caller from using the block any further
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 // vim: et:ts=4:sw=4

Generated by  doxygen 1.7.1