From 0553eff64a87eceff0de3b6260b4f2d45b61703a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 9 Jan 2019 22:40:50 -0800 Subject: upb_refcounted is gone! Some tests still to fix. --- upb/refcounted.h | 348 ------------------------------------------------------- 1 file changed, 348 deletions(-) delete mode 100644 upb/refcounted.h (limited to 'upb/refcounted.h') diff --git a/upb/refcounted.h b/upb/refcounted.h deleted file mode 100644 index 6698d38..0000000 --- a/upb/refcounted.h +++ /dev/null @@ -1,348 +0,0 @@ -/* -** upb::RefCounted (upb_refcounted) -** -** A refcounting scheme that supports circular refs. It accomplishes this by -** partitioning the set of objects into groups such that no cycle spans groups; -** we can then reference-count the group as a whole and ignore refs within the -** group. When objects are mutable, these groups are computed very -** conservatively; we group any objects that have ever had a link between them. -** When objects are frozen, we compute strongly-connected components which -** allows us to be precise and only group objects that are actually cyclic. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_REFCOUNTED_H_ -#define UPB_REFCOUNTED_H_ - -#include "upb/table.int.h" - -/* Reference tracking will check ref()/unref() operations to make sure the - * ref ownership is correct. Where possible it will also make tools like - * Valgrind attribute ref leaks to the code that took the leaked ref, not - * the code that originally created the object. - * - * Enabling this requires the application to define upb_lock()/upb_unlock() - * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE). - * For this reason we don't enable it by default, even in debug builds. - */ - -/* #define UPB_DEBUG_REFS */ - -#ifdef __cplusplus -namespace upb { -class RefCounted; -template class reffed_ptr; -} -#endif - -UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted) - -struct upb_refcounted_vtbl; - -#ifdef __cplusplus - -class upb::RefCounted { - public: - /* Returns true if the given object is frozen. */ - bool IsFrozen() const; - - /* Increases the ref count, the new ref is owned by "owner" which must not - * already own a ref (and should not itself be a refcounted object if the ref - * could possibly be circular; see below). - * Thread-safe iff "this" is frozen. */ - void Ref(const void *owner) const; - - /* Release a ref that was acquired from upb_refcounted_ref() and collects any - * objects it can. */ - void Unref(const void *owner) const; - - /* Moves an existing ref from "from" to "to", without changing the overall - * ref count. DonateRef(foo, NULL, owner) is the same as Ref(foo, owner), - * but "to" may not be NULL. */ - void DonateRef(const void *from, const void *to) const; - - /* Verifies that a ref to the given object is currently held by the given - * owner. Only effective in UPB_DEBUG_REFS builds. */ - void CheckRef(const void *owner) const; - - private: - UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted) -#else -struct upb_refcounted { -#endif - /* TODO(haberman): move the actual structure definition to structdefs.int.h. - * The only reason they are here is because inline functions need to see the - * definition of upb_handlers, which needs to see this definition. But we - * can change the upb_handlers inline functions to deal in raw offsets - * instead. - */ - - /* A single reference count shared by all objects in the group. */ - uint32_t *group; - - /* A singly-linked list of all objects in the group. */ - upb_refcounted *next; - - /* Table of function pointers for this type. */ - const struct upb_refcounted_vtbl *vtbl; - - /* Maintained only when mutable, this tracks the number of refs (but not - * ref2's) to this object. *group should be the sum of all individual_count - * in the group. */ - uint32_t individual_count; - - bool is_frozen; - -#ifdef UPB_DEBUG_REFS - upb_inttable *refs; /* Maps owner -> trackedref for incoming refs. */ - upb_inttable *ref2s; /* Set of targets for outgoing ref2s. */ -#endif -}; - -#ifdef UPB_DEBUG_REFS -extern upb_alloc upb_alloc_debugrefs; -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true, refs, ref2s} -#else -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true} -#endif - -UPB_BEGIN_EXTERN_C - -/* It is better to use tracked refs when possible, for the extra debugging - * capability. But if this is not possible (because you don't have easy access - * to a stable pointer value that is associated with the ref), you can pass - * UPB_UNTRACKED_REF instead. */ -extern const void *UPB_UNTRACKED_REF; - -/* Native C API. */ -bool upb_refcounted_isfrozen(const upb_refcounted *r); -void upb_refcounted_ref(const upb_refcounted *r, const void *owner); -void upb_refcounted_unref(const upb_refcounted *r, const void *owner); -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to); -void upb_refcounted_checkref(const upb_refcounted *r, const void *owner); - -#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \ - UPB_INLINE bool type ## _isfrozen(const type *v) { \ - return upb_refcounted_isfrozen(upcastfunc(v)); \ - } \ - UPB_INLINE void type ## _ref(const type *v, const void *owner) { \ - upb_refcounted_ref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _unref(const type *v, const void *owner) { \ - upb_refcounted_unref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \ - upb_refcounted_donateref(upcastfunc(v), from, to); \ - } \ - UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \ - upb_refcounted_checkref(upcastfunc(v), owner); \ - } - -#define UPB_REFCOUNTED_CPPMETHODS \ - bool IsFrozen() const { \ - return upb::upcast_to(this)->IsFrozen(); \ - } \ - void Ref(const void *owner) const { \ - return upb::upcast_to(this)->Ref(owner); \ - } \ - void Unref(const void *owner) const { \ - return upb::upcast_to(this)->Unref(owner); \ - } \ - void DonateRef(const void *from, const void *to) const { \ - return upb::upcast_to(this)->DonateRef(from, to); \ - } \ - void CheckRef(const void *owner) const { \ - return upb::upcast_to(this)->CheckRef(owner); \ - } - -/* Internal-to-upb Interface **************************************************/ - -typedef void upb_refcounted_visit(const upb_refcounted *r, - const upb_refcounted *subobj, - void *closure); - -struct upb_refcounted_vtbl { - /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2. - * Must be longjmp()-safe. */ - void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c); - - /* Must free the object and release all references to other objects. */ - void (*free)(upb_refcounted *r); -}; - -/* Initializes the refcounted with a single ref for the given owner. Returns - * false if memory could not be allocated. */ -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner); - -/* Adds a ref from one refcounted object to another ("from" must not already - * own a ref). These refs may be circular; cycles will be collected correctly - * (if conservatively). These refs do not need to be freed in from's free() - * function. */ -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from); - -/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any - * object it can. This is only necessary when "from" no longer points to "r", - * and not from from's "free" function. */ -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from); - -#define upb_ref2(r, from) \ - upb_refcounted_ref2((const upb_refcounted*)r, (upb_refcounted*)from) -#define upb_unref2(r, from) \ - upb_refcounted_unref2((const upb_refcounted*)r, (upb_refcounted*)from) - -/* Freezes all mutable object reachable by ref2() refs from the given roots. - * This will split refcounting groups into precise SCC groups, so that - * refcounting of frozen objects can be more aggressive. If memory allocation - * fails, or if more than 2**31 mutable objects are reachable from "roots", or - * if the maximum depth of the graph exceeds "maxdepth", false is returned and - * the objects are unchanged. - * - * After this operation succeeds, the objects are frozen/const, and may not be - * used through non-const pointers. In particular, they may not be passed as - * the second parameter of upb_refcounted_{ref,unref}2(). On the upside, all - * operations on frozen refcounteds are threadsafe, and objects will be freed - * at the precise moment that they become unreachable. - * - * Caller must own refs on each object in the "roots" list. */ -bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth); - -/* Shared by all compiled-in refcounted objects. */ -extern uint32_t static_refcount; - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ Wrappers. */ -namespace upb { -inline bool RefCounted::IsFrozen() const { - return upb_refcounted_isfrozen(this); -} -inline void RefCounted::Ref(const void *owner) const { - upb_refcounted_ref(this, owner); -} -inline void RefCounted::Unref(const void *owner) const { - upb_refcounted_unref(this, owner); -} -inline void RefCounted::DonateRef(const void *from, const void *to) const { - upb_refcounted_donateref(this, from, to); -} -inline void RefCounted::CheckRef(const void *owner) const { - upb_refcounted_checkref(this, owner); -} -} /* namespace upb */ -#endif - - -/* upb::reffed_ptr ************************************************************/ - -#ifdef __cplusplus - -#include /* For std::swap(). */ - -/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a - * ref on whatever object it points to (if any). */ -template class upb::reffed_ptr { - public: - reffed_ptr() : ptr_(NULL) {} - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - reffed_ptr(U* val, const void* ref_donor = NULL) - : ptr_(upb::upcast(val)) { - if (ref_donor) { - UPB_ASSERT(ptr_); - ptr_->DonateRef(ref_donor, this); - } else if (ptr_) { - ptr_->Ref(this); - } - } - - template - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - ~reffed_ptr() { if (ptr_) ptr_->Unref(this); } - - template - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - /* TODO(haberman): add C++11 move construction/assignment for greater - * efficiency. */ - - void swap(reffed_ptr& other) { - if (ptr_ == other.ptr_) { - return; - } - - if (ptr_) ptr_->DonateRef(this, &other); - if (other.ptr_) other.ptr_->DonateRef(&other, this); - std::swap(ptr_, other.ptr_); - } - - T& operator*() const { - UPB_ASSERT(ptr_); - return *ptr_; - } - - T* operator->() const { - UPB_ASSERT(ptr_); - return ptr_; - } - - T* get() const { return ptr_; } - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - void reset(U* ptr = NULL, const void* ref_donor = NULL) { - reffed_ptr(ptr, ref_donor).swap(*this); - } - - template - reffed_ptr down_cast() { - return reffed_ptr(upb::down_cast(get())); - } - - template - reffed_ptr dyn_cast() { - return reffed_ptr(upb::dyn_cast(get())); - } - - /* Plain release() is unsafe; if we were the only owner, it would leak the - * object. Instead we provide this: */ - T* ReleaseTo(const void* new_owner) { - T* ret = NULL; - ptr_->DonateRef(this, new_owner); - std::swap(ret, ptr_); - return ret; - } - - private: - T* ptr_; -}; - -#endif /* __cplusplus */ - -#endif /* UPB_REFCOUNT_H_ */ -- cgit v1.2.3