Skip to content

Commit 455718a

Browse files
committed
use atomics on shared_ptr
1 parent 784f6f6 commit 455718a

File tree

2 files changed

+19
-25
lines changed

2 files changed

+19
-25
lines changed

bindings/profilers/wall.cc

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ using namespace v8;
5858

5959
namespace dd {
6060

61+
using ContextPtr = std::shared_ptr<Global<Value>>;
62+
6163
// Maximum number of rounds in the GetV8ToEpochOffset
6264
static constexpr int MAX_EPOCH_OFFSET_ATTEMPTS = 20;
6365

@@ -492,7 +494,6 @@ WallProfiler::WallProfiler(std::chrono::microseconds samplingPeriod,
492494
contexts_.reserve(duration * 2 / samplingPeriod);
493495
}
494496

495-
curContext_.store(&context1_, std::memory_order_relaxed);
496497
collectionMode_.store(CollectionMode::kNoCollect, std::memory_order_relaxed);
497498

498499
auto isolate = v8::Isolate::GetCurrent();
@@ -952,28 +953,26 @@ v8::CpuProfiler* WallProfiler::CreateV8CpuProfiler() {
952953
}
953954

954955
v8::Local<v8::Value> WallProfiler::GetContext(Isolate* isolate) {
955-
auto context = *curContext_.load(std::memory_order_relaxed);
956+
auto context = GetContextPtr();
956957
if (!context) return v8::Undefined(isolate);
957958
return context->Get(isolate);
958959
}
959960

960961
void WallProfiler::SetContext(Isolate* isolate, Local<Value> value) {
961-
// Need to be careful here, because we might be interrupted by a
962-
// signal handler that will make use of curContext_.
963-
// Update of shared_ptr is not atomic, so instead we use a pointer
964-
// (curContext_) that points on two shared_ptr (context1_ and context2_),
965-
// update the shared_ptr that is not currently in use and then atomically
966-
// update curContext_.
967-
auto newCurContext = curContext_.load(std::memory_order_relaxed) == &context1_
968-
? &context2_
969-
: &context1_;
970-
if (!value->IsNullOrUndefined()) {
971-
*newCurContext = std::make_shared<Global<Value>>(isolate, value);
972-
} else {
973-
newCurContext->reset();
974-
}
975962
std::atomic_signal_fence(std::memory_order_release);
976-
curContext_.store(newCurContext, std::memory_order_relaxed);
963+
std::atomic_store_explicit(
964+
&curContext_,
965+
value->IsNullOrUndefined()
966+
? std::shared_ptr<Global<Value>>()
967+
: std::make_shared<Global<Value>>(isolate, value),
968+
std::memory_order_relaxed);
969+
}
970+
971+
ContextPtr WallProfiler::GetContextPtr() {
972+
auto contextPtr =
973+
atomic_load_explicit(&curContext_, std::memory_order_relaxed);
974+
std::atomic_signal_fence(std::memory_order_acquire);
975+
return contextPtr;
977976
}
978977

979978
NAN_GETTER(WallProfiler::GetContext) {
@@ -1007,10 +1006,8 @@ void WallProfiler::PushContext(int64_t time_from,
10071006
// Be careful this is called in a signal handler context therefore all
10081007
// operations must be async signal safe (in particular no allocations).
10091008
// Our ring buffer avoids allocations.
1010-
auto context = curContext_.load(std::memory_order_relaxed);
1011-
std::atomic_signal_fence(std::memory_order_acquire);
10121009
if (contexts_.size() < contexts_.capacity()) {
1013-
contexts_.push_back({*context, time_from, time_to, cpu_time});
1010+
contexts_.push_back({GetContextPtr(), time_from, time_to, cpu_time});
10141011
std::atomic_fetch_add_explicit(
10151012
reinterpret_cast<std::atomic<uint32_t>*>(&fields_[kSampleCount]),
10161013
1U,

bindings/profilers/wall.hh

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,7 @@ class WallProfiler : public Nan::ObjectWrap {
5151
// avoid heap allocation. Need to figure out the right move/copy semantics in
5252
// and out of the ring buffer.
5353

54-
// We're using a pair of shared pointers and an atomic pointer-to-current as
55-
// a way to ensure signal safety on update.
56-
ContextPtr context1_;
57-
ContextPtr context2_;
58-
std::atomic<ContextPtr*> curContext_;
54+
ContextPtr curContext_;
5955

6056
std::atomic<CollectionMode> collectionMode_;
6157
std::atomic<uint64_t> noCollectCallCount_;
@@ -99,6 +95,7 @@ class WallProfiler : public Nan::ObjectWrap {
9995
int64_t startCpuTime);
10096

10197
bool waitForSignal(uint64_t targetCallCount = 0);
98+
ContextPtr GetContextPtr();
10299

103100
public:
104101
/**

0 commit comments

Comments
 (0)