STXXL  1.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
disk_allocator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * lib/mng/disk_allocator.cpp
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002 Roman Dementiev <[email protected]>
7  * Copyright (C) 2008, 2010 Andreas Beckmann <[email protected]>
8  *
9  * Distributed under the Boost Software License, Version 1.0.
10  * (See accompanying file LICENSE_1_0.txt or copy at
11  * http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
18 #include <stxxl/bits/namespace.h>
19 #include <stxxl/bits/verbose.h>
20 
21 #include <cassert>
22 #include <map>
23 #include <ostream>
24 #include <utility>
25 
27 
28 void disk_allocator::dump() const
29 {
30  int64 total = 0;
31  sortseq::const_iterator cur = free_space.begin();
32  STXXL_ERRMSG("Free regions dump:");
33  for ( ; cur != free_space.end(); ++cur)
34  {
35  STXXL_ERRMSG("Free chunk: begin: " << (cur->first) << " size: " << (cur->second));
36  total += cur->second;
37  }
38  STXXL_ERRMSG("Total bytes: " << total);
39 }
40 
41 void disk_allocator::deallocation_error(
42  stxxl::int64 block_pos, stxxl::int64 block_size,
43  const sortseq::iterator& pred, const sortseq::iterator& succ) const
44 {
45  STXXL_ERRMSG("Error deallocating block at " << block_pos << " size " << block_size);
46  STXXL_ERRMSG(((pred == succ) ? "pred==succ" : "pred!=succ"));
47  if (pred == free_space.end()) {
48  STXXL_ERRMSG("pred==free_space.end()");
49  } else {
50  if (pred == free_space.begin())
51  STXXL_ERRMSG("pred==free_space.begin()");
52  STXXL_ERRMSG("pred: begin=" << pred->first << " size=" << pred->second);
53  }
54  if (succ == free_space.end()) {
55  STXXL_ERRMSG("succ==free_space.end()");
56  } else {
57  if (succ == free_space.begin())
58  STXXL_ERRMSG("succ==free_space.begin()");
59  STXXL_ERRMSG("succ: begin=" << succ->first << " size=" << succ->second);
60  }
61  dump();
62 }
63 
64 void disk_allocator::add_free_region(stxxl::int64 block_pos, stxxl::int64 block_size)
65 {
66  //assert(block_size);
67  //dump();
68  STXXL_VERBOSE2("Deallocating a block with size: " << block_size << " position: " << block_pos);
69  stxxl::int64 region_pos = block_pos;
70  stxxl::int64 region_size = block_size;
71  if (!free_space.empty())
72  {
73  sortseq::iterator succ = free_space.upper_bound(region_pos);
74  sortseq::iterator pred = succ;
75  if (pred != free_space.begin())
76  pred--;
77  if (pred != free_space.end())
78  {
79  if (pred->first <= region_pos && pred->first + pred->second > region_pos)
80  {
81  STXXL_THROW2(bad_ext_alloc, "disk_allocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " in empty space [" << pred->first << " + " << pred->second << "]");
82  }
83  }
84  if (succ != free_space.end())
85  {
86  if (region_pos <= succ->first && region_pos + region_size > succ->first)
87  {
88  STXXL_THROW2(bad_ext_alloc, "disk_allocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " which overlaps empty space [" << succ->first << " + " << succ->second << "]");
89  }
90  }
91  if (succ == free_space.end())
92  {
93  if (pred == free_space.end())
94  {
95  deallocation_error(block_pos, block_size, pred, succ);
96  assert(pred != free_space.end());
97  }
98  if ((*pred).first + (*pred).second == region_pos)
99  {
100  // coalesce with predecessor
101  region_size += (*pred).second;
102  region_pos = (*pred).first;
103  free_space.erase(pred);
104  }
105  }
106  else
107  {
108  if (free_space.size() > 1)
109  {
110 #if 0
111  if (pred == succ)
112  {
113  deallocation_error(block_pos, block_size, pred, succ);
114  assert(pred != succ);
115  }
116 #endif
117  bool succ_is_not_the_first = (succ != free_space.begin());
118  if ((*succ).first == region_pos + region_size)
119  {
120  // coalesce with successor
121  region_size += (*succ).second;
122  free_space.erase(succ);
123  //-tb: set succ to pred afterwards due to iterator invalidation
124  succ = pred;
125  }
126  if (succ_is_not_the_first)
127  {
128  if (pred == free_space.end())
129  {
130  deallocation_error(block_pos, block_size, pred, succ);
131  assert(pred != free_space.end());
132  }
133  if ((*pred).first + (*pred).second == region_pos)
134  {
135  // coalesce with predecessor
136  region_size += (*pred).second;
137  region_pos = (*pred).first;
138  free_space.erase(pred);
139  }
140  }
141  }
142  else
143  {
144  if ((*succ).first == region_pos + region_size)
145  {
146  // coalesce with successor
147  region_size += (*succ).second;
148  free_space.erase(succ);
149  }
150  }
151  }
152  }
153 
154  free_space[region_pos] = region_size;
155  free_bytes += block_size;
156 
157  //dump();
158 }
159 
161 // vim: et:ts=4:sw=4
long long int int64
Definition: types.h:38
#define STXXL_VERBOSE2(x)
Definition: verbose.h:107
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_THROW2(exception_type, location, error_message)
Throws exception_type with &quot;Error in [location] : [error_message]&quot;.
#define STXXL_ERRMSG(x)
Definition: verbose.h:80
#define STXXL_END_NAMESPACE
Definition: namespace.h:17