Skip to content

Commit de9b0c3

Browse files
rdemellowdaverigby
authored andcommitted
MB-30044: Make TaggedPtr<T> use explicit constructors
Add bool operator==(const TaggedPtr<T>& other) const to TaggedPtr<T>, so that we can compare two TaggedPtr templates. As currently when comparing two, they get cast to a bool() and then compared which is incorrect. Also refactor SingleThreadedRCPtr<T,P,D> to separate the single arg constructor and default constructor which inits value to Pointer's default value. Plus add reset() method that resets SingleThreadedRCPtr<> without taking an argument and sets the value to pointers default value. Refactor BasicLinkedList::purgeListElem() to only take ownership of the item that is to be erased after its been removed from the LinkedList. Change-Id: I8dfd27120bd73b774244fd5e3f6741408e23832b Reviewed-on: http://review.couchbase.org/c/kv_engine/+/132648 Tested-by: Build Bot <[email protected]> Reviewed-by: Dave Rigby <[email protected]>
1 parent e2564a0 commit de9b0c3

15 files changed

+72
-47
lines changed

engines/ep/src/atomic.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ class RCValue {
128128
template <class T, class Pointer = T*, class Deleter = std::default_delete<T>>
129129
class SingleThreadedRCPtr {
130130
public:
131-
explicit SingleThreadedRCPtr(Pointer init = nullptr) : value(init) {
131+
SingleThreadedRCPtr() : value(Pointer()){};
132+
133+
explicit SingleThreadedRCPtr(Pointer init) : value(init) {
132134
if (init != nullptr) {
133135
++value->_rc_refcount;
134136
}
@@ -165,7 +167,11 @@ class SingleThreadedRCPtr {
165167
}
166168
}
167169

168-
void reset(Pointer newValue = nullptr) {
170+
void reset() {
171+
swap(Pointer());
172+
}
173+
174+
void reset(Pointer newValue) {
169175
if (newValue != nullptr) {
170176
++newValue->_rc_refcount;
171177
}

engines/ep/src/dcp/consumer.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ ENGINE_ERROR_CODE DcpConsumer::deletion(uint32_t opaque,
603603
}
604604
} else {
605605
// MB-31141: Deletes cannot have a value
606-
item->replaceValue(Blob::New(0));
606+
item->replaceValue(TaggedPtr<Blob>(Blob::New(0),
607+
TaggedPtrBase::NoTagValue));
607608
item->setDataType(PROTOCOL_BINARY_RAW_BYTES);
608609
}
609610
}

engines/ep/src/item.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ class Item : public RCValue {
559559
} else {
560560
data = Blob::New(dta, nb);
561561
}
562-
replaceValue(data);
562+
replaceValue(TaggedPtr<Blob>(data, TaggedPtrBase::NoTagValue));
563563
}
564564

565565
ItemMetaData metaData;

engines/ep/src/kv_bucket.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,12 +577,14 @@ void KVBucket::runPreExpiryHook(VBucket& vb, Item& it) {
577577
auto result = engine.getServerApi()->document->pre_expiry(info);
578578
if (!result.empty()) {
579579
// A modified value was returned, use it
580-
it.replaceValue(Blob::New(result.data(), result.size()));
580+
it.replaceValue(TaggedPtr<Blob>(Blob::New(result.data(), result.size()),
581+
TaggedPtrBase::NoTagValue));
581582
// The API states only uncompressed xattr values are returned
582583
it.setDataType(PROTOCOL_BINARY_DATATYPE_XATTR);
583584
} else {
584585
// Make the document empty and raw
585-
it.replaceValue(Blob::New(0));
586+
it.replaceValue(
587+
TaggedPtr<Blob>(Blob::New(0), TaggedPtrBase::NoTagValue));
586588
it.setDataType(PROTOCOL_BINARY_RAW_BYTES);
587589
}
588590
}

engines/ep/src/linked_list.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,12 @@ std::ostream& operator <<(std::ostream& os, const BasicLinkedList& ll) {
500500

501501
OrderedLL::iterator BasicLinkedList::purgeListElem(OrderedLL::iterator it,
502502
bool isStale) {
503-
StoredValue::UniquePtr purged(&*it);
503+
std::unique_ptr<OrderedStoredValue> purged;
504+
auto next = it;
504505
{
505506
std::lock_guard<std::mutex> lckGd(getListWriteLock());
506-
it = seqList.erase(it);
507+
next = seqList.erase(it);
508+
purged.reset(&*it);
507509
}
508510

509511
if (isStale) {
@@ -523,7 +525,7 @@ OrderedLL::iterator BasicLinkedList::purgeListElem(OrderedLL::iterator it,
523525
purged->getBySeqno() > highestPurgedDeletedSeqno.load()) {
524526
highestPurgedDeletedSeqno = purged->getBySeqno();
525527
}
526-
return it;
528+
return next;
527529
}
528530

529531
std::unique_ptr<BasicLinkedList::RangeIteratorLL>

engines/ep/src/stored-value.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,8 +575,7 @@ class StoredValue {
575575
void replaceValue(std::unique_ptr<Blob> data) {
576576
// Maintain the tag
577577
auto tag = getValueTag();
578-
value.reset(data.release());
579-
setValueTag(tag);
578+
value.reset({data.release(), tag.raw});
580579
}
581580

582581
/**
@@ -1078,7 +1077,8 @@ class OrderedStoredValue : public StoredValue {
10781077
// point to the updated version of this StoredValue. _BUT_ we do not
10791078
// own the new SV. At destruction, we must release this ptr if
10801079
// we are stale.
1081-
chain_next_or_replacement.reset(newSv);
1080+
chain_next_or_replacement.reset(
1081+
TaggedPtr<StoredValue>(newSv, TaggedPtrBase::NoTagValue));
10821082
setStale(true);
10831083
}
10841084

engines/ep/src/stored_value_factories.cc

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,38 +23,42 @@ StoredValue::UniquePtr StoredValueFactory::operator()(
2323
const Item& itm, StoredValue::UniquePtr next) {
2424
// Allocate a buffer to store the StoredValue and any trailing bytes
2525
// that maybe required.
26-
return StoredValue::UniquePtr(
26+
return StoredValue::UniquePtr(TaggedPtr<StoredValue>(
2727
new (::operator new(StoredValue::getRequiredStorage(itm.getKey())))
2828
StoredValue(itm,
2929
std::move(next),
3030
*stats,
31-
/*isOrdered*/ false));
31+
/*isOrdered*/ false),
32+
TaggedPtrBase::NoTagValue));
3233
}
3334

3435
StoredValue::UniquePtr StoredValueFactory::copyStoredValue(
3536
const StoredValue& other, StoredValue::UniquePtr next) {
3637
// Allocate a buffer to store the copy of StoredValue and any
3738
// trailing bytes required for the key.
38-
return StoredValue::UniquePtr(
39+
return StoredValue::UniquePtr(TaggedPtr<StoredValue>(
3940
new (::operator new(other.getObjectSize()))
40-
StoredValue(other, std::move(next), *stats));
41+
StoredValue(other, std::move(next), *stats),
42+
TaggedPtrBase::NoTagValue));
4143
}
4244

4345
StoredValue::UniquePtr OrderedStoredValueFactory::operator()(
4446
const Item& itm, StoredValue::UniquePtr next) {
4547
// Allocate a buffer to store the OrderStoredValue and any trailing
4648
// bytes required for the key.
47-
return StoredValue::UniquePtr(
49+
return StoredValue::UniquePtr(TaggedPtr<StoredValue>(
4850
new (::operator new(
4951
OrderedStoredValue::getRequiredStorage(itm.getKey())))
50-
OrderedStoredValue(itm, std::move(next), *stats));
52+
OrderedStoredValue(itm, std::move(next), *stats),
53+
TaggedPtrBase::NoTagValue));
5154
}
5255

5356
StoredValue::UniquePtr OrderedStoredValueFactory::copyStoredValue(
5457
const StoredValue& other, StoredValue::UniquePtr next) {
5558
// Allocate a buffer to store the copy ofOrderStoredValue and any
5659
// trailing bytes required for the key.
57-
return StoredValue::UniquePtr(
60+
return StoredValue::UniquePtr(TaggedPtr<StoredValue>(
5861
new (::operator new(other.getObjectSize()))
59-
OrderedStoredValue(other, std::move(next), *stats));
62+
OrderedStoredValue(other, std::move(next), *stats),
63+
TaggedPtrBase::NoTagValue));
6064
}

engines/ep/src/tagged_ptr.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121

2222
#if (defined(__x86_64__) || defined(_M_X64) || defined(__s390x__))
2323

24+
class TaggedPtrBase {
25+
public:
26+
static const uint16_t NoTagValue = 0;
27+
};
28+
2429
/*
2530
* This class provides a tagged pointer, which means it is a pointer however
2631
* the top 16 bits (the tag) can be used to hold user data. This works
@@ -36,16 +41,12 @@
3641
*/
3742

3843
template <typename T>
39-
class TaggedPtr {
44+
class TaggedPtr : public TaggedPtrBase {
4045
public:
4146
using element_type = T;
4247

4348
// Need to define all methods which unique_ptr expects from a pointer type
44-
TaggedPtr() : raw(0) {
45-
}
46-
47-
TaggedPtr(T* obj) : TaggedPtr() {
48-
set(obj);
49+
TaggedPtr() : raw(NoTagValue) {
4950
}
5051

5152
TaggedPtr(T* obj, uint16_t tag) : TaggedPtr() {
@@ -61,7 +62,15 @@ class TaggedPtr {
6162
return !operator!=(other);
6263
}
6364

64-
operator bool() const {
65+
bool operator==(const TaggedPtr& other) const {
66+
return get() == other.get();
67+
}
68+
69+
bool operator!=(const TaggedPtr& other) const {
70+
return get() != other.get();
71+
}
72+
73+
explicit operator bool() const {
6574
return extractPointer(raw) != 0;
6675
}
6776

engines/ep/src/vbucket.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3881,7 +3881,7 @@ std::unique_ptr<Item> VBucket::pruneXattrDocument(
38813881
rv->setFlags(itemMeta.flags);
38823882
rv->setExpTime(itemMeta.exptime);
38833883
rv->setRevSeqno(itemMeta.revSeqno);
3884-
rv->replaceValue(newValue);
3884+
rv->replaceValue(TaggedPtr<Blob>(newValue, TaggedPtrBase::NoTagValue));
38853885
rv->setDataType(PROTOCOL_BINARY_DATATYPE_XATTR);
38863886
return rv;
38873887
} else {

engines/ep/src/vbucket_state.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ bool vbucket_transition_state::needsToBePersisted(
2828
void vbucket_transition_state::toItem(Item& item) const {
2929
nlohmann::json json = *this;
3030
std::string jsonState = json.dump();
31-
item.replaceValue(Blob::New(jsonState.data(), jsonState.size()));
31+
item.replaceValue(
32+
TaggedPtr<Blob>(Blob::New(jsonState.data(), jsonState.size()),
33+
TaggedPtrBase::NoTagValue));
3234
}
3335

3436
void vbucket_transition_state::fromItem(const Item& item) {

0 commit comments

Comments
 (0)