Skip to content

Commit cf44b96

Browse files
authored
fix: correct reference counting for Slice (#3998)
1 parent e6796f0 commit cf44b96

File tree

2 files changed

+32
-26
lines changed

2 files changed

+32
-26
lines changed

hybridse/include/base/fe_slice.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <string.h>
2424

2525
#include <string>
26+
#include <utility>
2627

2728
#include "base/raw_buffer.h"
2829

@@ -100,6 +101,12 @@ class Slice {
100101
return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
101102
}
102103

104+
protected:
105+
void _swap(Slice &slice) {
106+
std::swap(data_, slice.data_);
107+
std::swap(size_, slice.size_);
108+
}
109+
103110
private:
104111
uint32_t size_;
105112
const char *data_;
@@ -154,16 +161,17 @@ class RefCountedSlice : public Slice {
154161
private:
155162
RefCountedSlice(int8_t *data, size_t size, bool managed)
156163
: Slice(reinterpret_cast<const char *>(data), size),
157-
ref_cnt_(managed ? new int(1) : nullptr) {}
164+
ref_cnt_(managed ? new std::atomic<int32_t>(1) : nullptr) {}
158165

159166
RefCountedSlice(const char *data, size_t size, bool managed)
160-
: Slice(data, size), ref_cnt_(managed ? new int(1) : nullptr) {}
167+
: Slice(data, size), ref_cnt_(managed ? new std::atomic<int32_t>(1) : nullptr) {}
161168

162-
void Release();
169+
void _release();
163170

164-
void Update(const RefCountedSlice &slice);
171+
void _copy(const RefCountedSlice &slice);
172+
void _swap(RefCountedSlice &slice);
165173

166-
int32_t *ref_cnt_;
174+
std::atomic<int32_t> *ref_cnt_;
167175
};
168176

169177
} // namespace base

hybridse/src/base/fe_slice.cc

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,56 +15,54 @@
1515
*/
1616

1717
#include "base/fe_slice.h"
18+
#include <atomic>
1819

1920
namespace hybridse {
2021
namespace base {
2122

22-
RefCountedSlice::~RefCountedSlice() { Release(); }
23+
RefCountedSlice::~RefCountedSlice() { _release(); }
2324

24-
void RefCountedSlice::Release() {
25+
void RefCountedSlice::_release() {
2526
if (this->ref_cnt_ != nullptr) {
26-
auto& cnt = *this->ref_cnt_;
27-
cnt -= 1;
28-
if (cnt == 0 && buf() != nullptr) {
29-
// memset in case the buf is still used after free
30-
memset(buf(), 0, size());
27+
if (std::atomic_fetch_add_explicit(ref_cnt_, -1, std::memory_order_release) == 1) {
28+
std::atomic_thread_fence(std::memory_order_acquire);
29+
assert(buf());
3130
free(buf());
3231
delete this->ref_cnt_;
3332
}
3433
}
3534
}
3635

37-
void RefCountedSlice::Update(const RefCountedSlice& slice) {
36+
void RefCountedSlice::_copy(const RefCountedSlice& slice) {
3837
reset(slice.data(), slice.size());
39-
this->ref_cnt_ = slice.ref_cnt_;
38+
ref_cnt_ = slice.ref_cnt_;
4039
if (this->ref_cnt_ != nullptr) {
41-
(*this->ref_cnt_) += 1;
40+
std::atomic_fetch_add_explicit(ref_cnt_, 1, std::memory_order_relaxed);
4241
}
4342
}
4443

45-
RefCountedSlice::RefCountedSlice(const RefCountedSlice& slice) {
46-
this->Update(slice);
44+
void RefCountedSlice::_swap(RefCountedSlice& slice) {
45+
std::swap(ref_cnt_, slice.ref_cnt_);
46+
Slice::_swap(slice);
4747
}
4848

49-
RefCountedSlice::RefCountedSlice(RefCountedSlice&& slice) {
50-
this->Update(slice);
49+
RefCountedSlice::RefCountedSlice(const RefCountedSlice& slice) {
50+
_copy(slice);
5151
}
5252

53+
RefCountedSlice::RefCountedSlice(RefCountedSlice&& slice) { _swap(slice); }
54+
5355
RefCountedSlice& RefCountedSlice::operator=(const RefCountedSlice& slice) {
5456
if (&slice == this) {
5557
return *this;
5658
}
57-
this->Release();
58-
this->Update(slice);
59+
_release();
60+
_copy(slice);
5961
return *this;
6062
}
6163

6264
RefCountedSlice& RefCountedSlice::operator=(RefCountedSlice&& slice) {
63-
if (&slice == this) {
64-
return *this;
65-
}
66-
this->Release();
67-
this->Update(slice);
65+
_swap(slice);
6866
return *this;
6967
}
7068

0 commit comments

Comments
 (0)