diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-08-29 01:21:12 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-08-29 01:21:12 +0100 |
commit | 15e24ff7021ecb9646a55d11edef96061e846491 (patch) | |
tree | ee869562fbaea267dff4bc39c5e9d120f01236b8 | |
parent | Move and test lock helpers (diff) | |
download | libadhocutil-15e24ff7021ecb9646a55d11edef96061e846491.tar.bz2 libadhocutil-15e24ff7021ecb9646a55d11edef96061e846491.tar.xz libadhocutil-15e24ff7021ecb9646a55d11edef96061e846491.zip |
Move and test lazy pointer
-rw-r--r-- | libadhocutil/lazyPointer.h | 126 | ||||
-rw-r--r-- | libadhocutil/unittests/Jamfile.jam | 10 | ||||
-rw-r--r-- | libadhocutil/unittests/testLazyPointer.cpp | 77 |
3 files changed, 213 insertions, 0 deletions
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 <boost/function.hpp> +#include <boost/variant.hpp> +#include <boost/intrusive_ptr.hpp> + +template <typename T, typename P = boost::intrusive_ptr<T>> +class LazyPointer { + public: + typedef T element_type; + typedef P pointer_type; + typedef boost::function0<P> Factory; + typedef boost::variant<P, Factory> 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<Factory>(&source)) { + P p = (*f)(); + source = p; + return p; + } + else { + return boost::get<P>(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<T, P> & operator=(const P & p) + { + source = p; + return *this; + } + + LazyPointer<T, P> & operator=(T * t) + { + source = P(t); + return *this; + } + + LazyPointer<T, P> & operator=(const Factory & f) + { + source = f; + return *this; + } + + bool hasValue() const + { + return boost::get<P>(&source); + } + + private: + mutable Source source; +}; + +namespace boost { + template <typename R, typename T, typename P> + R * dynamic_pointer_cast(const LazyPointer<T, P> & p) { + return dynamic_cast<R *>(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 + : : : + <define>BOOST_TEST_DYN_LINK + <library>..//adhocutil + <library>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 <boost/test/unit_test.hpp> + +#include <boost/bind.hpp> +#include "intrusivePtrBase.h" +#include "lazyPointer.h" + +class Test : public IntrusivePtrBase { + public: + Test(int v) : + val(v) + { + } + const int val; +}; + +typedef LazyPointer<Test> 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()); +} + |