Removed a lot of old comments and support code relating to the way arrays used to be handled in the C++ backend

This commit is contained in:
Neil Brown 2008-03-08 13:52:50 +00:00
parent e1fd001322
commit 5197435b2c
2 changed files with 1 additions and 311 deletions

View File

@ -25,46 +25,6 @@ In order to compile the generated code, you will need:
* The C++CSP2 library (>= 2.0.2), available from <http://www.cppcsp.net/>, and any appropriate dependencies (e.g. Boost).
For the array handling I am currently using a combination of std::vector and an array view class (tockArrayView) I built myself.
I considered the following options:
1. in-built C arrays
2. boost::array
3. std::vector
4. boost::multi_array
5. Blitz++
6. Roll my own.
Option 1 is what Adam used in GenerateC, but it involves carrying around the array sizes, which is a real pain.
Options 2 and 3 are fairly similar (boost::array is possible because arrays are of constant size in occam) but neither supports multiple dimensions
nor array slicing, so that would have been awkward.
Option 4 does support multiple dimensions and array slicing - but the latter would involve keeping tabs of the dimensions of the *original* array
(that was sliced *from*), even through multiple slices and indexes, which would have been a nightmare.
Option 5 makes slicing nice and simple, and multiple dimensions are easy too. However, things like retyping are still a big problem, so in the end
it became untenable.
Therefore the only remaining option was 6. I use std::vector (although this may become boost::array) to actually store each array, and then
use tockArrayView to work with the array. tockArrayView represents a view of an array, and never allocates or deallocates any memory. Thus they
can be passed around freely, which makes them easy to work with.
For the ANY type I am currently using boost::any. However, this is not a correct solution because the type that occam pulls out is not
necessarily the type that was put in. Therefore ANY probably needs some serialisation of types (akin to what used to happen in C++CSP.NET)
to work properly.
For the variant protocols I am using boost::variant. But when there are more than 9 cases, I have to chain several variants together.
This is perfectly legal C++, but I think it is causing excessive memory usage in g++ (or possibly the tuples that work similarly...)
For the sequential protocols (including those after a tag in variant protocols) I am using boost::tuple for convenience (along with the handy
boost::tie function to extract the values). However I suspect this (or the variants -- see above) is causing a lot of memory usage in g++. Plus,
when more than 9 items are present in the protocol (including variant-tag) I have to chain the tuples together, which means chaining the tie function
as well. May be worth changing in future.
Channels of direction 'A.DirUnknown' are passed around as pointers to a One2OneChannel\<\> object. To read I use the reader() function and to write I use the writer() function.
For channels of direction 'A.DirInput' or 'A.DirOutput' I actually pass the Chanin\<\> and Chanout\<\> objects as you would expect.
-}
@ -793,13 +753,13 @@ cppgenRetypeSizes m destT destN srcT srcV
tell ["}"] in
case destT of
-- TODO we should be able to remove this check now that arrays have changed
-- TODO or at least it needs fixing in some way...
-- An array -- figure out the genMissing dimension, if there is one.
A.Array destDS _ ->
case (indexOfFreeDimensions destDS) of
-- No free dimensions; check the complete array matches in size.
[] -> checkSize
-- Free dimensions; tockArrayView will check at run-time instead
_ -> return ()
-- Not array; just check the size is 1.
_ -> checkSize

View File

@ -109,224 +109,6 @@ public:
}
};
//For tieing together chained tuples:
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
class T8, class T9, class T10>
inline boost::tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&, T10>
tie10(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8,
T9& t9, T10 t10) {
return boost::tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&, T10>
(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
}
inline std::pair< boost::array<unsigned,1> , unsigned > tockDims(const unsigned d0)
{
boost::array<unsigned,1> r;
r[0] = d0;
return std::pair< boost::array<unsigned,1> , unsigned >(r,d0 == 0 ? 0 : 1);
}
/*
Generates functions like this:
inline std::pair< boost::array<unsigned,2> , unsigned > tockDims(const unsigned d0,const unsigned d1,const unsigned d2)
{
boost::array<unsigned,2> r;
r[0] = d0;
r[1] = d1;
r[2] = d2;
return std::pair< boost::array<unsigned,2> , unsigned >(r,d1 * d2);
}
*/
#define TOCKDIMS_ARGS(___z,NUM,___data) ,const unsigned d##NUM
#define TOCKDIMS_ASSIGN(___z,NUM,___data) r[ NUM ] = d##NUM ;
#define TOCKDIMS_MULT(___z,NUM,___data) * d##NUM
#define TOCKDIMS(___z,NUM,___data) inline std::pair< boost::array<unsigned, NUM >,unsigned> tockDims(\
const unsigned d0 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_ARGS,0) ) { \
boost::array<unsigned, NUM > r; BOOST_PP_REPEAT(NUM,TOCKDIMS_ASSIGN,0) \
return std::pair< boost::array<unsigned, NUM > , unsigned >(r,1 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_MULT,0) ); }
//Up to 12 dimensions:
BOOST_PP_REPEAT_FROM_TO(2,12,TOCKDIMS,0)
template < typename T, unsigned DIMS >
class tockArrayView
{
T* realArray;
boost::array<unsigned,DIMS> dims;
//dims[1] * dims[2] * dims[3] ...
//If DIMS is 0 or 1, totalSubDim will be 1
unsigned totalSubDim;
template <typename U>
inline void operator=(const U&) {}
inline tockArrayView(T* _realArray,const boost::array<unsigned,DIMS+1>& _biggerDims,unsigned _totalSubDim)
: realArray(_realArray),totalSubDim(_totalSubDim)
{
memcpy(dims.c_array(),_biggerDims.data() + 1,sizeof(unsigned) * DIMS);
}
friend class tockArrayView<T,DIMS + 1>;
//TODO change the other methods so we can feed a string in here (the Meta) to report to occam_stop
inline void correctDimsRetype(const unsigned totalSourceBytes)
{
if (totalSubDim == 0 || dims[0] == 0)
{
//Can only happen if one of the dimensions is zero, i.e. unknown
//We must find this dimension and calculate it:
unsigned zeroDim;
unsigned totalDim = 1;
for (unsigned i = 0;i < DIMS;i++)
{
if (dims[i] == 0)
zeroDim = i;
else
totalDim *= dims[i];
}
//Check it fits exactly:
if ((totalSourceBytes / totalDim) % sizeof(T) != 0)
{
occam_stop ("", 3, "invalid size for RETYPES/RESHAPES (%d does not divide into %d)", (totalSourceBytes / totalDim), sizeof(T));
}
//Set the size of the unknown dimension:
dims[zeroDim] = (totalSourceBytes / totalDim) / sizeof(T);
totalSubDim = (totalDim * dims[zeroDim]) / dims[0];
}
}
public:
inline tockArrayView()
: realArray(NULL)
{
dims.assign(0);
totalSubDim = 0;
}
inline tockArrayView(const tockArrayView& v)
: realArray(v.realArray),
dims(v.dims),
totalSubDim(v.totalSubDim)
{
}
inline tockArrayView(T* _realArray,const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims)
: realArray(_realArray),dims(_dims.first),totalSubDim(_dims.second)
{
}
inline tockArrayView(std::vector<typename boost::remove_const<T>::type>& _vec,const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims)
: realArray(_vec.empty() ? NULL : &(_vec.at(0))),dims(_dims.first),totalSubDim(_dims.second)
{
}
//The retyping constructors have their parameters in the other order to the same-type functions above,
//to avoid ambiguities between retyping and same types (especially when const is involved):
template <typename U>
inline tockArrayView(const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims,U* _realArray)
: realArray(reinterpret_cast<T*>(_realArray)),dims(_dims.first),totalSubDim(_dims.second)
{
//Assume it's a single U item:
correctDimsRetype(sizeof(U));
}
//Retyping, same number of dims:
template <typename U,unsigned FROMDIMS>
inline tockArrayView(const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims,const tockArrayView<U,FROMDIMS>& tav)
: realArray(reinterpret_cast<T*>(tav.data())),dims(_dims.first),totalSubDim(_dims.second)
{
correctDimsRetype(tav.size() * sizeof(U));
}
inline tockArrayView<T,DIMS - 1> operator[] (const unsigned index) const
{
return tockArrayView<T,DIMS - 1>(realArray + (totalSubDim * index),dims,DIMS <= 1 ? 1 : (totalSubDim / dims[1]));
}
inline tockArrayView<T,DIMS> sliceFor(const unsigned amount) const
{
return sliceFromFor(0,amount);
}
inline tockArrayView<T,DIMS> sliceFrom(const unsigned index) const
{
return sliceFromFor(index,dims[0] - index);
}
inline tockArrayView<T,DIMS> sliceFromFor(const unsigned index,const unsigned amount) const
{
boost::array<unsigned,DIMS> sliceDims = dims;
sliceDims[0] = amount;
return tockArrayView<T,DIMS>(realArray + (totalSubDim * index),std::make_pair(sliceDims,totalSubDim));
}
inline T* data() const
{
return realArray;
}
inline const boost::array<unsigned,DIMS>& getDims() const
{
return dims;
}
inline unsigned getTotalSubDim() const
{
return totalSubDim;
}
inline unsigned size() const
{
return dims[0] * totalSubDim;
}
inline unsigned extent(const unsigned dim) const
{
return dims[dim];
}
inline operator tockArrayView<const T,DIMS>() const
{
return tockArrayView<const T,DIMS>((const T*)realArray,std::make_pair(dims,totalSubDim));
}
};
template <typename T>
class tockArrayView<T,0>
{
T* realArray;
inline tockArrayView(T* _realArray,boost::array<unsigned,1>,unsigned)
: realArray(_realArray)
{
}
friend class tockArrayView<T,1>;
public:
//Should only be used on arrays with zero dimensions:
inline T& access() const
{
return *realArray;
}
};
class tockSendableArrayOfBytes
{
private:
@ -344,26 +126,12 @@ public:
{
}
///Also for the sender:
template <typename T, unsigned N>
inline explicit tockSendableArrayOfBytes(const tockArrayView<T,N>& arr)
: n(0),sp(arr.data())
{
}
///For the receiver:
inline tockSendableArrayOfBytes(unsigned _n,void* p)
: n(_n),dp(p)
{
}
//Also for the receiver:
template <typename T, unsigned N>
inline explicit tockSendableArrayOfBytes(unsigned _n, const tockArrayView<T,N>& arr)
: n(_n),dp(arr.data())
{
}
inline void operator=(const tockSendableArrayOfBytes& _src)
{
//We use the receiver's byte count:
@ -382,44 +150,6 @@ inline void tockRecvInt(const csp::Chanin<tockSendableArrayOfBytes>& c, unsigned
c >> d;
}
template <typename T, unsigned N>
class tockSendableArray
{
private:
tockSendableArrayOfBytes aob;
public:
template <unsigned D>
inline explicit tockSendableArray(const tockArrayView<T,D>& arr)
: aob(N*sizeof(T),arr.data())
{
}
template <unsigned D>
inline explicit tockSendableArray(const tockArrayView<const T,D>& arr)
: aob(arr.data())
{
}
};
template <typename T, unsigned N, unsigned D>
inline void tockSendArray(const csp::Chanout< tockSendableArray<T,N> >& out,const tockArrayView<T,D>& arr)
{
out << tockSendableArray<T,N>(arr);
}
template <typename T, unsigned N, unsigned D>
inline void tockRecvArray(const csp::Chanin< tockSendableArray<T,N> >& in,const tockArrayView<T,D>& arr)
{
tockSendableArray<T,N> tsa(arr);
in >> tsa;
}
template <typename T, unsigned N, unsigned D>
inline void tockSendArray(const csp::Chanout< tockSendableArray<T,N> >& out,const tockArrayView<const T,D>& arr)
{
out << tockSendableArray<T,N>(arr);
}
inline void tockSendArrayOfBytes(const csp::Chanout<tockSendableArrayOfBytes>& c, const tockSendableArrayOfBytes& b)
{
c << b;