summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/test_cpp.cc20
-rw-r--r--tests/test_def.c18
-rw-r--r--upb/handlers-inl.h66
-rw-r--r--upb/refcounted.c9
-rw-r--r--upb/refcounted.h6
5 files changed, 108 insertions, 11 deletions
diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc
index 370c7b0..7ca5a0d 100644
--- a/tests/test_cpp.cc
+++ b/tests/test_cpp.cc
@@ -433,6 +433,25 @@ class StringBufTesterSizeTMethodNoHandlerDataNoHandle
}
};
+class StringBufTesterBoolMethodNoHandlerDataNoHandle
+ : public StringBufTesterBase {
+ public:
+ typedef StringBufTesterBoolMethodNoHandlerDataNoHandle ME;
+ void Register(upb::Handlers* h, const upb::FieldDef* f) {
+ UPB_UNUSED(f);
+ ASSERT(h->SetStringHandler(f, UpbMakeHandler(&ME::Handler)));
+ handler_data_val_ = kExpectedHandlerData;
+ }
+
+ private:
+ bool Handler(const char *buf, size_t len) {
+ ASSERT(buf == &buf_);
+ seen_ = true;
+ len_ = len;
+ return true;
+ }
+};
+
class StartMsgTesterBase {
public:
// We don't need the FieldDef it will create, but the test harness still
@@ -1124,6 +1143,7 @@ int run_tests(int argc, char *argv[]) {
TestHandler<StringBufTesterVoidFunctionWithHandlerDataNoHandle>();
TestHandler<StringBufTesterVoidFunctionWithHandlerDataWithHandle>();
TestHandler<StringBufTesterSizeTMethodNoHandlerDataNoHandle>();
+ TestHandler<StringBufTesterBoolMethodNoHandlerDataNoHandle>();
TestMismatchedTypes();
diff --git a/tests/test_def.c b/tests/test_def.c
index 7efd2b0..92b461f 100644
--- a/tests/test_def.c
+++ b/tests/test_def.c
@@ -25,6 +25,23 @@ static void test_empty_symtab() {
upb_symtab_unref(s, &s);
}
+static void test_noreftracking() {
+ // Reftracking is not required; clients can pass UPB_UNTRACKED_REF for owner.
+ upb_msgdef *md = upb_msgdef_new(UPB_UNTRACKED_REF);
+ upb_msgdef_ref(md, UPB_UNTRACKED_REF);
+
+ // Clients can mix tracked and untracked refs.
+ upb_msgdef_ref(md, &md);
+
+ upb_msgdef_unref(md, UPB_UNTRACKED_REF);
+ upb_msgdef_unref(md, UPB_UNTRACKED_REF);
+
+ // Call some random function on the messagedef to test that it is alive.
+ ASSERT(!upb_msgdef_isfrozen(md));
+
+ upb_msgdef_unref(md, &md);
+}
+
static upb_symtab *load_test_proto(void *owner) {
upb_symtab *s = upb_symtab_new(owner);
ASSERT(s);
@@ -271,5 +288,6 @@ int run_tests(int argc, char *argv[]) {
test_replacement();
test_freeze_free();
test_partial_freeze();
+ test_noreftracking();
return 0;
}
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);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback