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

prefetch_pool.h

00001 /***************************************************************************
00002  *  include/stxxl/bits/mng/prefetch_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_PREFETCH_POOL_HEADER
00014 #define STXXL_PREFETCH_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/write_pool.h>
00023 #include <stxxl/bits/compat_hash_map.h>
00024 
00025 
00026 __STXXL_BEGIN_NAMESPACE
00027 
00030 
00032 template <class BlockType>
00033 class prefetch_pool : private noncopyable
00034 {
00035 public:
00036     typedef BlockType block_type;
00037     typedef typename block_type::bid_type bid_type;
00038 
00039 protected:
00040     struct bid_hash
00041     {
00042         size_t operator () (const bid_type & bid) const
00043         {
00044             size_t result = size_t(bid.storage) +
00045                             size_t(bid.offset & 0xffffffff) + size_t(bid.offset >> 32);
00046             return result;
00047         }
00048 #ifdef BOOST_MSVC
00049         bool operator () (const bid_type & a, const bid_type & b) const
00050         {
00051             return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset);
00052         }
00053         enum
00054         {                               // parameters for hash table
00055             bucket_size = 4,            // 0 < bucket_size
00056             min_buckets = 8             // min_buckets = 2 ^^ N, 0 < N
00057         };
00058 #endif
00059     };
00060     typedef std::pair<block_type *, request_ptr> busy_entry;
00061     typedef typename compat_hash_map<bid_type, busy_entry, bid_hash>::result hash_map_type;
00062     typedef typename std::list<block_type *>::iterator free_blocks_iterator;
00063     typedef typename hash_map_type::iterator busy_blocks_iterator;
00064 
00065     // contains free prefetch blocks
00066     std::list<block_type *> free_blocks;
00067     // blocks that are in reading or already read but not retrieved by user
00068     hash_map_type busy_blocks;
00069 
00070     unsigned_type free_blocks_size;
00071 
00072 public:
00075     explicit prefetch_pool(unsigned_type init_size = 1) : free_blocks_size(init_size)
00076     {
00077         unsigned_type i = 0;
00078         for ( ; i < init_size; ++i)
00079             free_blocks.push_back(new block_type);
00080     }
00081 
00082     void swap(prefetch_pool & obj)
00083     {
00084         std::swap(free_blocks, obj.free_blocks);
00085         std::swap(busy_blocks, obj.busy_blocks);
00086         std::swap(free_blocks_size, obj.free_blocks_size);
00087     }
00088 
00090     virtual ~prefetch_pool()
00091     {
00092         while (!free_blocks.empty())
00093         {
00094             delete free_blocks.back();
00095             free_blocks.pop_back();
00096         }
00097 
00098         try
00099         {
00100             busy_blocks_iterator i2 = busy_blocks.begin();
00101             for ( ; i2 != busy_blocks.end(); ++i2)
00102             {
00103                 i2->second.second->wait();
00104                 delete i2->second.first;
00105             }
00106         }
00107         catch (...)
00108         { }
00109     }
00111     unsigned_type size() const { return free_blocks_size + busy_blocks.size(); }
00112 
00120     bool hint(bid_type bid)
00121     {
00122         // if block is already hinted, no need to hint it again
00123         if (in_prefetching(bid)) {
00124             STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " was already cached");
00125             return true;
00126         }
00127 
00128         if (free_blocks_size) //  only if we have a free block
00129         {
00130             --free_blocks_size;
00131             block_type * block = free_blocks.back();
00132             free_blocks.pop_back();
00133             STXXL_VERBOSE2("prefetch_pool::hint bid=" << bid << " => prefetching");
00134             request_ptr req = block->read(bid);
00135             busy_blocks[bid] = busy_entry(block, req);
00136             return true;
00137         }
00138         STXXL_VERBOSE2("prefetch_pool::hint bid=" << bid << " => no free blocks for prefetching");
00139         return false;
00140     }
00141 
00142     bool hint(bid_type bid, write_pool<block_type> & w_pool)
00143     {
00144         // if block is already hinted, no need to hint it again
00145         if (in_prefetching(bid)) {
00146             STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " was already cached");
00147             return true;
00148         }
00149 
00150         if (free_blocks_size) //  only if we have a free block
00151         {
00152             --free_blocks_size;
00153             block_type * block = free_blocks.back();
00154             free_blocks.pop_back();
00155             if (w_pool.has_request(bid))
00156             {
00157                 busy_entry wp_request = w_pool.steal_request(bid);
00158                 STXXL_VERBOSE1("prefetch_pool::hint2 bid=" << bid << " was in write cache at " << wp_request.first);
00159                 assert(wp_request.first != 0);
00160                 w_pool.add(block);  //in exchange
00161                 busy_blocks[bid] = wp_request;
00162                 return true;
00163             }
00164             STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " => prefetching");
00165             request_ptr req = block->read(bid);
00166             busy_blocks[bid] = busy_entry(block, req);
00167             return true;
00168         }
00169         STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " => no free blocks for prefetching");
00170         return false;
00171     }
00172 
00173     bool invalidate(bid_type bid)
00174     {
00175         busy_blocks_iterator cache_el = busy_blocks.find(bid);
00176         if (cache_el == busy_blocks.end())
00177             return false;
00178 
00179         // cancel request if it is a read request, there might be
00180         // write requests 'stolen' from a write_pool that may not be cancelled
00181         if (cache_el->second.second->get_type() == request::READ)
00182             cache_el->second.second->cancel();
00183         // finish the request
00184         cache_el->second.second->wait();
00185         ++free_blocks_size;
00186         free_blocks.push_back(cache_el->second.first);
00187         busy_blocks.erase(cache_el);
00188         return true;
00189     }
00190 
00191     bool in_prefetching(bid_type bid)
00192     {
00193         return (busy_blocks.find(bid) != busy_blocks.end());
00194     }
00195 
00202     request_ptr read(block_type * & block, bid_type bid)
00203     {
00204         busy_blocks_iterator cache_el = busy_blocks.find(bid);
00205         if (cache_el == busy_blocks.end())
00206         {
00207             // not cached
00208             STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => no copy in cache, retrieving to " << block);
00209             return block->read(bid);
00210         }
00211 
00212         // cached
00213         STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => copy in cache exists");
00214         ++free_blocks_size;
00215         free_blocks.push_back(block);
00216         block = cache_el->second.first;
00217         request_ptr result = cache_el->second.second;
00218         busy_blocks.erase(cache_el);
00219         return result;
00220     }
00221 
00222     request_ptr read(block_type * & block, bid_type bid, write_pool<block_type> & w_pool)
00223     {
00224         // try cache
00225         busy_blocks_iterator cache_el = busy_blocks.find(bid);
00226         if (cache_el != busy_blocks.end())
00227         {
00228             // cached
00229             STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => copy in cache exists");
00230             ++free_blocks_size;
00231             free_blocks.push_back(block);
00232             block = cache_el->second.first;
00233             request_ptr result = cache_el->second.second;
00234             busy_blocks.erase(cache_el);
00235             return result;
00236         }
00237 
00238         // try w_pool cache
00239         if (w_pool.has_request(bid))
00240         {
00241             busy_entry wp_request = w_pool.steal_request(bid);
00242             STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " was in write cache at " << wp_request.first);
00243             assert(wp_request.first != 0);
00244             w_pool.add(block);  //in exchange
00245             block = wp_request.first;
00246             return wp_request.second;
00247         }
00248 
00249         // not cached
00250         STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => no copy in cache, retrieving to " << block);
00251         return block->read(bid);
00252     }
00253 
00260     unsigned_type resize(unsigned_type new_size)
00261     {
00262         int_type diff = int_type(new_size) - int_type(size());
00263         if (diff > 0)
00264         {
00265             free_blocks_size += diff;
00266             while (--diff >= 0)
00267                 free_blocks.push_back(new block_type);
00268 
00269 
00270             return size();
00271         }
00272 
00273         while (diff < 0 && free_blocks_size > 0)
00274         {
00275             ++diff;
00276             --free_blocks_size;
00277             delete free_blocks.back();
00278             free_blocks.pop_back();
00279         }
00280         return size();
00281     }
00282 };
00283 
00285 
00286 __STXXL_END_NAMESPACE
00287 
00288 namespace std
00289 {
00290     template <class BlockType>
00291     void swap(stxxl::prefetch_pool<BlockType> & a,
00292               stxxl::prefetch_pool<BlockType> & b)
00293     {
00294         a.swap(b);
00295     }
00296 }
00297 
00298 #endif // !STXXL_PREFETCH_POOL_HEADER
00299 // vim: et:ts=4:sw=4

Generated by  doxygen 1.7.1