Merge remote-tracking branch 'epics-base/master'

This commit is contained in:
Matej Sekoranja
2016-03-06 21:33:43 +01:00
8 changed files with 237 additions and 59 deletions

View File

@@ -12,7 +12,7 @@
###########################################
# Set EPICS Base version and upload target
BASE=3.15.2
BASE=3.15.3
PUBLISH=${1:-DONT}
###########################################

View File

@@ -24,8 +24,7 @@ using std::string;
namespace epics { namespace pvData {
PVField::PVField(FieldConstPtr field)
: notImplemented("not implemented"),
parent(NULL),field(field),
: parent(NULL),field(field),
fieldOffset(0), nextFieldOffset(0),
immutable(false)
{

View File

@@ -279,7 +279,8 @@ namespace epics { namespace pvData {
uint32 inUse = (set1.wordsInUse < set2.wordsInUse) ? set1.wordsInUse : set2.wordsInUse;
ensureCapacity(inUse);
wordsInUse = inUse;
if(inUse>wordsInUse)
wordsInUse = inUse;
// Perform logical AND on words in common
for (uint32 i = 0; i < inUse; i++)
@@ -358,7 +359,7 @@ namespace epics { namespace pvData {
words[j] = 0;
for (uint32 remaining = (bytes - longs * 8), j = 0; j < remaining; j++)
words[i] |= (buffer->getByte() & 0xffL) << (8 * j);
words[i] |= (buffer->getByte() & 0xffLL) << (8 * j);
}

View File

@@ -326,7 +326,7 @@ public:
//! Internal for static_shared_vector_cast
template<typename FROM>
shared_vector(const shared_vector<FROM> &src,
typename meta::is_void<FROM, detail::_shared_vector_cast_tag>::type)
detail::_shared_vector_cast_tag)
:base_t(std::tr1::static_pointer_cast<E>(src.dataPtr()),
src.dataOffset()/sizeof(E),
src.dataCount()/sizeof(E))
@@ -432,8 +432,8 @@ public:
shared_vector<E> original(...);
if(!original.unique()){
shared_vector<E> temp(myallocator(original.size()),
0, original.size());
std::tr1::shared_ptr<E> sptr(myalloc(original.size()), myfree);
shared_vector<E> temp(sptr, 0, original.size());
std::copy(original.begin(), original.end(), temp.begin());
original.swap(temp);
}
@@ -532,6 +532,20 @@ public:
*
* Does not allow access or iteration of contents
* other than as void* or const void*
*
* In order to support shared_vector_convert<>()
* information about the type of the underlying allocation
* is stored.
* This is implicitly set by static_shared_vector_cast<>()
* and may be explicitly checked/changed using
* original_type()/set_original_type().
*
* A shared_vector<void> directly constructed
* from a smart pointer does not have an associated
* original_type().
* Use epics::pvData::ScalarTypeFunc::allocArray()
* to convienently allocate an array with a known
* original_type().
*/
template<typename E>
class shared_vector<E, typename meta::is_void<E>::type >
@@ -539,7 +553,11 @@ class shared_vector<E, typename meta::is_void<E>::type >
{
typedef detail::shared_vector_base<E> base_t;
ScalarType m_vtype;
// allow specialization for all E to be friends
template<typename E1, class Enable1> friend class shared_vector;
public:
typedef E value_type;
typedef E* pointer;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
@@ -566,7 +584,7 @@ public:
//! Internal for static_shared_vector_cast
template<typename FROM>
shared_vector(const shared_vector<FROM> &src,
typename meta::is_not_void<FROM, detail::_shared_vector_cast_tag>::type)
detail::_shared_vector_cast_tag)
:base_t(std::tr1::static_pointer_cast<E>(src.dataPtr()),
src.dataOffset()*sizeof(FROM),
src.dataCount()*sizeof(FROM))
@@ -575,12 +593,12 @@ public:
shared_vector(shared_vector<void>& O,
detail::_shared_vector_freeze_tag t)
:base_t(O,t)
:base_t(O,t), m_vtype(O.m_vtype)
{}
shared_vector(shared_vector<const void>& O,
detail::_shared_vector_thaw_tag t)
:base_t(O,t)
:base_t(O,t), m_vtype(O.m_vtype)
{}
shared_vector& operator=(const shared_vector& o)
@@ -602,6 +620,64 @@ public:
ScalarType original_type() const {return m_vtype;}
};
namespace detail {
template<typename TO, typename FROM, class Enable = void>
struct static_shared_vector_caster { /* no default */ };
// from void to non-void with same const-ness
template<typename TO>
struct static_shared_vector_caster<TO, void,
typename meta::_and<meta::same_const<TO,void>, meta::is_not_void<TO> >::type> {
static inline shared_vector<TO> op(const shared_vector<void>& src) {
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
};
template<typename TO>
struct static_shared_vector_caster<TO, const void,
typename meta::_and<meta::same_const<TO,const void>, meta::is_not_void<TO> >::type> {
static inline shared_vector<TO> op(const shared_vector<const void>& src) {
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
};
// from non-void to void with same const-ness
template<typename FROM>
struct static_shared_vector_caster<void, FROM,
typename meta::_and<meta::same_const<void,FROM>, meta::is_not_void<FROM> >::type> {
static FORCE_INLINE shared_vector<void> op(const shared_vector<FROM>& src) {
return shared_vector<void>(src, detail::_shared_vector_cast_tag());
}
};
template<typename FROM>
struct static_shared_vector_caster<const void, FROM,
typename meta::_and<meta::same_const<const void,FROM>, meta::is_not_void<FROM> >::type> {
static FORCE_INLINE shared_vector<const void> op(const shared_vector<FROM>& src) {
return shared_vector<const void>(src, detail::_shared_vector_cast_tag());
}
};
// cast to same type, no-op
template<typename TOFRO>
struct static_shared_vector_caster<TOFRO,TOFRO,void> {
static FORCE_INLINE const shared_vector<TOFRO>& op(const shared_vector<TOFRO>& src) {
return src;
}
};
} // namespace detail
/** @brief Allow casting of shared_vector between types
*
* Currently only to/from void is implemented.
*
@warning Casting from void is undefined unless the offset and length
* are integer multiples of the size of the destination type.
*/
template<typename TO, typename FROM>
static FORCE_INLINE
shared_vector<TO>
static_shared_vector_cast(const shared_vector<FROM>& src)
{
return detail::static_shared_vector_caster<TO,FROM>::op(src);
}
namespace detail {
// Default to type conversion using castUnsafe (C++ type casting) on each element
@@ -634,7 +710,7 @@ namespace detail {
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
};
// convert from void uses original type or throws an exception.
template<typename TO, typename FROM>
struct shared_vector_converter<TO,FROM,
@@ -662,30 +738,16 @@ namespace detail {
};
}
/** @brief Allow casting of shared_vector between types
*
* Currently only to/from void is implemented.
*
@warning Casting from void is undefined unless the offset and length
* are integer multiples of the size of the destination type.
*/
template<typename TO, typename FROM>
static FORCE_INLINE
shared_vector<TO>
static_shared_vector_cast(const shared_vector<FROM>& src,
typename meta::same_const<TO,FROM,int>::type = 0)
{
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
}
/** @brief Allow converting of shared_vector between types
*
* Conversion utilizes castUnsafe<TO,FROM>().
*
* Converting to/from void is supported. Convert to void
* is an alias for static_shared_vector_cast<void>().
* Convert from void utilizes shared_vector<void>::original_type()
* and throws std::runtime_error if this is not valid.
* Convert from void utilizes shared_vector<void>::original_type().
*
* @throws std::runtime_error if cast is not valid.
* @throws std::bad_alloc for out of memory condition
*/
template<typename TO, typename FROM>
static FORCE_INLINE
@@ -861,8 +923,11 @@ std::ostream& operator<<(std::ostream& strm, const epics::pvData::shared_vector<
* shared_vector has additional constructors from raw pointers
* and shared_ptr s.
*
* The copy constructor and assignment operator allow implicit
* casting from type 'shared_vector<T>' to 'shared_vector<const T>'.
* Implicit casting is not allowed. Instead use
* const_shared_vector_cast()/freeze()/thaw() (@ref vectorconst)
* to casting between 'T' and 'const T'.
* Use static_shared_vector_cast() to cast between
* void and non-void (same const-ness).
*
* To facilitate safe modification the methods unique() and
* make_unique() are provided.
@@ -964,17 +1029,15 @@ Type #2 is constant reference to a mutable value.
Type #3 is a mutable reference to a constant value.
Type #4 is a constant reference to a constant value.
Casting between const and non-const references of the same value type
is governed by the normal C++ casting rules.
Casting between const and non-const values does @b not follow the normal
C++ casting rules.
C++ casting rules (no implicit cast).
For casting between shared_vector<T> and shared_vector<const T>
explicit casting operations are required. These operations are
@b freeze() (non-const to const) and @b thaw() (const to non-const).
A shared_vector<const T> is "frozen" as its value can not be modified.
A 'shared_vector<const T>' is "frozen" as its value can not be modified.
However it can still be sliced because the reference is not const.
These functions are defined like:
@@ -998,17 +1061,18 @@ The following guarantees are provided by both functions:
# The returned reference points to a value which is only referenced by
shared_vectors with the same value const-ness as the returned reference.
Please note that the argument of both freeze and thaw is a non-const
@note The argument of both freeze() and thaw() is a non-const
reference which will always be cleared.
@section vfreeze Freezing
The act of freezing a shared_vector requires that the shared_vector
passed in must be unique() or an exception is thrown. This is
done to reduce the possibility of accidental copying.
passed in must be unique() or an exception is thrown.
No copy is made.
This possibility can be avoided by calling the make_unique() on a
The possibility of an exception can be avoided by calling the make_unique() on a
shared_vector before passing it to freeze().
This will make a copy if necessary.
@section vthaw Thawing

View File

@@ -254,7 +254,6 @@ protected:
private:
static void computeOffset(const PVField *pvField);
static void computeOffset(const PVField *pvField,std::size_t offset);
std::string notImplemented;
std::string fieldName;
PVStructure *parent;
FieldConstPtr field;

View File

@@ -109,13 +109,13 @@ static void testOperators()
b1.set(1);
testOk1(!(b1 == b2));
// different internal length, but the same
testDiag("different internal length, but the same");
b2.set(100);
b2.set(1);
b2.flip(100);
testOk1(b1 == b2);
// OR test
testDiag("OR test");
b2.set(65);
b2.set(106);
b2.set(105);
@@ -127,12 +127,12 @@ static void testOperators()
str = toString(b1);
testOk1(str == "{1, 65, 105, 106}");
// AND test
testDiag("AND test");
b1.set(128);
b1 &= b2;
testOk1(b1 == b2);
// XOR test
testDiag("XOR test");
b1.set(128);
b1 ^= b2;
testOk1((b1.cardinality() == 1 && b1.get(128) == true));
@@ -144,17 +144,24 @@ static void testOperators()
testOk1((b1.cardinality() == 2 && b1.get(1) == true && b1.get(256) == true));
// assign
testDiag("assign");
b1 = b2;
testOk1(b1 == b2);
// or_and
testDiag("or_and");
b1.clear(); b1.set(2);
b2.clear(); b2.set(66); b2.set(128);
BitSet b3; b3.set(128); b3.set(520);
b1.or_and(b2, b3);
str = toString(b1);
testOk1(str == "{2, 128}");
b1.clear(); b1.set(1);
b2.clear();
b3.clear(); b3.set(1);
std::cout<<"# "<<toString(b3)<<" |= "<<toString(b1)<<" & "<<toString(b2)<<"\n";
b3.or_and(b1, b2);
testOk(toString(b3) == "{1}", "%s == {1}", toString(b3).c_str());
}
static void tofrostring(const BitSet& in, const char *expect, size_t elen, int byteOrder)
@@ -264,7 +271,7 @@ static void testSerialize()
MAIN(testBitSet)
{
testPlan(77);
testPlan(78);
testGetSetClearFlip();
testOperators();
testSerialize();

View File

@@ -358,19 +358,46 @@ static void testVoid()
{
testDiag("Test vector cast to/from void");
epics::pvData::shared_vector<int32> typed(4);
epics::pvData::shared_vector<int32> IV(4);
epics::pvData::shared_vector<void> untyped2(epics::pvData::static_shared_vector_cast<void>(typed));
epics::pvData::shared_vector<void> VV(epics::pvData::static_shared_vector_cast<void>(IV));
testOk1(typed.dataPtr().get()==untyped2.dataPtr().get());
testOk1(typed.size()*sizeof(int)==untyped2.size());
testOk1(IV.dataPtr().get()==VV.dataPtr().get());
testOk1(IV.size()*sizeof(int)==VV.size());
untyped2.slice(sizeof(int), 2*sizeof(int));
VV.slice(sizeof(int), 2*sizeof(int));
typed = epics::pvData::static_shared_vector_cast<int32>(untyped2);
IV = epics::pvData::static_shared_vector_cast<int32>(VV);
testOk1(typed.dataOffset()==1);
testOk1(typed.size()==2);
testOk1(IV.dataOffset()==1);
testOk1(IV.size()==2);
VV.clear();
}
static void testConstVoid()
{
testDiag("Test vector cast to/from const void");
epics::pvData::shared_vector<const int32> CIV(4);
epics::pvData::shared_vector<const void> CVV(epics::pvData::static_shared_vector_cast<const void>(CIV));
// case const void to const void
epics::pvData::shared_vector<const void> CVV2(epics::pvData::static_shared_vector_cast<const void>(CVV));
testOk1(CIV.dataPtr().get()==CVV2.dataPtr().get());
testOk1(CIV.size()*sizeof(int)==CVV2.size());
CVV2.slice(sizeof(int), 2*sizeof(int));
CIV = epics::pvData::static_shared_vector_cast<const int32>(CVV2);
testOk1(CIV.dataOffset()==1);
testOk1(CIV.size()==2);
epics::pvData::shared_vector<void> VV;
// not possible to thaw() void as shared_vector<void> has no make_unique()
//VV = thaw(CVV);
CVV = freeze(VV);
}
struct dummyStruct {};
@@ -537,9 +564,66 @@ static void testICE()
}
}
static
void testBad()
{
epics::pvData::shared_vector<int> I;
epics::pvData::shared_vector<const int> CI;
epics::pvData::shared_vector<float> F;
epics::pvData::shared_vector<const float> CF;
epics::pvData::shared_vector<void> V;
epics::pvData::shared_vector<const void> CV;
(void)I;
(void)CI;
(void)F;
(void)CF;
(void)V;
(void)CV;
// Tests which should result in compile failure.
// as there is no established way to test this automatically,
// uncomment one at a time
// No copy from const to non-const
//CI = I;
//I = CI;
//epics::pvData::shared_vector<const int> CI2(I);
//epics::pvData::shared_vector<int> I2(CI);
// shared_vector_convert can't thaw()
//I = epics::pvData::shared_vector_convert<int>(CI);
//V = epics::pvData::shared_vector_convert<void>(CV);
// shared_vector_convert can't freeze()
//CI = epics::pvData::shared_vector_convert<const int>(I);
//CV = epics::pvData::shared_vector_convert<const void>(V);
// static_shared_vector_cast can't thaw()
//I = epics::pvData::static_shared_vector_cast<int>(CI);
//V = epics::pvData::static_shared_vector_cast<void>(CV);
// static_shared_vector_cast can't freeze()
//CI = epics::pvData::static_shared_vector_cast<const int>(I);
//CV = epics::pvData::static_shared_vector_cast<const void>(V);
// freeze() can't change type.
// the error here will be with the assignment
//I = epics::pvData::freeze(CV);
//I = epics::pvData::freeze(CF);
//CI = epics::pvData::freeze(V);
//CI = epics::pvData::freeze(F);
// that() can't change type.
// the error here will be with the assignment
//CI = epics::pvData::thaw(V);
//CI = epics::pvData::thaw(F);
//I = epics::pvData::thaw(CV);
//I = epics::pvData::that(CF);
}
MAIN(testSharedVector)
{
testPlan(163);
testPlan(167);
testDiag("Tests for shared_vector");
testDiag("sizeof(shared_vector<int32>)=%lu",
@@ -554,9 +638,11 @@ MAIN(testSharedVector)
testSlice();
testPush();
testVoid();
testConstVoid();
testNonPOD();
testVectorConvert();
testWeak();
testICE();
testBad();
return testDone();
}

View File

@@ -177,11 +177,32 @@ static void testShare()
testOk1(!cdata.unique());
}
static void testVoid()
{
testDiag("Check PVScalarArray put/get from void");
PVIntArrayPtr iarr = static_pointer_cast<PVIntArray>(getPVDataCreate()->createPVScalarArray(pvInt));
PVIntArray::const_svector idata(4, 1);
iarr->PVScalarArray::putFrom(idata);
idata.clear();
shared_vector<const void> cvbuf;
iarr->PVScalarArray::getAs(cvbuf);
idata = static_shared_vector_cast<const PVIntArray::value_type>(cvbuf);
testOk1(idata.size()==4);
iarr->PVScalarArray::putFrom(cvbuf);
testOk1(iarr->getLength()==4);
}
} // end namespace
MAIN(testPVScalarArray)
{
testPlan(156);
testPlan(158);
testFactory();
testBasic<PVByteArray>();
testBasic<PVUByteArray>();
@@ -189,5 +210,6 @@ MAIN(testPVScalarArray)
testBasic<PVDoubleArray>();
testBasic<PVStringArray>();
testShare();
testVoid();
return testDone();
}