Added UPB_UNTRACKED_REF and some more handler overload options.

pull/13171/head
Josh Haberman 10 years ago
parent d493500abc
commit 43f2455cbd
  1. 20
      tests/test_cpp.cc
  2. 18
      tests/test_def.c
  3. 66
      upb/handlers-inl.h
  4. 9
      upb/refcounted.c
  5. 6
      upb/refcounted.h

@ -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();

@ -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;
}

@ -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

@ -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);

@ -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);

Loading…
Cancel
Save