From 15e24ff7021ecb9646a55d11edef96061e846491 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 29 Aug 2015 01:21:12 +0100 Subject: Move and test lazy pointer --- libadhocutil/lazyPointer.h | 126 +++++++++++++++++++++++++++++ libadhocutil/unittests/Jamfile.jam | 10 +++ libadhocutil/unittests/testLazyPointer.cpp | 77 ++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 libadhocutil/lazyPointer.h create mode 100644 libadhocutil/unittests/testLazyPointer.cpp diff --git a/libadhocutil/lazyPointer.h b/libadhocutil/lazyPointer.h new file mode 100644 index 0000000..23058c7 --- /dev/null +++ b/libadhocutil/lazyPointer.h @@ -0,0 +1,126 @@ +#ifndef LIBADHOC_LAZYPOINTER_H +#define LIBADHOC_LAZYPOINTER_H + +#include +#include +#include + +template > +class LazyPointer { + public: + typedef T element_type; + typedef P pointer_type; + typedef boost::function0

Factory; + typedef boost::variant Source; + + // Constructors + LazyPointer(const Factory & f) : + source(f) + { + } + + LazyPointer(const P & p) : + source(p) + { + } + + LazyPointer(T * p) : + source(P(p)) + { + } + + LazyPointer() : + source(P(NULL)) + { + } + + // Getters + operator P() const + { + return deref(); + } + + T * operator->() const + { + return get(); + } + + T & operator*() const + { + return *get(); + } + + T * get() const + { + return deref().get(); + } + + P deref() const + { + if (Factory * f = boost::get(&source)) { + P p = (*f)(); + source = p; + return p; + } + else { + return boost::get

(source); + } + } + + bool operator!() const + { + return get() == nullptr; + } + + operator bool() const + { + return get() != nullptr; + } + + bool operator==(const P & o) const + { + return (deref() == o); + } + + bool operator==(const T * o) const + { + return (deref().get() == o); + } + + // Setters + LazyPointer & operator=(const P & p) + { + source = p; + return *this; + } + + LazyPointer & operator=(T * t) + { + source = P(t); + return *this; + } + + LazyPointer & operator=(const Factory & f) + { + source = f; + return *this; + } + + bool hasValue() const + { + return boost::get

(&source); + } + + private: + mutable Source source; +}; + +namespace boost { + template + R * dynamic_pointer_cast(const LazyPointer & p) { + return dynamic_cast(p.get()); + } +} + +#endif + diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam index e26825a..4a6b430 100644 --- a/libadhocutil/unittests/Jamfile.jam +++ b/libadhocutil/unittests/Jamfile.jam @@ -86,3 +86,13 @@ run testLocks ; +run + testLazyPointer.cpp + : : : + BOOST_TEST_DYN_LINK + ..//adhocutil + boost_utf + : + testLazyPointer + ; + diff --git a/libadhocutil/unittests/testLazyPointer.cpp b/libadhocutil/unittests/testLazyPointer.cpp new file mode 100644 index 0000000..6c4ddcd --- /dev/null +++ b/libadhocutil/unittests/testLazyPointer.cpp @@ -0,0 +1,77 @@ +#define BOOST_TEST_MODULE LazyPointer +#include + +#include +#include "intrusivePtrBase.h" +#include "lazyPointer.h" + +class Test : public IntrusivePtrBase { + public: + Test(int v) : + val(v) + { + } + const int val; +}; + +typedef LazyPointer TestLazyPointer; + +static +TestLazyPointer::pointer_type +factory() +{ + return new Test(3); +} + +static +TestLazyPointer::pointer_type +paramFactory(const std::string & str) +{ + return new Test(str.length()); +} + +BOOST_AUTO_TEST_CASE ( islazy ) +{ + TestLazyPointer p(boost::bind(&factory)); + BOOST_REQUIRE_EQUAL(false, p.hasValue()); + Test * t = p.get(); + BOOST_REQUIRE(t); + BOOST_REQUIRE_EQUAL(true, p.hasValue()); + BOOST_REQUIRE_EQUAL(p, t); + BOOST_REQUIRE_EQUAL(3, t->val); + BOOST_REQUIRE_EQUAL(3, p->val); +} + +BOOST_AUTO_TEST_CASE ( preinit ) +{ + Test * t = new Test(4); + TestLazyPointer p(t); + BOOST_REQUIRE_EQUAL(true, p.hasValue()); + BOOST_REQUIRE_EQUAL(p, t); + BOOST_REQUIRE_EQUAL(4, p->val); +} + +BOOST_AUTO_TEST_CASE ( reset ) +{ + Test * t = new Test(4); + TestLazyPointer p(t); + BOOST_REQUIRE_EQUAL(true, p.hasValue()); + BOOST_REQUIRE_EQUAL(4, p->val); + p = nullptr; + BOOST_REQUIRE_EQUAL(true, p.hasValue()); + BOOST_REQUIRE_EQUAL(true, !p); + p = boost::bind(&factory); + BOOST_REQUIRE_EQUAL(false, p.hasValue()); + p.get(); + BOOST_REQUIRE_EQUAL(true, p.hasValue()); + BOOST_REQUIRE_EQUAL(3, p->val); +} + +BOOST_AUTO_TEST_CASE ( nondefault ) +{ + TestLazyPointer p(boost::bind(¶mFactory, "some string")); + BOOST_REQUIRE_EQUAL(false, p.hasValue()); + BOOST_REQUIRE_EQUAL(11, (*p).val); + BOOST_REQUIRE_EQUAL(true, p.hasValue()); +} + -- cgit v1.2.3