diff --git a/persistent-data/space-maps/careful_alloc.cc b/persistent-data/space-maps/careful_alloc.cc index ae35ec2..7ef0217 100644 --- a/persistent-data/space-maps/careful_alloc.cc +++ b/persistent-data/space-maps/careful_alloc.cc @@ -71,7 +71,7 @@ namespace { } 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); } @@ -109,11 +109,11 @@ namespace { } void mark_freed(block_address b) { - freed_blocks_.insert(b); + freed_blocks_.add(b, b + 1); } bool was_freed(block_address b) const { - return freed_blocks_.count(b) > 0; + return freed_blocks_.member(b) > 0; } checked_space_map::ptr sm_; diff --git a/persistent-data/space-maps/recursive.cc b/persistent-data/space-maps/recursive.cc index 09d63e5..f7939e9 100644 --- a/persistent-data/space-maps/recursive.cc +++ b/persistent-data/space-maps/recursive.cc @@ -129,7 +129,7 @@ namespace { find_free(span_iterator &it) { 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); } @@ -240,7 +240,7 @@ namespace { ops_[op.b_].push_back(op); 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 { diff --git a/persistent-data/space-maps/subtracting_span_iterator.h b/persistent-data/space-maps/subtracting_span_iterator.h index 7cad531..602a783 100644 --- a/persistent-data/space-maps/subtracting_span_iterator.h +++ b/persistent-data/space-maps/subtracting_span_iterator.h @@ -2,98 +2,60 @@ #define SPAN_ITERATOR_H #include "persistent-data/space_map.h" +#include "persistent-data/run_set.h" #include //---------------------------------------------------------------- namespace persistent_data { - // FIXME: rewrite with tests using the run_list stuff. class subtracting_span_iterator : public space_map::span_iterator { public: - typedef set block_set; + typedef typename base::run_set block_set; 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) - : sub_it_(sub_it), - forbidden_blocks_(forbidden_blocks), - current_begin_() { + : max_(max) { + for (maybe_span ms = sub_it.first(); ms; ms = sub_it.next()) + runs_.add(ms->first, ms->second); + + block_set bs(forbidden_blocks); + runs_.negate(); + runs_.merge(bs); + runs_.negate(); } virtual maybe_span first() { - current_span_ = sub_it_.first(); - - if (current_span_) - current_begin_ = current_span_->first; - - return next(); + current_ = runs_.begin(); + return get_current(); } virtual maybe_span next() { - maybe_span r; + if (current_ != runs_.end()) + ++current_; - while (more_spans()) { - r = next_(); - if (r) - break; - } - - return r; + return get_current(); } private: - bool more_spans() const { - return current_span_; + maybe_span get_current() { + // 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 { - return current_begin_ == current_span_->second; + typedef boost::optional maybe; + static block_address maybe_default(maybe const &m, block_address default_) { + return m ? *m : default_; } - bool forbidden_block(block_address b) const { - return forbidden_blocks_.count(b) > 0; - } - - 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_; + block_address max_; + block_set runs_; + block_set::const_iterator current_; }; } diff --git a/unit-tests/span_iterator_t.cc b/unit-tests/span_iterator_t.cc index 8c6a188..c75640a 100644 --- a/unit-tests/span_iterator_t.cc +++ b/unit-tests/span_iterator_t.cc @@ -1,6 +1,7 @@ #include "gmock/gmock.h" #include "persistent-data/space-maps/subtracting_span_iterator.h" +#include "persistent-data/run_set.h" using namespace std; using namespace persistent_data; @@ -53,27 +54,42 @@ namespace { class span_iterator_mock : public space_map::span_iterator { 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(next, maybe_span()); }; class SpanItTests : public Test { public: - SpanItTests() - : it(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)))); + subtracting_span_iterator run() { + span_iterator_mock mock_it; + return subtracting_span_iterator(1000, mock_it, forbidden); } - span_iterator_mock mock_it; - set forbidden; - subtracting_span_iterator it; + base::run_set forbidden; }; + + 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) { + auto it = run(); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); } 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.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) { 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.next(), Eq(maybe_span(span(59, 103)))); } 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.next(), Eq(maybe_span(span(41, 47)))); 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) { 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.next(), Eq(maybe_span(span(36, 47)))); 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) { - forbidden.insert(46); + forbidden.add(46); + auto it = run(); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 46)))); 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) { 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.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) { 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.next(), Eq(maybe_span(span(70, 103)))); } TEST_F(SpanItTests, sub_it_with_removed_intermediate_blocks) { - forbidden.insert(53); - forbidden.insert(54); - forbidden.insert(57); - forbidden.insert(58); + forbidden.add(53); + forbidden.add(54); + forbidden.add(57); + forbidden.add(58); + auto it = run(); ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47)))); ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103)))); }