consider using RefArray for the Session API
This commit is contained in:
parent
ea538d962f
commit
bfc18dfb94
8 changed files with 264 additions and 261 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
REFARRAYIMPL.hpp - some implementations of the ref-array interface
|
||||
REF-ARRAY-IMPL.hpp - some implementations of the ref-array interface
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -20,30 +20,30 @@
|
|||
|
||||
*/
|
||||
|
||||
/** @file refarrayimpl.hpp
|
||||
/** @file ref-array-impl.hpp
|
||||
** Some (library-) implementations of the RefArray interface.
|
||||
**
|
||||
**
|
||||
** Being an array-like object exposing just a const ref, it is typically used
|
||||
** on interfaces, and the type of the array "elements" usually is a ABC or interface.
|
||||
** The actual implementation usually holds a subclass, and is either based on a vector,
|
||||
** The actual implementation typically holds a subclass, and is either based on a vector,
|
||||
** or a fixed storage contained within the implementation. The only price to pay is
|
||||
** that of an virtual call on element access.
|
||||
** a virtual call on element access.
|
||||
**
|
||||
** For advanced use it would be possible to have a pointer-array or even an embedded
|
||||
** For advanced uses it would be possible to have a pointer-array or even an embedded
|
||||
** storage of variant-records, able to hold a mixture of subclasses. (the latter cases
|
||||
** will be implemented when needed).
|
||||
**
|
||||
** @see refarraytest.cpp
|
||||
**
|
||||
** @see ref-array-test.cpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIB_REFARRAYIMPL_H
|
||||
#define LIB_REFARRAYIMPL_H
|
||||
#ifndef LIB_REF_ARRAY_IMPL_H
|
||||
#define LIB_REF_ARRAY_IMPL_H
|
||||
|
||||
|
||||
#include "lib/refarray.hpp"
|
||||
#include "proc/nobugcfg.hpp"
|
||||
#include "lib/ref-array.hpp"
|
||||
#include "include/logging.h"
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
|
|
@ -74,7 +74,7 @@ namespace lib {
|
|||
return table_.size();
|
||||
}
|
||||
|
||||
virtual B const& operator[] (size_t i) const
|
||||
virtual B const& operator[] (size_t i) const
|
||||
{
|
||||
REQUIRE (i < size());
|
||||
return table_[i];
|
||||
|
|
@ -108,7 +108,7 @@ namespace lib {
|
|||
|
||||
|
||||
/**
|
||||
* RefArray implementation based on a fix sized array,
|
||||
* RefArray implementation based on a fixed size array,
|
||||
* i.e. the storage is embedded. Embedded subclass obj
|
||||
* either need to be default constructible or be
|
||||
* placed directly by a factory
|
||||
|
|
@ -167,8 +167,9 @@ namespace lib {
|
|||
REQUIRE (i < size());
|
||||
return array_[i];
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace lib
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
REFARRAY.hpp - abstraction providing array-like access to a list of references
|
||||
REF-ARRAY.hpp - abstraction providing array-like access to a list of references
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef LIB_REFARRAY_H
|
||||
#define LIB_REFARRAY_H
|
||||
#ifndef LIB_REF_ARRAY_H
|
||||
#define LIB_REF_ARRAY_H
|
||||
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
** - contained objects accessed by reference, never NULL.
|
||||
** - the exposed iterator automatically dereferences
|
||||
** - TODO: detaching of objects...
|
||||
** - TODO: retro-fit with refarray interface (--> builder branch)
|
||||
** - TODO: retro-fit with RefArray interface
|
||||
**
|
||||
** @see scoped-ptrvect-test.cpp
|
||||
** @see scoped-holder.hpp
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
|
||||
#include "proc/engine/procnode.hpp"
|
||||
#include "lib/refarray.hpp"
|
||||
#include "lib/ref-array.hpp"
|
||||
#include "lib/util-foreach.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include "proc/asset/proc.hpp"
|
||||
#include "proc/mobject/parameter.hpp"
|
||||
#include "lib/frameid.hpp"
|
||||
#include "lib/refarray.hpp"
|
||||
#include "lib/ref-array.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
|
|||
241
tests/common/ref-array-test.cpp
Normal file
241
tests/common/ref-array-test.cpp
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
RefArray(Test) - unittest for wrapping with array-of-refs access
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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/util.hpp"
|
||||
|
||||
#include "lib/ref-array-impl.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using ::test::Test;
|
||||
using std::vector;
|
||||
using std::rand;
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace test{
|
||||
|
||||
|
||||
namespace { // test types
|
||||
|
||||
struct I
|
||||
{
|
||||
virtual int op(int i) const =0;
|
||||
virtual ~I() {}
|
||||
};
|
||||
|
||||
struct Sub1 : I
|
||||
{
|
||||
int offs_;
|
||||
|
||||
Sub1 (int o=1) : offs_(o) {}
|
||||
|
||||
int op (int i) const { return i+offs_; }
|
||||
};
|
||||
|
||||
struct Sub2 : I
|
||||
{
|
||||
const char* letterz_;
|
||||
Sub2() : letterz_("ABCDEFGHIJKLMNOPQRSTUVWXYZ") {}
|
||||
|
||||
int op (int i) const { return (int)letterz_[i % 26]; }
|
||||
};
|
||||
|
||||
struct Sub3 : I
|
||||
{
|
||||
int id_;
|
||||
static long sum;
|
||||
static long trigger;
|
||||
|
||||
Sub3(int id) : id_(id)
|
||||
{
|
||||
sum +=id_;
|
||||
if ( id_ == trigger )
|
||||
throw trigger; // fail while in construction
|
||||
}
|
||||
~Sub3()
|
||||
{
|
||||
sum -=id_;
|
||||
}
|
||||
|
||||
int op (int i) const { return i + id_; }
|
||||
};
|
||||
|
||||
long Sub3::sum = 0;
|
||||
long Sub3::trigger = -1;
|
||||
|
||||
|
||||
} // (END) test types
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* @test build several wrappers, each based on a different storage,
|
||||
* all providing RefArray access to a given vector. The rationale
|
||||
* for RefArray is to expose just the interface: the data structure
|
||||
* within the actual implementation holds subclass instances of
|
||||
* the specified interface.
|
||||
* - RefArrayVectorWrapper is a ref to an existing vector
|
||||
* - RefArrayVector subclasses std::vector
|
||||
* - RefArrayTable holds a fix sized table, i.e. embedded storage
|
||||
*
|
||||
* @see ref-array-impl.hpp
|
||||
*/
|
||||
class RefArray_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
checkWrapper();
|
||||
checkVector();
|
||||
checkTable();
|
||||
checkTable_inplaceCreation();
|
||||
checkTable_errorHandling();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
checkWrapper()
|
||||
{
|
||||
vector<Sub2> subz(10);
|
||||
RefArrayVectorWrapper<I,Sub2> subWrap (subz);
|
||||
|
||||
RefArray<I> & rArr (subWrap);
|
||||
|
||||
ASSERT (subWrap.size()==subz.size());
|
||||
ASSERT (INSTANCEOF(I, &rArr[0]));
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
{
|
||||
ASSERT (&rArr[i] == &subz[i]);
|
||||
ASSERT (rArr[i].op(i) == subz[i].op(i));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkVector()
|
||||
{
|
||||
RefArrayVector<I,Sub2> subz(10);
|
||||
|
||||
vector<Sub2> & vect (subz);
|
||||
RefArray<I> & rArr (subz);
|
||||
|
||||
ASSERT (vect.size()==subz.size());
|
||||
ASSERT (INSTANCEOF(I, &rArr[0]));
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
{
|
||||
ASSERT (&rArr[i] == &vect[i]);
|
||||
ASSERT (rArr[i].op(i) == vect[i].op(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ADR(OBJ) (ulong)&(OBJ)
|
||||
|
||||
void
|
||||
checkTable()
|
||||
{
|
||||
RefArrayTable<I,20,Sub1> tab;
|
||||
// creates 20 Sub1-objects in-place
|
||||
// which are indeed located within the object
|
||||
ASSERT (sizeof(tab) >= 20 * sizeof(Sub1));
|
||||
ASSERT (ADR(tab) < ADR(tab[19]) && ADR(tab[19]) < ADR(tab) + sizeof(tab));
|
||||
|
||||
RefArray<I> & rArr (tab);
|
||||
|
||||
ASSERT (20 == tab.size());
|
||||
ASSERT (INSTANCEOF(I, &rArr[0]));
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
{
|
||||
ASSERT (i*sizeof(Sub1) == ADR(rArr[i]) - ADR(rArr[0]) ); // indeed array-like storage
|
||||
ASSERT (int(i+1) == rArr[i].op(i)); // check the known result
|
||||
}
|
||||
}
|
||||
|
||||
template<class SUB>
|
||||
struct Fac ///< fabricating a series of subclass instances with varying ctor parameter
|
||||
{
|
||||
int offset_;
|
||||
Fac ( ) : offset_ (0) {}
|
||||
|
||||
void operator() (void* place)
|
||||
{
|
||||
ASSERT (place);
|
||||
new(place) SUB (offset_++); // note: varying ctor parameter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
checkTable_inplaceCreation()
|
||||
{
|
||||
Fac<Sub1> theFact;
|
||||
RefArrayTable<I,30,Sub1> tab (theFact);
|
||||
RefArray<I> & rArr (tab);
|
||||
ASSERT (30 == tab.size());
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
ASSERT (int(i+i) == rArr[i].op(i)); // each one has gotten another offset ctor parameter
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkTable_errorHandling()
|
||||
{
|
||||
for (uint i=0; i<500; ++i)
|
||||
{
|
||||
Sub3::sum = 0;
|
||||
Sub3::trigger = (rand() % 50); // when hitting the trigger Sub3 throws
|
||||
try
|
||||
{
|
||||
{
|
||||
Fac<Sub3> factory;
|
||||
RefArrayTable<I,30,Sub3> table (factory);
|
||||
ASSERT (Sub3::sum == (29+1)*29/2);
|
||||
}
|
||||
ASSERT (Sub3::sum == 0);
|
||||
}
|
||||
|
||||
catch(long id)
|
||||
{
|
||||
ASSERT (id == Sub3::trigger);
|
||||
ASSERT (Sub3::sum == id);
|
||||
// meaning: all objects have been cleaned up,
|
||||
// with the exception of the one hitting the trigger
|
||||
} }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (RefArray_test, "unit common");
|
||||
|
||||
|
||||
|
||||
}} // namespace lib::test
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
/*
|
||||
RefArray(Test) - unittest for wrapping with array-of-refs access
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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/util.hpp"
|
||||
|
||||
#include "lib/refarrayimpl.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using ::test::Test;
|
||||
using std::vector;
|
||||
using std::rand;
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace test {
|
||||
|
||||
namespace { // test types
|
||||
|
||||
struct I
|
||||
{
|
||||
virtual int op(int i) const =0;
|
||||
virtual ~I() {}
|
||||
};
|
||||
|
||||
struct Sub1 : I
|
||||
{
|
||||
int offs_;
|
||||
|
||||
Sub1 (int o=1) : offs_(o) {}
|
||||
|
||||
int op (int i) const { return i+offs_; }
|
||||
};
|
||||
|
||||
struct Sub2 : I
|
||||
{
|
||||
const char* letterz_;
|
||||
Sub2() : letterz_("ABCDEFGHIJKLMNOPQRSTUVWXYZ") {}
|
||||
|
||||
int op (int i) const { return (int)letterz_[i % 26]; }
|
||||
};
|
||||
|
||||
struct Sub3 : I
|
||||
{
|
||||
int id_;
|
||||
static long sum;
|
||||
static long trigger;
|
||||
|
||||
Sub3(int id) : id_(id)
|
||||
{
|
||||
sum +=id_;
|
||||
if ( id_ == trigger )
|
||||
throw trigger; // fail while in construction
|
||||
}
|
||||
~Sub3()
|
||||
{
|
||||
sum -=id_;
|
||||
}
|
||||
|
||||
int op (int i) const { return i + id_; }
|
||||
};
|
||||
|
||||
long Sub3::sum = 0;
|
||||
long Sub3::trigger = -1;
|
||||
|
||||
|
||||
} // (END) test types
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* @test build several wrappers, each based on a different storage,
|
||||
* all providing RefArray access to a given vector. The rationale
|
||||
* is to expose just the interface.
|
||||
* - RefArrayVectorWrapper is a ref to an existing vector
|
||||
* - RefArrayVector subclasses std::vector
|
||||
* - RefArrayTable holds a fix sized table, i.e. embedded storage
|
||||
*
|
||||
* @see refarrayimpl.hpp
|
||||
*/
|
||||
class RefArray_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg arg)
|
||||
{
|
||||
checkWrapper();
|
||||
checkVector();
|
||||
checkTable();
|
||||
checkTable_inplaceCreation();
|
||||
checkTable_errorHandling();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkWrapper()
|
||||
{
|
||||
vector<Sub2> subz(10);
|
||||
RefArrayVectorWrapper<I,Sub2> subWrap (subz);
|
||||
|
||||
RefArray<I> & rArr (subWrap);
|
||||
|
||||
ASSERT (subWrap.size()==subz.size());
|
||||
ASSERT (INSTANCEOF(I, &rArr[0]));
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
{
|
||||
ASSERT (&rArr[i] == &subz[i]);
|
||||
ASSERT (rArr[i].op(i) == subz[i].op(i));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkVector()
|
||||
{
|
||||
RefArrayVector<I,Sub2> subz(10);
|
||||
|
||||
vector<Sub2> & vect (subz);
|
||||
RefArray<I> & rArr (subz);
|
||||
|
||||
ASSERT (vect.size()==subz.size());
|
||||
ASSERT (INSTANCEOF(I, &rArr[0]));
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
{
|
||||
ASSERT (&rArr[i] == &vect[i]);
|
||||
ASSERT (rArr[i].op(i) == vect[i].op(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ADR(OBJ) (ulong)&(OBJ)
|
||||
|
||||
void
|
||||
checkTable()
|
||||
{
|
||||
RefArrayTable<I,20,Sub1> tab;
|
||||
// creates 20 Sub1-objects in-place
|
||||
// which are indeed located within the object
|
||||
ASSERT (sizeof(tab) >= 20 * sizeof(Sub1));
|
||||
ASSERT (ADR(tab) < ADR(tab[19]) && ADR(tab[19]) < ADR(tab) + sizeof(tab));
|
||||
|
||||
RefArray<I> & rArr (tab);
|
||||
|
||||
ASSERT (20 == tab.size());
|
||||
ASSERT (INSTANCEOF(I, &rArr[0]));
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
{
|
||||
ASSERT (i*sizeof(Sub1) == ADR(rArr[i]) - ADR(rArr[0]) ); // indeed array-like storage
|
||||
ASSERT (int(i+1) == rArr[i].op(i)); // check the known result
|
||||
}
|
||||
}
|
||||
|
||||
template<class SUB>
|
||||
struct Fac ///< fabricating a series of subclass instances with varying ctor parameter
|
||||
{
|
||||
int offset_;
|
||||
Fac ( ) : offset_ (0) {}
|
||||
|
||||
void operator() (void* place)
|
||||
{
|
||||
ASSERT (place);
|
||||
new (place) SUB (offset_++); // note: varying ctor parameter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
checkTable_inplaceCreation()
|
||||
{
|
||||
Fac<Sub1> theFact;
|
||||
RefArrayTable<I,30,Sub1> tab (theFact);
|
||||
RefArray<I> & rArr (tab);
|
||||
ASSERT (30 == tab.size());
|
||||
for (size_t i=0; i<rArr.size(); ++i)
|
||||
ASSERT (int(i+i) == rArr[i].op(i)); // each one has gotten another offset ctor parameter
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkTable_errorHandling()
|
||||
{
|
||||
for (uint i=0; i<500; ++i)
|
||||
{
|
||||
Sub3::sum = 0;
|
||||
Sub3::trigger = (rand() % 50); // when hitting the trigger Sub3 throws
|
||||
try
|
||||
{
|
||||
{
|
||||
Fac<Sub3> factory;
|
||||
RefArrayTable<I,30,Sub3> table (factory);
|
||||
ASSERT (Sub3::sum == (29+1)*29/2);
|
||||
}
|
||||
ASSERT (Sub3::sum == 0);
|
||||
}
|
||||
|
||||
catch(long id)
|
||||
{
|
||||
ASSERT (id == Sub3::trigger);
|
||||
ASSERT (Sub3::sum == id);
|
||||
// meaning: all objects have been cleaned up,
|
||||
// with the exception of the one hitting the trigger
|
||||
} }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (RefArray_test, "unit common");
|
||||
|
||||
|
||||
|
||||
} // namespace test
|
||||
|
||||
} // namespace lib
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "proc/engine/procnode.hpp"
|
||||
#include "proc/engine/bufftable.hpp"
|
||||
#include "lib/refarray.hpp"
|
||||
#include "lib/ref-array.hpp"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
|
|
|
|||
Loading…
Reference in a new issue