ENH: improved parallel transfer of strings

- support send/receive with embedded '\0' characters
This commit is contained in:
Mark Olesen
2017-11-04 15:51:52 +01:00
parent f42ed2fc9f
commit 507486194e
4 changed files with 51 additions and 18 deletions

View File

@ -120,6 +120,24 @@ void testMapDistribute()
} }
// Print to Perr
template<class T>
Ostream& perrInfo(const T& data)
{
Perr<< data;
return Perr;
}
// Print to Perr
template<>
Ostream& perrInfo(const string& data)
{
Perr<< data << " (size: " << data.size() << ")";
return Perr;
}
template<class T> template<class T>
void testTransfer(const T& input) void testTransfer(const T& input)
{ {
@ -127,7 +145,8 @@ void testTransfer(const T& input)
if (Pstream::master()) if (Pstream::master())
{ {
Perr<<"test transfer (" << (typeid(T).name()) << "): " << data << nl << endl; Perr<<"test transfer (" << (typeid(T).name()) << "): ";
perrInfo(data) << nl << endl;
} }
if (Pstream::myProcNo() != Pstream::masterNo()) if (Pstream::myProcNo() != Pstream::masterNo())
@ -141,7 +160,7 @@ void testTransfer(const T& input)
Perr<< "slave receiving from master " << Pstream::masterNo() << endl; Perr<< "slave receiving from master " << Pstream::masterNo() << endl;
IPstream fromMaster(Pstream::commsTypes::blocking, Pstream::masterNo()); IPstream fromMaster(Pstream::commsTypes::blocking, Pstream::masterNo());
fromMaster >> data; fromMaster >> data;
Perr<< data << endl; perrInfo(data) << endl;
} }
else else
{ {
@ -155,7 +174,7 @@ void testTransfer(const T& input)
Perr<< "master receiving from slave " << slave << endl; Perr<< "master receiving from slave " << slave << endl;
IPstream fromSlave(Pstream::commsTypes::blocking, slave); IPstream fromSlave(Pstream::commsTypes::blocking, slave);
fromSlave >> data; fromSlave >> data;
Perr<< data << endl; perrInfo(data) << endl;
} }
for for
@ -258,6 +277,15 @@ int main(int argc, char *argv[])
testTransfer(scalar(3.14159)); testTransfer(scalar(3.14159));
testTransfer(string("test string")); testTransfer(string("test string"));
testTransfer(string(" x ")); testTransfer(string(" x "));
{
// Slightly roundabout way to construct with a nul in string
string str1("embedded. nul character in string");
str1[8] = '\0';
Info<< "len: " << str1.size() << endl;
testTransfer(str1);
}
testTransfer(word("3.141 59")); // bad word, but transfer doesn't care testTransfer(word("3.141 59")); // bad word, but transfer doesn't care
testTokenized(label(1234)); testTokenized(label(1234));

View File

@ -42,12 +42,12 @@ inline void Foam::UIPstream::checkEof()
template<class T> template<class T>
inline void Foam::UIPstream::readFromBuffer(T& t) inline void Foam::UIPstream::readFromBuffer(T& val)
{ {
const size_t align = sizeof(T); const size_t align = sizeof(T);
externalBufPosition_ = align + ((externalBufPosition_ - 1) & ~(align - 1)); externalBufPosition_ = align + ((externalBufPosition_ - 1) & ~(align - 1));
t = reinterpret_cast<T&>(externalBuf_[externalBufPosition_]); val = reinterpret_cast<T&>(externalBuf_[externalBufPosition_]);
externalBufPosition_ += sizeof(T); externalBufPosition_ += sizeof(T);
checkEof(); checkEof();
} }
@ -67,10 +67,14 @@ inline void Foam::UIPstream::readFromBuffer
+ ((externalBufPosition_ - 1) & ~(align - 1)); + ((externalBufPosition_ - 1) & ~(align - 1));
} }
const char* bufPtr = &externalBuf_[externalBufPosition_]; const char* const __restrict__ buf = &externalBuf_[externalBufPosition_];
char* dataPtr = reinterpret_cast<char*>(data); char* const __restrict__ output = reinterpret_cast<char*>(data);
size_t i = count;
while (i--) *dataPtr++ = *bufPtr++; for (size_t i = 0; i < count; ++i)
{
output[i] = buf[i];
}
externalBufPosition_ += count; externalBufPosition_ += count;
checkEof(); checkEof();
} }
@ -78,14 +82,15 @@ inline void Foam::UIPstream::readFromBuffer
inline Foam::Istream& Foam::UIPstream::readStringFromBuffer(std::string& str) inline Foam::Istream& Foam::UIPstream::readStringFromBuffer(std::string& str)
{ {
// Use std::string::assign() to copy content, including '\0'.
// Stripping (when desired) is the responsibility of the sending side.
size_t len; size_t len;
readFromBuffer(len); readFromBuffer(len);
// Uses the underlying std::string::operator=()
// - no stripInvalid invoked (the sending side should have done that) str.assign(&externalBuf_[externalBufPosition_], len);
// - relies on trailing '\0' char (so cannot send anything with an embedded
// nul char) externalBufPosition_ += len;
str = &externalBuf_[externalBufPosition_];
externalBufPosition_ += len + 1;
checkEof(); checkEof();
return *this; return *this;
@ -276,7 +281,7 @@ Foam::Istream& Foam::UIPstream::read(token& t)
Foam::Istream& Foam::UIPstream::read(char& c) Foam::Istream& Foam::UIPstream::read(char& c)
{ {
c = externalBuf_[externalBufPosition_]; c = externalBuf_[externalBufPosition_];
externalBufPosition_++; ++externalBufPosition_;
checkEof(); checkEof();
return *this; return *this;
} }

View File

@ -80,7 +80,7 @@ class UIPstream
//- Read a T from the transfer buffer //- Read a T from the transfer buffer
template<class T> template<class T>
inline void readFromBuffer(T& t); inline void readFromBuffer(T& val);
//- Read count bytes of data from the transfer buffer //- Read count bytes of data from the transfer buffer
// using align byte alignment // using align byte alignment

View File

@ -109,7 +109,7 @@ inline void Foam::UOPstream::writeStringToBuffer(const std::string& str)
{ {
const size_t len = str.size(); const size_t len = str.size();
writeToBuffer(len); writeToBuffer(len);
writeToBuffer(str.c_str(), len + 1, 1); writeToBuffer(str.data(), len, 1);
} }