Commit bbd6fb43 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

No mutable flags in IOBuf

Summary: [Folly] No mutable flags in IOBuf to avoid races when invoking `const`-qualified members concurrently.

Reviewed By: simpkins

Differential Revision: D17251909

fbshipit-source-id: e52d333fb620d05f7229a11db9c2f14fe9f6f028
parent b1233937
......@@ -591,7 +591,6 @@ IOBuf IOBuf::cloneAsValue() const {
IOBuf IOBuf::cloneOneAsValue() const {
if (SharedInfo* info = sharedInfo()) {
setFlags(kFlagMaybeShared);
info->refcount.fetch_add(1, std::memory_order_acq_rel);
}
return IOBuf(
......@@ -657,7 +656,7 @@ void IOBuf::unshareOneSlow() {
// Release our reference on the old buffer
decrementRefcount();
// Make sure kFlagMaybeShared and kFlagFreeSharedInfo are all cleared.
// Make sure flags are all cleared.
setFlagsAndSharedInfo(0, sharedInfo);
// Update the buffer pointers to point to the new buffer
......@@ -790,7 +789,7 @@ void IOBuf::coalesceAndReallocate(
// Point at the new buffer
decrementRefcount();
// Make sure kFlagMaybeShared and kFlagFreeSharedInfo are all cleared.
// Make sure flags are all cleared.
setFlagsAndSharedInfo(0, newInfo);
capacity_ = actualCapacity;
......@@ -1176,15 +1175,7 @@ uint32_t IOBuf::approximateShareCountOne() const {
if (UNLIKELY(!sharedInfo())) {
return 1U;
}
if (LIKELY(!(flags() & kFlagMaybeShared))) {
return 1U;
}
auto shareCount = sharedInfo()->refcount.load(std::memory_order_acquire);
if (shareCount < 2) {
// we're the last one left
clearFlags(kFlagMaybeShared);
}
return shareCount;
return sharedInfo()->refcount.load(std::memory_order_acquire);
}
size_t IOBufHash::operator()(const IOBuf& buf) const noexcept {
......
......@@ -1020,19 +1020,7 @@ class IOBuf {
return true;
}
if (LIKELY(!(flags() & kFlagMaybeShared))) {
return false;
}
// kFlagMaybeShared is set, so we need to check the reference count.
// (Checking the reference count requires an atomic operation, which is why
// we prefer to only check kFlagMaybeShared if possible.)
bool shared = sharedInfo()->refcount.load(std::memory_order_acquire) > 1;
if (!shared) {
// we're the last one left
clearFlags(kFlagMaybeShared);
}
return shared;
return sharedInfo()->refcount.load(std::memory_order_acquire) > 1;
}
/**
......@@ -1409,8 +1397,7 @@ class IOBuf {
// as these flags are stashed in the least significant 2 bits of a
// max-align-aligned pointer.
kFlagFreeSharedInfo = 0x1,
kFlagMaybeShared = 0x2,
kFlagMask = kFlagFreeSharedInfo | kFlagMaybeShared
kFlagMask = (1 << 2 /* least significant bits */) - 1,
};
struct SharedInfoObserverEntryBase {
......@@ -1541,7 +1528,7 @@ class IOBuf {
std::size_t capacity_{0};
// Pack flags in least significant 2 bits, sharedInfo in the rest
mutable uintptr_t flagsAndSharedInfo_{0};
uintptr_t flagsAndSharedInfo_{0};
static inline uintptr_t packFlagsAndSharedInfo(
uintptr_t flags,
......@@ -1567,12 +1554,12 @@ class IOBuf {
}
// flags_ are changed from const methods
inline void setFlags(uintptr_t flags) const noexcept {
inline void setFlags(uintptr_t flags) noexcept {
DCHECK_EQ(flags & ~kFlagMask, 0u);
flagsAndSharedInfo_ |= flags;
}
inline void clearFlags(uintptr_t flags) const noexcept {
inline void clearFlags(uintptr_t flags) noexcept {
DCHECK_EQ(flags & ~kFlagMask, 0u);
flagsAndSharedInfo_ &= ~flags;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment