Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * mng/diskallocator.cpp 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2008, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00008 * 00009 * Distributed under the Boost Software License, Version 1.0. 00010 * (See accompanying file LICENSE_1_0.txt or copy at 00011 * http://www.boost.org/LICENSE_1_0.txt) 00012 **************************************************************************/ 00013 00014 #include <stxxl/bits/mng/diskallocator.h> 00015 #include <stxxl/bits/common/error_handling.h> 00016 00017 00018 __STXXL_BEGIN_NAMESPACE 00019 00020 void DiskAllocator::dump() const 00021 { 00022 int64 total = 0; 00023 sortseq::const_iterator cur = free_space.begin(); 00024 STXXL_ERRMSG("Free regions dump:"); 00025 for ( ; cur != free_space.end(); ++cur) 00026 { 00027 STXXL_ERRMSG("Free chunk: begin: " << (cur->first) << " size: " << (cur->second)); 00028 total += cur->second; 00029 } 00030 STXXL_ERRMSG("Total bytes: " << total); 00031 } 00032 00033 00034 void DiskAllocator::deallocation_error( 00035 stxxl::int64 block_pos, stxxl::int64 block_size, 00036 const sortseq::iterator & pred, const sortseq::iterator & succ) const 00037 { 00038 STXXL_ERRMSG("Error deallocating block at " << block_pos << " size " << block_size); 00039 STXXL_ERRMSG(((pred == succ) ? "pred==succ" : "pred!=succ")); 00040 if (pred == free_space.end()) { 00041 STXXL_ERRMSG("pred==free_space.end()"); 00042 } else { 00043 if (pred == free_space.begin()) 00044 STXXL_ERRMSG("pred==free_space.begin()"); 00045 STXXL_ERRMSG("pred: begin=" << pred->first << " size=" << pred->second); 00046 } 00047 if (succ == free_space.end()) { 00048 STXXL_ERRMSG("succ==free_space.end()"); 00049 } else { 00050 if (succ == free_space.begin()) 00051 STXXL_ERRMSG("succ==free_space.begin()"); 00052 STXXL_ERRMSG("succ: begin=" << succ->first << " size=" << succ->second); 00053 } 00054 dump(); 00055 } 00056 00057 00058 void DiskAllocator::add_free_region(stxxl::int64 block_pos, stxxl::int64 block_size) 00059 { 00060 //assert(block_size); 00061 //dump(); 00062 STXXL_VERBOSE2("Deallocating a block with size: " << block_size << " position: " << block_pos); 00063 stxxl::int64 region_pos = block_pos; 00064 stxxl::int64 region_size = block_size; 00065 if (!free_space.empty()) 00066 { 00067 sortseq::iterator succ = free_space.upper_bound(region_pos); 00068 sortseq::iterator pred = succ; 00069 if (pred != free_space.begin()) 00070 pred--; 00071 if (pred != free_space.end()) 00072 { 00073 if (pred->first <= region_pos && pred->first + pred->second > region_pos) 00074 { 00075 STXXL_THROW(bad_ext_alloc, "DiskAllocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " in empty space [" << pred->first << " + " << pred->second << "]"); 00076 } 00077 } 00078 if (succ != free_space.end()) 00079 { 00080 if (region_pos <= succ->first && region_pos + region_size > succ->first) 00081 { 00082 STXXL_THROW(bad_ext_alloc, "DiskAllocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " which overlaps empty space [" << succ->first << " + " << succ->second << "]"); 00083 } 00084 } 00085 if (succ == free_space.end()) 00086 { 00087 if (pred == free_space.end()) 00088 { 00089 deallocation_error(block_pos, block_size, pred, succ); 00090 assert(pred != free_space.end()); 00091 } 00092 if ((*pred).first + (*pred).second == region_pos) 00093 { 00094 // coalesce with predecessor 00095 region_size += (*pred).second; 00096 region_pos = (*pred).first; 00097 free_space.erase(pred); 00098 } 00099 } 00100 else 00101 { 00102 if (free_space.size() > 1) 00103 { 00104 #if 0 00105 if (pred == succ) 00106 { 00107 deallocation_error(block_pos, block_size, pred, succ); 00108 assert(pred != succ); 00109 } 00110 #endif 00111 bool succ_is_not_the_first = (succ != free_space.begin()); 00112 if ((*succ).first == region_pos + region_size) 00113 { 00114 // coalesce with successor 00115 region_size += (*succ).second; 00116 free_space.erase(succ); 00117 } 00118 if (succ_is_not_the_first) 00119 { 00120 if (pred == free_space.end()) 00121 { 00122 deallocation_error(block_pos, block_size, pred, succ); 00123 assert(pred != free_space.end()); 00124 } 00125 if ((*pred).first + (*pred).second == region_pos) 00126 { 00127 // coalesce with predecessor 00128 region_size += (*pred).second; 00129 region_pos = (*pred).first; 00130 free_space.erase(pred); 00131 } 00132 } 00133 } 00134 else 00135 { 00136 if ((*succ).first == region_pos + region_size) 00137 { 00138 // coalesce with successor 00139 region_size += (*succ).second; 00140 free_space.erase(succ); 00141 } 00142 } 00143 } 00144 } 00145 00146 free_space[region_pos] = region_size; 00147 free_bytes += block_size; 00148 00149 //dump(); 00150 } 00151 00152 __STXXL_END_NAMESPACE 00153 // vim: et:ts=4:sw=4