implement a simple singleton holder for NIL/default objects

This commit is contained in:
Fischlurch 2010-06-02 06:03:06 +02:00
parent a6621703af
commit 68aefe5074
3 changed files with 185 additions and 0 deletions

84
src/lib/null-value.hpp Normal file
View 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

View file

@ -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

View 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