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:
parent
6a6bdafcf1
commit
6caf73ad9d
@ -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).
|
||||||
|
@ -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());
|
||||||
|
Loading…
Reference in New Issue
Block a user