ソースを参照

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年前
コミット
93ae8221dc
2個のファイルの変更73行の追加8行の削除
  1. 56
    4
      child.cpp
  2. 17
    4
      child.hpp

+ 56
- 4
child.cpp ファイルの表示

@@ -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 ファイルの表示

@@ -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;

読み込み中…
キャンセル
保存