diff options
| -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()); +} + | 
