• 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/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

Generated by  doxygen 1.7.1