Permalink
Browse files

Add timeout support to the blocking version of gatheredWrite().

  • Loading branch information...
1 parent 7d85576 commit c885c3956bb216b9333b32c20160895ec960c0d2 @FooBarWidget FooBarWidget committed Aug 3, 2011
Showing with 35 additions and 3 deletions.
  1. +4 −1 ext/common/Utils/IOUtils.cpp
  2. +10 −1 ext/common/Utils/IOUtils.h
  3. +21 −1 test/cxx/IOUtilsTest.cpp
@@ -860,14 +860,17 @@ eraseBeginningOfIoVec(struct iovec *iov, size_t count, size_t index, size_t offs
}
void
-gatheredWrite(int fd, const StaticString data[], unsigned int count) {
+gatheredWrite(int fd, const StaticString data[], unsigned int count, unsigned long long *timeout) {
struct iovec iov[count];
size_t total, iovCount;
size_t written = 0;
total = staticStringArrayToIoVec(data, count, iov, iovCount);
while (written < total) {
+ if (timeout != NULL && !waitUntilWritable(fd, timeout)) {
+ throw TimeoutException("Cannot write enough data within the specified timeout");
+ }
ssize_t ret = writevFunction(fd, iov, std::min(iovCount, (size_t) IOV_MAX));
if (ret == -1) {
int e = errno;
View
@@ -345,10 +345,19 @@ ssize_t gatheredWrite(int fd, const StaticString data[], unsigned int dataCount,
* @param fd The file descriptor to write to.
* @param data An array of buffers to be written.
* @param count Number of items in <em>data</em>.
+ * @param timeout A pointer to an integer, which specifies the maximum number of
+ * microseconds that may be spent on writing all the data.
+ * If the timeout expired then TimeoutException will be thrown.
+ * If this function returns without throwing an exception, then the
+ * total number of microseconds spent on writing will be deducted
+ * from <tt>timeout</tt>.
+ * Pass NULL if you do not want to enforce a timeout.
* @throws SystemException Something went wrong.
+ * @throws TimeoutException Unable to write all given data within
+ * <tt>timeout</tt> microseconds.
* @throws boost::thread_interrupted
*/
-void gatheredWrite(int fd, const StaticString data[], unsigned int dataCount);
+void gatheredWrite(int fd, const StaticString data[], unsigned int dataCount, unsigned long long *timeout = NULL);
/**
* Sets a writev-emulating function that gatheredWrite() should call instead of the real writev().
View
@@ -1,5 +1,6 @@
#include "TestSupport.h"
-#include "Utils/IOUtils.h"
+#include <Utils/IOUtils.h>
+#include <Utils/SystemTime.h>
#include <oxt/system_calls.hpp>
#include <boost/bind.hpp>
#include <sys/types.h>
@@ -485,6 +486,25 @@ namespace tut {
ensure_equals(writevData, "hellomyworld!!");
}
+ TEST_METHOD(45) {
+ // Test writev() timeout support.
+ setWritevFunction(NULL);
+ Pipe p = createPipe();
+ unsigned long long startTime = SystemTime::getUsec();
+ unsigned long long timeout = 30000;
+ try {
+ StaticString data[] = { "hello", "world" };
+ for (int i = 0; i < 1024 * 1024; i++) {
+ gatheredWrite(p[1], data, 2, &timeout);
+ }
+ fail("TimeoutException expected");
+ } catch (const TimeoutException &) {
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
+ ensure("30 msec have passed", elapsed >= 29000 && elapsed <= 45000);
+ ensure(timeout <= 2000);
+ }
+ }
+
/***** Test waitUntilReadable() *****/
TEST_METHOD(50) {

0 comments on commit c885c39

Please sign in to comment.