simplify insertion methods for SkTLList

Review URL: https://codereview.chromium.org/1459663002
This commit is contained in:
bsalomon 2015-11-18 14:11:08 -08:00 committed by Commit bot
parent f9b1577d76
commit 5aaef1ff1a
4 changed files with 26 additions and 103 deletions

View File

@ -10,6 +10,7 @@
#include "SkTInternalLList.h"
#include "SkTypes.h"
#include <utility>
template <typename T> class SkTLList;
template <typename T>
@ -66,52 +67,42 @@ public:
}
}
T* addToHead(const T& t) {
/** Adds a new element to the list at the head. */
template <typename... Args> T* addToHead(Args&&... args) {
this->validate();
Node* node = this->createNode();
fList.addToHead(node);
new (node->fObj) T(t);
this->validate();
return reinterpret_cast<T*>(node->fObj);
return new (node->fObj) T(std::forward<Args>(args)...);
}
T* addToHead() {
this->validate();
Node* node = this->createNode();
fList.addToHead(node);
new (node->fObj) T;
this->validate();
return reinterpret_cast<T*>(node->fObj);
}
T* addToTail(const T& t) {
/** Adds a new element to the list at the tail. */
template <typename... Args> T* addToTail(Args&&... args) {
this->validate();
Node* node = this->createNode();
fList.addToTail(node);
new (node->fObj) T(t);
this->validate();
return reinterpret_cast<T*>(node->fObj);
}
T* addToTail() {
this->validate();
Node* node = this->createNode();
fList.addToTail(node);
new (node->fObj) T;
this->validate();
return reinterpret_cast<T*>(node->fObj);
return new (node->fObj) T(std::forward<Args>(args)...);
}
/** Adds a new element to the list before the location indicated by the iterator. If the
iterator refers to a nullptr location then the new element is added at the tail */
T* addBefore(const T& t, const Iter& location) {
return new (this->internalAddBefore(location)) T(t);
template <typename... Args> T* addBefore(Iter location, Args&&... args) {
this->validate();
Node* node = this->createNode();
fList.addBefore(node, location.getNode());
this->validate();
return new (node->fObj) T(std::forward<Args>(args)...);
}
/** Adds a new element to the list after the location indicated by the iterator. If the
iterator refers to a nullptr location then the new element is added at the head */
T* addAfter(const T& t, const Iter& location) {
return new (this->internalAddAfter(location)) T(t);
template <typename... Args> T* addAfter(Iter location, Args&&... args) {
this->validate();
Node* node = this->createNode();
fList.addAfter(node, location.getNode());
this->validate();
return new (node->fObj) T(std::forward<Args>(args)...);
}
/** Convenience methods for getting an iterator initialized to the head/tail of the list. */
@ -227,12 +218,6 @@ public:
}
};
// For use with operator new
enum Placement {
kBefore_Placement,
kAfter_Placement,
};
private:
struct Block {
int fNodesInUse;
@ -333,30 +318,6 @@ private:
#endif
}
// Support in-place initializing of objects inserted into the list via operator new.
friend void* operator new<T>(size_t,
SkTLList* list,
Placement placement,
const Iter& location);
// Helpers that insert the node and returns a pointer to where the new object should be init'ed.
void* internalAddBefore(Iter location) {
this->validate();
Node* node = this->createNode();
fList.addBefore(node, location.getNode());
this->validate();
return node->fObj;
}
void* internalAddAfter(Iter location) {
this->validate();
Node* node = this->createNode();
fList.addAfter(node, location.getNode());
this->validate();
return node->fObj;
}
NodeList fList;
NodeList fFreeList;
int fCount;
@ -364,40 +325,4 @@ private:
};
// Use the below macros rather than calling this directly
template <typename T>
void *operator new(size_t, SkTLList<T>* list,
typename SkTLList<T>::Placement placement,
const typename SkTLList<T>::Iter& location) {
SkASSERT(list);
if (SkTLList<T>::kBefore_Placement == placement) {
return list->internalAddBefore(location);
} else {
return list->internalAddAfter(location);
}
}
// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
// to match the op new silences warnings about missing op delete when a constructor throws an
// exception.
template <typename T>
void operator delete(void*,
SkTLList<T>*,
typename SkTLList<T>::Placement,
const typename SkTLList<T>::Iter&) {
SK_CRASH();
}
#define SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) \
(new ((list), SkTLList< type_name >::kBefore_Placement, (location)) type_name args)
#define SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) \
(new ((list), SkTLList< type_name >::kAfter_Placement, (location)) type_name args)
#define SkNEW_INSERT_AT_LLIST_HEAD(list, type_name, args) \
SkNEW_INSERT_IN_LLIST_BEFORE((list), (list)->headIter(), type_name, args)
#define SkNEW_INSERT_AT_LLIST_TAIL(list, type_name, args) \
SkNEW_INSERT_IN_LLIST_AFTER((list), (list)->tailIter(), type_name, args)
#endif

View File

@ -206,9 +206,7 @@ static void reduced_stack_walker(const SkClipStack& stack,
if (isFlip) {
SkASSERT(SkRegion::kXOR_Op == element->getOp() ||
SkRegion::kReverseDifference_Op == element->getOp());
SkNEW_INSERT_AT_LLIST_HEAD(result,
Element,
(queryBounds, SkRegion::kReverseDifference_Op, false));
result->addToHead(queryBounds, SkRegion::kReverseDifference_Op, false);
} else {
Element* newElement = result->addToHead(*element);
if (newElement->isAA()) {
@ -386,7 +384,7 @@ void GrReducedClip::ReduceClipStack(const SkClipStack& stack,
// iior should only be true if aa/non-aa status matches among all elements.
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
bool doAA = iter.prev()->isAA();
SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
result->addToHead(isectRect, SkRegion::kReplace_Op, doAA);
if (requiresAA) {
*requiresAA = doAA;
}

View File

@ -207,7 +207,7 @@ void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob,
SkPaint runPaint(skPaint);
for (SkTextBlobRunIterator iter(skBlob); !iter.done(); iter.next()) {
iter.applyFontToPaint(&runPaint); // No need to re-seed the paint.
TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint));
TextRun* run = this->addToTail(runPaint);
const char* text = reinterpret_cast<const char*>(iter.glyphs());
size_t byteLength = sizeof(uint16_t) * iter.glyphCount();

View File

@ -152,11 +152,11 @@ static void TestTLList(skiatest::Reporter* reporter) {
list2.reset();
// use both before/after in-place construction on an empty list
SkNEW_INSERT_IN_LLIST_BEFORE(&list2, list2.headIter(), ListElement, (1));
list2.addBefore(list2.headIter(), 1);
REPORTER_ASSERT(reporter, list2 == list1);
list2.reset();
SkNEW_INSERT_IN_LLIST_AFTER(&list2, list2.tailIter(), ListElement, (1));
list2.addAfter(list2.tailIter(), 1);
REPORTER_ASSERT(reporter, list2 == list1);
// add an element to the second list, check that iters are still valid
@ -210,7 +210,7 @@ static void TestTLList(skiatest::Reporter* reporter) {
// insert either before or after the iterator, then check that the
// surrounding sequence is correct.
if (2 == insertionMethod) {
SkNEW_INSERT_IN_LLIST_BEFORE(&list1, iter, ListElement, (id));
list1.addBefore(iter, id);
Iter newItem(iter);
newItem.prev();
REPORTER_ASSERT(reporter, newItem.get()->fID == id);
@ -222,7 +222,7 @@ static void TestTLList(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, prev.next()->fID == id);
}
} else {
SkNEW_INSERT_IN_LLIST_AFTER(&list1, iter, ListElement, (id));
list1.addAfter(iter, id);
Iter newItem(iter);
newItem.next();
REPORTER_ASSERT(reporter, newItem.get()->fID == id);