blob: eb5a0662f8d1bfd5b95112e8800e704828039472 (
plain) (
tree)
|
|
#include "singleton.h"
#include <util/system/spinlock.h>
#include <util/system/thread.h>
#include <util/system/sanitizers.h>
#include <cstring>
namespace {
static inline bool MyAtomicTryLock(TAtomic& a, TAtomicBase v) noexcept {
return AtomicCas(&a, v, 0);
}
static inline bool MyAtomicTryAndTryLock(TAtomic& a, TAtomicBase v) noexcept {
return (AtomicGet(a) == 0) && MyAtomicTryLock(a, v);
}
static inline TAtomicBase MyThreadId() noexcept {
const TAtomicBase ret = TThread::CurrentThreadId();
if (ret) {
return ret;
}
//clash almost impossible, ONLY if we have threads with ids 0 and 1!
return 1;
}
}
void NPrivate::FillWithTrash(void* ptr, size_t len) {
#if defined(NDEBUG)
Y_UNUSED(ptr);
Y_UNUSED(len);
#else
if constexpr (NSan::TSanIsOn()) {
Y_UNUSED(ptr);
Y_UNUSED(len);
} else {
memset(ptr, 0xBA, len);
}
#endif
}
void NPrivate::LockRecursive(TAtomic& lock) noexcept {
const TAtomicBase id = MyThreadId();
Y_VERIFY(AtomicGet(lock) != id, "recursive singleton initialization");
if (!MyAtomicTryLock(lock, id)) {
TSpinWait sw;
do {
sw.Sleep();
} while (!MyAtomicTryAndTryLock(lock, id));
}
}
void NPrivate::UnlockRecursive(TAtomic& lock) noexcept {
Y_VERIFY(AtomicGet(lock) == MyThreadId(), "unlock from another thread?!?!");
AtomicUnlock(&lock);
}
|