Clean up Iterator.

This CL renames the private struct Iterator::Cleanup ->
Iterator::CleanupNode, to better reflect that it's a linked list node,
and extracts duplicated code from its user in IsEmpty() and Run()
methods.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=199175058
This commit is contained in:
costan 2018-06-04 12:29:13 -07:00 committed by Victor Costan
parent 6a6bdafcf1
commit 6caf73ad9d
2 changed files with 45 additions and 32 deletions

View File

@ -77,17 +77,25 @@ class LEVELDB_EXPORT Iterator {
// //
// Note that unlike all of the preceding methods, this method is // Note that unlike all of the preceding methods, this method is
// not abstract and therefore clients should not override it. // not abstract and therefore clients should not override it.
typedef void (*CleanupFunction)(void* arg1, void* arg2); using CleanupFunction = void (*)(void* arg1, void* arg2);
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
private: private:
struct Cleanup { // Cleanup functions are stored in a single-linked list.
// The list's head node is inlined in the iterator.
struct CleanupNode {
// The head node is used if the function pointer is not null.
CleanupFunction function; CleanupFunction function;
void* arg1; void* arg1;
void* arg2; void* arg2;
Cleanup* next; CleanupNode* next;
// True if the node is not used. Only head nodes might be unused.
bool IsEmpty() const { return function == nullptr; }
// Invokes the cleanup function.
void Run() { assert(function != nullptr); (*function)(arg1, arg2); }
}; };
Cleanup cleanup_; CleanupNode cleanup_head_;
}; };
// Return an empty iterator (yields nothing). // Return an empty iterator (yields nothing).

View File

@ -7,54 +7,59 @@
namespace leveldb { namespace leveldb {
Iterator::Iterator() { Iterator::Iterator() {
cleanup_.function = nullptr; cleanup_head_.function = nullptr;
cleanup_.next = nullptr; cleanup_head_.next = nullptr;
} }
Iterator::~Iterator() { Iterator::~Iterator() {
if (cleanup_.function != nullptr) { if (!cleanup_head_.IsEmpty()) {
(*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); cleanup_head_.Run();
for (Cleanup* c = cleanup_.next; c != nullptr; ) { for (CleanupNode* node = cleanup_head_.next; node != nullptr; ) {
(*c->function)(c->arg1, c->arg2); node->Run();
Cleanup* next = c->next; CleanupNode* next_node = node->next;
delete c; delete node;
c = next; node = next_node;
} }
} }
} }
void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) {
assert(func != nullptr); assert(func != nullptr);
Cleanup* c; CleanupNode* node;
if (cleanup_.function == nullptr) { if (cleanup_head_.IsEmpty()) {
c = &cleanup_; node = &cleanup_head_;
} else { } else {
c = new Cleanup; node = new CleanupNode();
c->next = cleanup_.next; node->next = cleanup_head_.next;
cleanup_.next = c; cleanup_head_.next = node;
} }
c->function = func; node->function = func;
c->arg1 = arg1; node->arg1 = arg1;
c->arg2 = arg2; node->arg2 = arg2;
} }
namespace { namespace {
class EmptyIterator : public Iterator { class EmptyIterator : public Iterator {
public: public:
EmptyIterator(const Status& s) : status_(s) { } EmptyIterator(const Status& s) : status_(s) { }
virtual bool Valid() const { return false; } ~EmptyIterator() override = default;
virtual void Seek(const Slice& target) { }
virtual void SeekToFirst() { } bool Valid() const override { return false; }
virtual void SeekToLast() { } void Seek(const Slice& target) override { }
virtual void Next() { assert(false); } void SeekToFirst() override { }
virtual void Prev() { assert(false); } void SeekToLast() override { }
Slice key() const { assert(false); return Slice(); } void Next() override { assert(false); }
Slice value() const { assert(false); return Slice(); } void Prev() override { assert(false); }
virtual Status status() const { return status_; } Slice key() const override { assert(false); return Slice(); }
Slice value() const override { assert(false); return Slice(); }
Status status() const override { return status_; }
private: private:
Status status_; Status status_;
}; };
} // namespace
} // anonymous namespace
Iterator* NewEmptyIterator() { Iterator* NewEmptyIterator() {
return new EmptyIterator(Status::OK()); return new EmptyIterator(Status::OK());