Kaynağa Gözat

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 9 yıl önce
ebeveyn
işleme
93ae8221dc
2 değiştirilmiş dosya ile 73 ekleme ve 8 silme
  1. 56
    4
      child.cpp
  2. 17
    4
      child.hpp

+ 56
- 4
child.cpp Dosyayı Görüntüle

@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/select.h>
#include <cstring>
#include <cerrno>
@@ -77,6 +78,13 @@ namespace CodeDweller {
exitCode = 0;
}
size_t
Child::numBytesAvailable() const {
return readStreambuf.numBytesAvailable();
}
void
Child::run() {
@@ -219,7 +227,7 @@ namespace CodeDweller {
throw std::runtime_error("Error creating pipe for stdin: " +
getErrorText());
}
if (pipe(childStdOutPipe, O_NONBLOCK) != 0) {
if (pipe(childStdOutPipe) != 0) {
close(childStdInPipe[0]);
close(childStdInPipe[1]);
throw std::runtime_error("Error creating pipe for stdout: " +
@@ -487,9 +495,34 @@ namespace CodeDweller {
}
#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
Child::ReadStreambuf::underflow() {
std::cout << "underflow()." << std::endl; // debug
// Check for empty buffer.
if (gptr() < egptr()) {
@@ -497,7 +530,7 @@ namespace CodeDweller {
return traits_type::to_int_type(*gptr());
}
std::cout << "need to fill buffer." << std::endl; // debug
// Need to fill the buffer.
char *base = &(buffer.front());
char *start = base;
@@ -523,10 +556,18 @@ namespace CodeDweller {
}
#else
ssize_t nBytesRead;
std::cout << "Requesting read of " << buffer.size() - (start - base)
<< " bytes" << std::endl; // debug
nBytesRead = read(inputFileDescriptor,
start,
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) {
return traits_type::eof();
}
@@ -540,6 +581,8 @@ namespace CodeDweller {
// Update buffer pointers.
setg(base, start, start + nBytesRead);
std::cout << "underflow() return." << std::endl; // debug
return traits_type::to_int_type(*gptr());
}
@@ -598,6 +641,15 @@ namespace CodeDweller {
ssize_t nBytesWritten;
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

+ 17
- 4
child.hpp Dosyayı Görüntüle

@@ -65,6 +65,8 @@ namespace CodeDweller {
/// process.
class ReadStreambuf : public std::streambuf {

friend class Child;

public:

/// Reader streambuf constructor.
@@ -94,12 +96,23 @@ namespace CodeDweller {

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().
int_type underflow();

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

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

@@ -231,7 +244,7 @@ namespace CodeDweller {
blocking.

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

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

Loading…
İptal
Kaydet