diff --git a/src/Init/Util.lean b/src/Init/Util.lean index 0cdb92fecb..974eed11f2 100644 --- a/src/Init/Util.lean +++ b/src/Init/Util.lean @@ -45,6 +45,13 @@ def dbgSleep {α : Type u} (ms : UInt32) (f : Unit → α) : α := f () @[extern "lean_ptr_addr"] unsafe opaque ptrAddrUnsafe {α : Type u} (a : @& α) : USize +/-- +Returns `true` if `a` is an exclusive object. +We say an object is exclusive if it is single-threaded and its reference counter is 1. +-/ +@[extern "lean_is_exclusive_obj"] +unsafe opaque isExclusiveUnsafe {α : Type u} (a : @& α) : Bool + set_option linter.unusedVariables.funArgs false in @[inline] unsafe def withPtrAddrUnsafe {α : Type u} {β : Type v} (a : α) (k : USize → β) (h : ∀ u₁ u₂, k u₁ = k u₂) : β := k (ptrAddrUnsafe a) diff --git a/src/include/lean/lean.h b/src/include/lean/lean.h index c62398f8fa..e2f704a80d 100644 --- a/src/include/lean/lean.h +++ b/src/include/lean/lean.h @@ -481,6 +481,10 @@ static inline bool lean_is_exclusive(lean_object * o) { } } +static inline uint8_t lean_is_exclusive_obj(lean_object * o) { + return lean_is_exclusive(o); +} + static inline bool lean_is_shared(lean_object * o) { if (LEAN_LIKELY(lean_is_st(o))) { return o->m_rc > 1; @@ -1133,6 +1137,17 @@ static inline void * lean_get_external_data(lean_object * o) { return lean_to_external(o)->m_data; } +static inline lean_object * lean_set_external_data(lean_object * o, void * data) { + if (lean_is_exclusive(o)) { + lean_to_external(o)->m_data = data; + return o; + } else { + lean_object * o_new = lean_alloc_external(lean_get_external_class(o), data); + lean_dec_ref(o); + return o_new; + } +} + /* Natural numbers */ #define LEAN_MAX_SMALL_NAT (SIZE_MAX >> 1)