Make reference counting thread safe
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
146f215614
commit
3eaf8dea2a
2 changed files with 43 additions and 20 deletions
|
@ -7,42 +7,37 @@ Author: Leonardo de Moura
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "name.h"
|
#include "name.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "rc.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
|
||||||
constexpr char const * anonymous_str = "[anonymous]";
|
constexpr char const * anonymous_str = "[anonymous]";
|
||||||
|
|
||||||
struct name::imp {
|
struct name::imp {
|
||||||
|
MK_LEAN_RC()
|
||||||
bool m_is_string;
|
bool m_is_string;
|
||||||
unsigned m_rc;
|
|
||||||
imp * m_prefix;
|
imp * m_prefix;
|
||||||
union {
|
union {
|
||||||
char * m_str;
|
char * m_str;
|
||||||
unsigned m_k;
|
unsigned m_k;
|
||||||
};
|
};
|
||||||
|
|
||||||
void inc_ref() { m_rc++; }
|
void dealloc() {
|
||||||
|
|
||||||
void dec_ref() {
|
|
||||||
imp * curr = this;
|
imp * curr = this;
|
||||||
while (curr) {
|
while (true) {
|
||||||
lean_assert(curr->m_rc > 0);
|
lean_assert(curr->get_rc() == 0);
|
||||||
curr->m_rc--;
|
|
||||||
if (curr->m_rc == 0) {
|
|
||||||
imp * p = curr->m_prefix;
|
imp * p = curr->m_prefix;
|
||||||
if (curr->m_is_string)
|
if (curr->m_is_string)
|
||||||
delete[] reinterpret_cast<char*>(curr);
|
delete[] reinterpret_cast<char*>(curr);
|
||||||
else
|
else
|
||||||
delete curr;
|
delete curr;
|
||||||
curr = p;
|
curr = p;
|
||||||
}
|
if (!curr || !curr->dec_ref_core())
|
||||||
else {
|
break;
|
||||||
curr = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imp(bool s, imp * p):m_is_string(s), m_rc(1), m_prefix(p) { if (p) p->inc_ref(); }
|
imp(bool s, imp * p):m_rc(1), m_is_string(s), m_prefix(p) { if (p) p->inc_ref(); }
|
||||||
|
|
||||||
static void display_core(std::ostream & out, char const * sep, imp * p) {
|
static void display_core(std::ostream & out, char const * sep, imp * p) {
|
||||||
lean_assert(p != nullptr);
|
lean_assert(p != nullptr);
|
||||||
|
|
28
src/util/rc.h
Normal file
28
src/util/rc.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||||
|
Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
|
Author: Leonardo de Moura
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Goodies for reference counting
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#ifdef LEAN_THREAD_UNSAFE_REF_COUNT
|
||||||
|
#define MK_LEAN_RC() \
|
||||||
|
unsigned m_rc; \
|
||||||
|
unsigned get_rc() const { return m_rc; } \
|
||||||
|
void inc_ref() { m_rc++; } \
|
||||||
|
bool dec_ref_core() { lean_assert(get_rc() > 0); m_rc--; return m_rc == 0; } \
|
||||||
|
void dec_ref() { if (dec_ref_core()) dealloc(); }
|
||||||
|
#else
|
||||||
|
#include <atomic>
|
||||||
|
#define MK_LEAN_RC() \
|
||||||
|
std::atomic<unsigned> m_rc; \
|
||||||
|
unsigned get_rc() const { return std::atomic_load(&m_rc); } \
|
||||||
|
void inc_ref() { std::atomic_fetch_add_explicit(&m_rc, 1u, std::memory_order_relaxed); } \
|
||||||
|
bool dec_ref_core() { lean_assert(get_rc() > 0); return std::atomic_fetch_sub_explicit(&m_rc, 1u, std::memory_order_relaxed) == 1u; } \
|
||||||
|
void dec_ref() { if (dec_ref_core()) dealloc(); }
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue