diff options
Diffstat (limited to 'upb')
-rw-r--r-- | upb/handlers-inl.h | 66 | ||||
-rw-r--r-- | upb/refcounted.c | 9 | ||||
-rw-r--r-- | upb/refcounted.h | 6 |
3 files changed, 70 insertions, 11 deletions
diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h index b4ba4a3..14ecb41 100644 --- a/upb/handlers-inl.h +++ b/upb/handlers-inl.h @@ -586,6 +586,17 @@ void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); } +// Function wrapper that munges the return value from bool to void*. +template <class P1, class P2, bool F(P1, P2)> +void *ReturnClosureOrBreak2(P1 p1, P2 p2) { + return F(p1, p2) ? p1 : UPB_BREAK; +} + +template <class P1, class P2, class P3, bool F(P1, P2, P3)> +void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) { + return F(p1, p2, p3) ? p1 : UPB_BREAK; +} + // For the string callback, which takes five params, returns the size param. template <class P1, class P2, void F(P1, P2, const char *, size_t, const BufferHandle *)> @@ -595,6 +606,15 @@ size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, return p4; } +// For the string callback, which takes five params, returns the size param or +// zero. +template <class P1, class P2, + bool F(P1, P2, const char *, size_t, const BufferHandle *)> +size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4, + const BufferHandle *p5) { + return F(p1, p2, p3, p4, p5) ? p4 : 0; +} + // If we have a function returning void but want a function returning bool, wrap // it in a function that returns true. template <class P1, class P2, void F(P1, P2), class I> @@ -619,17 +639,6 @@ struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> { typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func; }; -// If our function returns void but we want one returning size_t, wrap it in a -// function that returns the size argument. -template <class P1, class P2, - void F(P1, P2, const char *, size_t, const BufferHandle *), class I> -struct MaybeWrapReturn< - Func5<void, P1, P2, const char *, size_t, const BufferHandle *, F, I>, - size_t> { - typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *, - ReturnStringLen<P1, P2, F>, I> Func; -}; - // If our function returns R* but we want one returning void*, wrap it in a // function that casts to void*. template <class R, class P1, class P2, R *F(P1, P2), class I> @@ -645,6 +654,41 @@ struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *, Func; }; +// If our function returns bool but we want one returning void*, wrap it in a +// function that returns either the first param or UPB_BREAK. +template <class P1, class P2, bool F(P1, P2), class I> +struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> { + typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func; +}; + +template <class P1, class P2, class P3, bool F(P1, P2, P3), class I> +struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> { + typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I> + Func; +}; + +// If our function returns void but we want one returning size_t, wrap it in a +// function that returns the size argument. +template <class P1, class P2, + void F(P1, P2, const char *, size_t, const BufferHandle *), class I> +struct MaybeWrapReturn< + Func5<void, P1, P2, const char *, size_t, const BufferHandle *, F, I>, + size_t> { + typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *, + ReturnStringLen<P1, P2, F>, I> Func; +}; + +// If our function returns bool but we want one returning size_t, wrap it in a +// function that returns either 0 or the buf size. +template <class P1, class P2, + bool F(P1, P2, const char *, size_t, const BufferHandle *), class I> +struct MaybeWrapReturn< + Func5<bool, P1, P2, const char *, size_t, const BufferHandle *, F, I>, + size_t> { + typedef Func5<size_t, P1, P2, const char *, size_t, const BufferHandle *, + ReturnNOr0<P1, P2, F>, I> Func; +}; + // ConvertParams /////////////////////////////////////////////////////////////// // Template class that converts the function parameters if necessary, and diff --git a/upb/refcounted.c b/upb/refcounted.c index 4e01081..cba535f 100644 --- a/upb/refcounted.c +++ b/upb/refcounted.c @@ -25,6 +25,9 @@ static void freeobj(upb_refcounted *o); +const char untracked_val; +const void *UPB_UNTRACKED_REF = &untracked_val; + /* arch-specific atomic primitives *******************************************/ #ifdef UPB_THREAD_UNSAFE ////////////////////////////////////////////////////// @@ -111,6 +114,9 @@ static trackedref *trackedref_new(bool is_ref2) { } static void track(const upb_refcounted *r, const void *owner, bool ref2) { + assert(owner); + if (owner == UPB_UNTRACKED_REF) return; + upb_lock(); upb_value v; if (upb_inttable_lookupptr(r->refs, owner, &v)) { @@ -140,6 +146,9 @@ static void track(const upb_refcounted *r, const void *owner, bool ref2) { } static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { + assert(owner); + if (owner == UPB_UNTRACKED_REF) return; + upb_lock(); upb_value v; bool found = upb_inttable_lookupptr(r->refs, owner, &v); diff --git a/upb/refcounted.h b/upb/refcounted.h index ab56e4d..42251b1 100644 --- a/upb/refcounted.h +++ b/upb/refcounted.h @@ -89,6 +89,12 @@ UPB_DEFINE_STRUCT0(upb_refcounted, 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); |