/* * C++CSP support code for Tock programs * Copyright (C) 2007, 2008 University of Kent * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2 of the License, or (at * your option) any later version. * * This library 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 Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ //To get the UINT8_MAX etc macros in C++: #define __STDC_LIMIT_MACROS #include class StopException { public: std::string reason; inline StopException(const std::string& _reason) : reason(_reason) { } }; #define occam_stop(pos, nargs, format, args...) \ do { \ char buffer[1024]; \ snprintf(buffer, sizeof(buffer), "Program stopped at %s: " format "\n", pos, ##args); \ throw StopException(buffer); \ } while (0) #include #include #include #include #include #include #include #include #include #include inline unsigned TimeDiffHelper(unsigned now,unsigned waitFor) { //If waitFor is in the 2^31 before now, it is in the past: if (now - waitFor < 2147483648) { //if we have wrapped round between waitFor and now, we actually want to return a minus-one: if ((waitFor >= 2147483648) && (now < 2147483648)) { return (unsigned)(int)(-1); } else { return 0; } } else { //It is in the future. If we will wrap round before getting there, return one: if ((now >= 2147483648) && (waitFor < 2147483648)) { return 1; } else { return 0; } } } class StreamWriter : public csp::CSProcess { private: std::ostream& out; csp::Chanin in; protected: virtual void run() { try { uint8_t c; while (true) { in >> c; out << c; } out.flush(); } catch (csp::PoisonException& e) { in.poison(); } } public: inline StreamWriter(std::ostream& _out,const csp::Chanin& _in) : out(_out),in(_in) { } }; class tockSendableArrayOfBytes { private: unsigned n; ///This is not as horrific as it looks - it is never used as a way to get rid of the const tag on the same pointer, only one field is used at a time. union { const void* sp; void* dp; }; public: ///For the sender: inline explicit tockSendableArrayOfBytes(const void* p) : n(0),sp(p) { } ///For the receiver: inline tockSendableArrayOfBytes(unsigned _n,void* p) : n(_n),dp(p) { } inline void operator=(const tockSendableArrayOfBytes& _src) { //We use the receiver's byte count: memcpy(dp,_src.sp,n); } }; inline void tockSendInt(const csp::Chanout& c, unsigned int n) { c << tockSendableArrayOfBytes(&n); } inline void tockRecvInt(const csp::Chanin& c, unsigned int* p) { tockSendableArrayOfBytes d(sizeof(unsigned int),p); c >> d; } inline void tockSendArrayOfBytes(const csp::Chanout& c, const tockSendableArrayOfBytes& b) { c << b; } inline void tockRecvArrayOfBytes(const csp::Chanin& c, const tockSendableArrayOfBytes& _b) { //We can't read into the const parameter, so we copy it into a non-const version and read into that. //The copying will preserve the pointer inside, so it doesn't cause any problems: tockSendableArrayOfBytes b(_b); c >> b; } template inline void tockInitChanArray(T* pointTo,T** pointFrom,int count) { for (int i = 0;i < count;i++) pointFrom[i] = &(pointTo[i]); } class StreamWriterByteArray : public csp::CSProcess { private: std::ostream& out; csp::Chanin in; protected: virtual void run() { try { uint8_t c; while (true) { tockSendableArrayOfBytes aob(1,&c); in >> aob; out << c; } out.flush(); } catch (csp::PoisonException& e) { in.poison(); } } public: inline StreamWriterByteArray(std::ostream& _out,const csp::Chanin& _in) : out(_out),in(_in) { } }; template class tockList { private: mutable std::list data; public: inline tockList() { } inline explicit tockList(const T& t) { data.push_back(t); } inline tockList& operator()(const T& t) { data.push_back(t); return *this; } typedef typename std::list::iterator iterator; inline iterator beginSeqEach() { return data.begin(); } inline iterator limitIterator() { return data.end(); } inline void endSeqEach() { } inline void remove(const iterator& _it) { data.erase(_it); } //TODO add beginParEach //TODO add functions for concatenation //By default the class acts like a mobile thing: inline void operator=(const tockList& _rhs) { data.clear(); data.swap(_rhs.data); } class derefTockList { private: tockList* ref; public: inline explicit derefTockList(tockList* _ref) : ref(_ref) { } //If you dereference both sides, you get a proper copy-assignment: void operator=(const derefTockList& _rhs) { ref->data = _rhs.ref->data; } }; derefTockList operator*() { return derefTockList(this); } };