Browse Source

Testing non-blocking read.


git-svn-id: https://svn.microneil.com/svn/CodeDweller/branches/adeniz_1@54 d34b734f-a00e-4b39-a726-e4eeb87269ab
adeniz_1
adeniz 10 years ago
parent
commit
93ae8221dc
2 changed files with 73 additions and 8 deletions
  1. 56
    4
      child.cpp
  2. 17
    4
      child.hpp

+ 56
- 4
child.cpp View File

#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h> #include <signal.h>
#include <sys/select.h>
#include <cstring> #include <cstring>
#include <cerrno> #include <cerrno>
exitCode = 0; exitCode = 0;
} }
size_t
Child::numBytesAvailable() const {
return readStreambuf.numBytesAvailable();
}
void void
Child::run() { Child::run() {
throw std::runtime_error("Error creating pipe for stdin: " + throw std::runtime_error("Error creating pipe for stdin: " +
getErrorText()); getErrorText());
} }
if (pipe(childStdOutPipe, O_NONBLOCK) != 0) {
if (pipe(childStdOutPipe) != 0) {
close(childStdInPipe[0]); close(childStdInPipe[0]);
close(childStdInPipe[1]); close(childStdInPipe[1]);
throw std::runtime_error("Error creating pipe for stdout: " + throw std::runtime_error("Error creating pipe for stdout: " +
} }
#endif #endif
size_t
Child::ReadStreambuf::numBytesAvailable() const {
size_t nBytesAvailable = egptr() - gptr();
fd_set readFd;
int retVal;
struct timeval timeout = {0, 0};
FD_ZERO(&readFd);
FD_SET(inputFileDescriptor, &readFd);
// Check if input is available.
retVal = select(inputFileDescriptor + 1, &readFd, NULL, NULL, &timeout);
if (-1 == retVal) {
throw std::runtime_error("Error from select(): " + getErrorText());
} else if (retVal > 0) {
nBytesAvailable++;
}
return nBytesAvailable;
}
std::streambuf::int_type std::streambuf::int_type
Child::ReadStreambuf::underflow() { Child::ReadStreambuf::underflow() {
std::cout << "underflow()." << std::endl; // debug
// Check for empty buffer. // Check for empty buffer.
if (gptr() < egptr()) { if (gptr() < egptr()) {
return traits_type::to_int_type(*gptr()); return traits_type::to_int_type(*gptr());
} }
std::cout << "need to fill buffer." << std::endl; // debug
// Need to fill the buffer. // Need to fill the buffer.
char *base = &(buffer.front()); char *base = &(buffer.front());
char *start = base; char *start = base;
} }
#else #else
ssize_t nBytesRead; ssize_t nBytesRead;
std::cout << "Requesting read of " << buffer.size() - (start - base)
<< " bytes" << std::endl; // debug
nBytesRead = read(inputFileDescriptor, nBytesRead = read(inputFileDescriptor,
start, start,
buffer.size() - (start - base)); buffer.size() - (start - base));
// debug
std::cout << "nBytesRead: " << nBytesRead << std::endl; // debug
for (int i = 0; i < nBytesRead; i++) {
std::cout << (char) start[i];
}
std::cout << std::endl;
// end of debug
if (-1 == nBytesRead) { if (-1 == nBytesRead) {
return traits_type::eof(); return traits_type::eof();
} }
// Update buffer pointers. // Update buffer pointers.
setg(base, start, start + nBytesRead); setg(base, start, start + nBytesRead);
std::cout << "underflow() return." << std::endl; // debug
return traits_type::to_int_type(*gptr()); return traits_type::to_int_type(*gptr());
} }
ssize_t nBytesWritten; ssize_t nBytesWritten;
nBytesWritten = write(outputFileDescriptor, pbase(), nBytes); nBytesWritten = write(outputFileDescriptor, pbase(), nBytes);
// debug
std::cout << "flushBuffer(). Requested to write " << nBytes << " bytes, "
<<"wrote " << nBytesWritten << " bytes." << std::endl;
char *ch = pbase();
for (int i = 0; i < nBytesWritten; i++) {
std::cout << (char) ch[i];
}
std::cout << std::endl;
// end of debug.
#endif #endif

+ 17
- 4
child.hpp View File

/// process. /// process.
class ReadStreambuf : public std::streambuf { class ReadStreambuf : public std::streambuf {


friend class Child;

public: public:


/// Reader streambuf constructor. /// Reader streambuf constructor.


private: private:


/** Return the number of bytes that can be read without
blocking.

This method checks if any input is available from the pipe,
and returns the number of bytes in the input buffer plus 1.
Reading that number of bytes will not block. Reading a
larger number of bytes might block.

\returns minimum number of bytes that can be read without
blocking.

*/
size_t numBytesAvailable() const;

/// Override streambuf::underflow(). /// Override streambuf::underflow().
int_type underflow(); int_type underflow();


/// Fill the buffer.
//void fillBuffer();

/// Copy constructor not implemented. /// Copy constructor not implemented.
ReadStreambuf(const ReadStreambuf &); ReadStreambuf(const ReadStreambuf &);


blocking. blocking.


*/ */
ssize_t inputBytesAvailable();
size_t numBytesAvailable() const;


/// Output stream to write data to the child's standard input. /// Output stream to write data to the child's standard input.
std::ostream writer; std::ostream writer;

Loading…
Cancel
Save