diff --git a/src/lib/null-value.hpp b/src/lib/null-value.hpp new file mode 100644 index 000000000..5b102d110 --- /dev/null +++ b/src/lib/null-value.hpp @@ -0,0 +1,84 @@ +/* + NULL-VALUE.hpp - maintain per-type NIL values in static memory + + Copyright (C) Lumiera.org + 2010, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file null-value.hpp + ** Singleton-style holder for \em NIL or \em default values. + ** This template allows to maintain a "Null Object" value, with type-based access. + ** It is implemented as a cluster of Meyer's Singletons, thus the creation happens + ** on demand, and the destruction happens "sometime" during application shutdown. + ** Contrary to the generic lumiera Singleton holder, this implementation is + ** lightweight and without any further prerequisites, contains no logging, + ** no assertions and no locking. + ** @warning we can't make any assumptions regarding the exact time when the dtor + ** is called, and it is even impossible to detect if this happened already. + ** Any access after that point will use a defunct object, thus the user + ** needs to assure this facility is never used during application shutdown + ** + ** \par purpose of NIL objects + ** Employing the NIL object pattern instead of NULL pointers typically leads to + ** greatly simplified and more robust code. Usually the only problem is these NIL + ** marker objects need to exist somewhere. In case no factory is used for object + ** creation, this NullValue holder might satisfy this need. + ** + ** NIL objects are assumed to be default constructible for now. Initialisation + ** may introduce a race, which is considered acceptable here, as these objects + ** are assumed to be simple, constant and value-like. + ** + ** @todo initialisation could be extended to use a free function to fabricate + ** the NIL value object, so to support the special case of an NIL object + ** not being default constructible + ** + ** @see null-value-test.cpp + ** @see lib::advice::Request usage example + ** + */ + + + +#ifndef LIB_NULL_VALUE_H +#define LIB_NULL_VALUE_H + + + +namespace lib { + + /** + * Singleton holder for NIL or default value objects. + * Implemented as a cluster of Meyer's singletons, maintaining + * a single value per type. + */ + template + struct NullValue + { + static TY const& + get() + { + static TY nilValue; + return nilValue; + } + }; + + + +} // namespace lib +#endif diff --git a/tests/40components.tests b/tests/40components.tests index d8719d0db..eafc67b76 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -359,6 +359,11 @@ return: 0 END +TEST "NIL object singleton" NullValue_test < + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + + + +#include "lib/test/run.hpp" +#include "lib/null-value.hpp" +#include "lib/util.hpp" + +#include + + +namespace lib { +namespace test{ + + using util::isSameObject; + using std::rand; + + + namespace { // test data and helpers... + + + /** Test dummy to track ctor call */ + struct DummyType + { + static bool created; + + uint id_; + + DummyType() + : id_(1 + (rand() % 100)) + { + created = true; + } + }; + + bool DummyType::created = false; + + + } + + + + /*************************************************************************************** + * @test Access "NIL values" just by type, verify these are actually singletons + * and are indeed created on demand. + * + * @see null-value.hpp + * @see lib::advice::Request usage example + */ + class NullValue_test : public Test + { + + void + run (Arg) + { + CHECK (long() == NullValue::get()); + CHECK (short() == NullValue::get()); + CHECK (isSameObject(NullValue::get(), NullValue::get())); + + CHECK (!DummyType::created); + DummyType copy (NullValue::get()); + CHECK ( DummyType::created); + + CHECK ( copy.id_ == NullValue::get().id_); + CHECK (!isSameObject(NullValue::get(), copy)); + CHECK ( isSameObject(NullValue::get(), NullValue::get())); + } + }; + + + /** Register this test class... */ + LAUNCHER (NullValue_test, "unit common"); + + +}} // namespace lib::test