[subtracting_span_iterator] recode using run_set

This commit is contained in:
Joe Thornber
2013-07-09 11:25:09 +01:00
parent 2709629313
commit 311034f771
4 changed files with 82 additions and 95 deletions

View File

@ -71,7 +71,7 @@ namespace {
} }
virtual maybe_block find_free(span_iterator &it) { virtual maybe_block find_free(span_iterator &it) {
subtracting_span_iterator filtered_it(it, freed_blocks_); subtracting_span_iterator filtered_it(get_nr_blocks(), it, freed_blocks_);
return sm_->find_free(filtered_it); return sm_->find_free(filtered_it);
} }
@ -109,11 +109,11 @@ namespace {
} }
void mark_freed(block_address b) { void mark_freed(block_address b) {
freed_blocks_.insert(b); freed_blocks_.add(b, b + 1);
} }
bool was_freed(block_address b) const { bool was_freed(block_address b) const {
return freed_blocks_.count(b) > 0; return freed_blocks_.member(b) > 0;
} }
checked_space_map::ptr sm_; checked_space_map::ptr sm_;

View File

@ -129,7 +129,7 @@ namespace {
find_free(span_iterator &it) { find_free(span_iterator &it) {
recursing_lock lock(*this); recursing_lock lock(*this);
subtracting_span_iterator filtered_it(it, allocated_blocks_); subtracting_span_iterator filtered_it(get_nr_blocks(), it, allocated_blocks_);
return sm_->find_free(filtered_it); return sm_->find_free(filtered_it);
} }
@ -240,7 +240,7 @@ namespace {
ops_[op.b_].push_back(op); ops_[op.b_].push_back(op);
if (op.op_ == block_op::INC || (op.op_ == block_op::SET && op.rc_ > 0)) if (op.op_ == block_op::INC || (op.op_ == block_op::SET && op.rc_ > 0))
allocated_blocks_.insert(op.b_); allocated_blocks_.add(op.b_, op.b_ + 1);
} }
void cant_recurse(string const &method) const { void cant_recurse(string const &method) const {

View File

@ -2,98 +2,60 @@
#define SPAN_ITERATOR_H #define SPAN_ITERATOR_H
#include "persistent-data/space_map.h" #include "persistent-data/space_map.h"
#include "persistent-data/run_set.h"
#include <set> #include <set>
//---------------------------------------------------------------- //----------------------------------------------------------------
namespace persistent_data { namespace persistent_data {
// FIXME: rewrite with tests using the run_list stuff.
class subtracting_span_iterator : public space_map::span_iterator { class subtracting_span_iterator : public space_map::span_iterator {
public: public:
typedef set<block_address> block_set; typedef typename base::run_set<block_address> block_set;
typedef space_map::span span; typedef space_map::span span;
subtracting_span_iterator(span_iterator &sub_it, subtracting_span_iterator(block_address max,
span_iterator &sub_it,
block_set const &forbidden_blocks) block_set const &forbidden_blocks)
: sub_it_(sub_it), : max_(max) {
forbidden_blocks_(forbidden_blocks), for (maybe_span ms = sub_it.first(); ms; ms = sub_it.next())
current_begin_() { runs_.add(ms->first, ms->second);
block_set bs(forbidden_blocks);
runs_.negate();
runs_.merge(bs);
runs_.negate();
} }
virtual maybe_span first() { virtual maybe_span first() {
current_span_ = sub_it_.first(); current_ = runs_.begin();
return get_current();
if (current_span_)
current_begin_ = current_span_->first;
return next();
} }
virtual maybe_span next() { virtual maybe_span next() {
maybe_span r; if (current_ != runs_.end())
++current_;
while (more_spans()) { return get_current();
r = next_();
if (r)
break;
}
return r;
} }
private: private:
bool more_spans() const { maybe_span get_current() {
return current_span_; // FIXME: unsafe deref of begin and end
return (current_ == runs_.end()) ?
maybe_span() :
maybe_span(std::make_pair(maybe_default(current_->begin_, 0ULL),
maybe_default(current_->end_, max_)));
} }
bool span_consumed() const { typedef boost::optional<block_address> maybe;
return current_begin_ == current_span_->second; static block_address maybe_default(maybe const &m, block_address default_) {
return m ? *m : default_;
} }
bool forbidden_block(block_address b) const { block_address max_;
return forbidden_blocks_.count(b) > 0; block_set runs_;
} block_set::const_iterator current_;
void skip_forbidden_blocks() {
while (!span_consumed() && forbidden_block(current_begin_))
current_begin_++;
}
span get_span() {
block_address b = current_begin_;
while (!span_consumed() && !forbidden_block(current_begin_))
current_begin_++;
return span(b, current_begin_);
}
void get_current_span_from_sub_it() {
current_span_ = sub_it_.next();
if (current_span_)
current_begin_ = current_span_->first;
}
maybe_span next_() {
if (span_consumed())
get_current_span_from_sub_it();
if (!more_spans())
return maybe_span();
skip_forbidden_blocks();
if (!span_consumed())
return maybe_span(get_span());
else
return maybe_span();
}
span_iterator &sub_it_;
block_set const &forbidden_blocks_;
maybe_span current_span_;
block_address current_begin_;
}; };
} }

View File

@ -1,6 +1,7 @@
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "persistent-data/space-maps/subtracting_span_iterator.h" #include "persistent-data/space-maps/subtracting_span_iterator.h"
#include "persistent-data/run_set.h"
using namespace std; using namespace std;
using namespace persistent_data; using namespace persistent_data;
@ -53,27 +54,42 @@ namespace {
class span_iterator_mock : public space_map::span_iterator { class span_iterator_mock : public space_map::span_iterator {
public: public:
span_iterator_mock() {
Sequence dummy;
EXPECT_CALL(*this, first()).
InSequence(dummy).
WillOnce(Return(maybe_span(span(23, 47))));
EXPECT_CALL(*this, next()).
InSequence(dummy).
WillOnce(Return(maybe_span(span(59, 103))));
EXPECT_CALL(*this, next()).
InSequence(dummy).
WillOnce(Return(maybe_span()));
}
MOCK_METHOD0(first, maybe_span()); MOCK_METHOD0(first, maybe_span());
MOCK_METHOD0(next, maybe_span()); MOCK_METHOD0(next, maybe_span());
}; };
class SpanItTests : public Test { class SpanItTests : public Test {
public: public:
SpanItTests() subtracting_span_iterator run() {
: it(mock_it, forbidden) { span_iterator_mock mock_it;
return subtracting_span_iterator(1000, mock_it, forbidden);
EXPECT_CALL(mock_it, first()).
Times(1).
WillOnce(Return(maybe_span(span(23, 47))));
EXPECT_CALL(mock_it, next()).
Times(1).
WillOnce(Return(maybe_span(span(59, 103))));
} }
span_iterator_mock mock_it; base::run_set<block_address> forbidden;
set<block_address> forbidden;
subtracting_span_iterator it;
}; };
ostream &operator <<(ostream &out, maybe_span const &m) {
out << "maybe_span[";
if (m)
out << m->first << ", " << m->second;
out << "]";
return out;
}
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -103,14 +119,16 @@ TEST(RegularSpanItTests, regular_span_iterator)
TEST_F(SpanItTests, sub_it_with_no_removed_blocks) TEST_F(SpanItTests, sub_it_with_no_removed_blocks)
{ {
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
} }
TEST_F(SpanItTests, sub_it_with_removed_first_block) TEST_F(SpanItTests, sub_it_with_removed_first_block)
{ {
forbidden.insert(23); forbidden.add(23);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(24, 47)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(24, 47))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
} }
@ -118,16 +136,18 @@ TEST_F(SpanItTests, sub_it_with_removed_first_block)
TEST_F(SpanItTests, sub_it_with_removed_run_overlapping_front_of_first_block) TEST_F(SpanItTests, sub_it_with_removed_run_overlapping_front_of_first_block)
{ {
for (block_address i = 19; i < 26; i++) for (block_address i = 19; i < 26; i++)
forbidden.insert(i); forbidden.add(i);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(26, 47)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(26, 47))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
} }
TEST_F(SpanItTests, sub_it_with_removed_mid_block) TEST_F(SpanItTests, sub_it_with_removed_mid_block)
{ {
forbidden.insert(40); forbidden.add(40);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 40)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 40))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(41, 47)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(41, 47))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
@ -136,8 +156,9 @@ TEST_F(SpanItTests, sub_it_with_removed_mid_block)
TEST_F(SpanItTests, sub_it_with_removed_run_mid_block) TEST_F(SpanItTests, sub_it_with_removed_run_mid_block)
{ {
for (block_address i = 26; i < 36; i++) for (block_address i = 26; i < 36; i++)
forbidden.insert(i); forbidden.add(i);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(36, 47)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(36, 47))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
@ -145,8 +166,9 @@ TEST_F(SpanItTests, sub_it_with_removed_run_mid_block)
TEST_F(SpanItTests, sub_it_with_removed_end_block) TEST_F(SpanItTests, sub_it_with_removed_end_block)
{ {
forbidden.insert(46); forbidden.add(46);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 46)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 46))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
} }
@ -154,8 +176,9 @@ TEST_F(SpanItTests, sub_it_with_removed_end_block)
TEST_F(SpanItTests, sub_it_with_removed_run_end_block) TEST_F(SpanItTests, sub_it_with_removed_run_end_block)
{ {
for (block_address i = 26; i < 50; i++) for (block_address i = 26; i < 50; i++)
forbidden.insert(i); forbidden.add(i);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
} }
@ -163,19 +186,21 @@ TEST_F(SpanItTests, sub_it_with_removed_run_end_block)
TEST_F(SpanItTests, sub_it_with_removed_run_overlapping_2_blocks) TEST_F(SpanItTests, sub_it_with_removed_run_overlapping_2_blocks)
{ {
for (block_address i = 26; i < 70; i++) for (block_address i = 26; i < 70; i++)
forbidden.insert(i); forbidden.add(i);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(70, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(70, 103))));
} }
TEST_F(SpanItTests, sub_it_with_removed_intermediate_blocks) TEST_F(SpanItTests, sub_it_with_removed_intermediate_blocks)
{ {
forbidden.insert(53); forbidden.add(53);
forbidden.insert(54); forbidden.add(54);
forbidden.insert(57); forbidden.add(57);
forbidden.insert(58); forbidden.add(58);
auto it = run();
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47)))); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47))));
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
} }