From 86bad61b76a260ffc442acffbe58feee67df45e5 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 24 Mar 2012 11:24:16 -0700 Subject: Sync from internal Google development. Many improvements, too many to mention. One significant perf regression warrants investigation: omitfp.parsetoproto2_googlemessage1.upb_jit: 343 -> 252 (-26.53) plain.parsetoproto2_googlemessage1.upb_jit: 334 -> 251 (-24.85) 25% regression for this benchmark is bad, but since I don't think there's any fundamental design issue that caused it I'm going to go ahead with the commit anyway. Can investigate and fix later. Other benchmarks were neutral or showed slight improvement. --- upb/refcount.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 upb/refcount.h (limited to 'upb/refcount.h') diff --git a/upb/refcount.h b/upb/refcount.h new file mode 100644 index 0000000..cb2bda9 --- /dev/null +++ b/upb/refcount.h @@ -0,0 +1,70 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009 Google Inc. See LICENSE for details. + * Author: Josh Haberman + * + * A thread-safe refcount that can optionally track references for debugging + * purposes. It helps avoid circular references by allowing a + * strongly-connected component in the graph to share a refcount. + * + * This interface is internal to upb. + */ + +#ifndef UPB_REFCOUNT_H_ +#define UPB_REFCOUNT_H_ + +#include +#include +#include "upb/table.h" + +#ifndef NDEBUG +#define UPB_DEBUG_REFS +#endif + +typedef struct _upb_refcount { + uint32_t *count; + struct _upb_refcount *next; // Circularly-linked list of this SCC. + uint16_t index; // For SCC algorithm. + uint16_t lowlink; // For SCC algorithm. +#ifdef UPB_DEBUG_REFS + upb_inttable refs; +#endif +} upb_refcount; + +// NON THREAD SAFE operations ////////////////////////////////////////////////// + +// Initializes the refcount with a single ref for the given owner. Returns +// NULL if memory could not be allocated. +bool upb_refcount_init(upb_refcount *r, void *owner); + +// Uninitializes the refcount. May only be called after unref() returns true. +void upb_refcount_uninit(upb_refcount *r); + +// Moves an existing ref from ref_donor to new_owner, without changing the +// overall ref count. +void upb_refcount_donateref(upb_refcount *r, void *from, void *to); + +// Finds strongly-connected components among some set of objects and merges all +// refcounts that share a SCC. The given function will be called when the +// algorithm needs to visit children of a particular object; the function +// should call upb_refcount_visit() once for each child obj. +// +// Returns false if memory allocation failed. +typedef void upb_getsuccessors(upb_refcount *obj, void*); +bool upb_refcount_findscc(upb_refcount **objs, int n, upb_getsuccessors *func); +void upb_refcount_visit(upb_refcount *obj, upb_refcount *subobj, void *closure); + +// Thread-safe operations ////////////////////////////////////////////////////// + +// Increases the ref count, the new ref is owned by "owner" which must not +// already own a ref. Circular reference chains are not allowed. +void upb_refcount_ref(upb_refcount *r, void *owner); + +// Release a ref owned by owner, returns true if that was the last ref. +bool upb_refcount_unref(upb_refcount *r, void *owner); + +// Returns true if these two objects share a refcount. +bool upb_refcount_merged(const upb_refcount *r, const upb_refcount *r2); + +#endif // UPB_REFCOUNT_H_ -- cgit v1.2.3