implement a simple singleton holder for NIL/default objects
This commit is contained in:
parent
a6621703af
commit
68aefe5074
3 changed files with 185 additions and 0 deletions
84
src/lib/null-value.hpp
Normal file
84
src/lib/null-value.hpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
NULL-VALUE.hpp - maintain per-type NIL values in static memory
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2010, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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 <b>never used during application shutdown</b>
|
||||
**
|
||||
** \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<class TY>
|
||||
struct NullValue
|
||||
{
|
||||
static TY const&
|
||||
get()
|
||||
{
|
||||
static TY nilValue;
|
||||
return nilValue;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace lib
|
||||
#endif
|
||||
|
|
@ -315,6 +315,11 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "NIL object singleton" NullValue_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "inline type erasure" OpaqueHolder_test <<END
|
||||
out: 1
|
||||
out: 3
|
||||
|
|
|
|||
96
tests/lib/null-value-test.cpp
Normal file
96
tests/lib/null-value-test.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
NullValue(Test) - verify the singleton holder for NIL or default values
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2010, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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 <cstdlib>
|
||||
|
||||
|
||||
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<long>::get());
|
||||
CHECK (short() == NullValue<short>::get());
|
||||
CHECK (isSameObject(NullValue<short>::get(), NullValue<short>::get()));
|
||||
|
||||
CHECK (!DummyType::created);
|
||||
DummyType copy (NullValue<DummyType>::get());
|
||||
CHECK ( DummyType::created);
|
||||
|
||||
CHECK ( copy.id_ == NullValue<DummyType>::get().id_);
|
||||
CHECK (!isSameObject(NullValue<DummyType>::get(), copy));
|
||||
CHECK ( isSameObject(NullValue<DummyType>::get(), NullValue<DummyType>::get()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (NullValue_test, "unit common");
|
||||
|
||||
|
||||
}} // namespace lib::test
|
||||
Loading…
Reference in a new issue