[Aptitude-svn-commit] r4033 - in branches/aptitude-0.3/aptitude: . src/generic tests

Daniel Burrows dburrows at costa.debian.org
Thu Sep 1 22:11:27 UTC 2005


Author: dburrows
Date: Thu Sep  1 22:11:24 2005
New Revision: 4033

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/generic/event_queue.h
   branches/aptitude-0.3/aptitude/src/generic/threads.h
   branches/aptitude-0.3/aptitude/tests/test_threads.cc
Log:
Add support for timed waits

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Thu Sep  1 22:11:24 2005
@@ -1,5 +1,9 @@
 2005-09-01  Daniel Burrows  <dburrows at debian.org>
 
+	* src/generic/event_queue.h, src/generic/threads.h, tests/test_threads.cc:
+
+	  Add support for timed waits.
+
 	* src/generic/event_queue.h, tests/test_threads.cc:
 
 	  Write a simple event queue abstraction.

Modified: branches/aptitude-0.3/aptitude/src/generic/event_queue.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/event_queue.h	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/event_queue.h	Thu Sep  1 22:11:24 2005
@@ -1,4 +1,4 @@
-// channel.h
+// channel.h                                              -*-c++-*-
 //
 //   Copyright (C) 2005 Daniel Burrows
 //
@@ -116,6 +116,23 @@
 	}
     }
 
+    /** Retrieve a single value from the event queue, or fail if the
+     *  time "until" is reached.
+     */
+    bool timed_get(T &out, const timespec &until)
+    {
+      mutex::lock l(m);
+
+      if(c.timed_wait(l, until, not_empty(q)))
+	{
+	  out = q.front();
+	  q.pop_front();
+	  return true;
+	}
+      else
+	return false;
+    }
+
     /** Return \b true if the event queue is currently empty. */
     bool empty() const
     {

Modified: branches/aptitude-0.3/aptitude/src/generic/threads.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/threads.h	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/threads.h	Thu Sep  1 22:11:24 2005
@@ -25,6 +25,7 @@
 #ifndef THREADS_H
 #define THREADS_H
 
+#include <errno.h>
 #include "exception.h"
 
 namespace threads
@@ -383,6 +384,48 @@
       while(!p())
 	wait(l);
     }
+
+    /** Wait until either the condition is signalled or until the
+     *  given time.
+     *
+     *  \param l the guard of the condition
+     *  \param until the time at which the wait should terminate
+     *
+     *  \return \b true if the condition occurred or \b false if time
+     *                  ran out.
+     */
+    template<typename Lock>
+    bool timed_wait(const Lock &l, const timespec &until)
+    {
+      if(!l.get_locked())
+	throw ConditionNotLockedException();
+
+      int rval;
+
+      // Ignore EINTR for the time being.
+      while((rval = pthread_cond_timedwait(&cond, &l.parent.m, &until)) == EINTR)
+	;
+
+      return rval != ETIMEDOUT;
+    }
+
+    /** Wait either until the condition is signalled while the given
+     *  predicate is \b true or until the given time.
+     */
+    template<typename Lock, typename Pred>
+    bool timed_wait(const Lock &l, const timespec &until, const Pred &p)
+    {
+      if(!l.get_locked())
+	throw ConditionNotLockedException();
+
+      while(!p())
+	{
+	  if(!timed_wait(l, until))
+	    return false;
+	}
+
+      return true;
+    }
   };
 
   /** A higher-level abstraction borrowed from Concurrent Haskell,
@@ -445,6 +488,16 @@
      */
     bool try_put(const T &t);
 
+    /** As try_take(), but wait for the given amount of time before
+     *  giving up.
+     */
+    bool timed_take(T &out, const timespec &until);
+
+    /** As try_put(), but wait for the given amount of time before
+     *  giving up.
+     */
+    bool timed_put(const T &t, const timespec &until);
+
     /** Atomically modify the contents of the box; if an exception is
      *  thrown by the given function object, no action will be
      *  performed.
@@ -492,8 +545,6 @@
 
     cond.wait(l, bool_ref_pred(filled));
 
-    assert(filled);
-
     filled = false;
 
     // Interesting question: does l get released before or after the
@@ -518,6 +569,21 @@
   }
 
   template<typename T>
+  bool box<T>::timed_take(T &out, const timespec &until)
+  {
+    mutex::lock l(m);
+
+    if(cond.timed_wait(l, until, bool_ref_pred(filled)))
+      {
+	filled = false;
+	out = val;
+	return true;
+      }
+    else
+      return false;
+  }
+
+  template<typename T>
   void box<T>::put(const T &new_val)
   {
     mutex::lock l(m);
@@ -546,6 +612,22 @@
   }
 
   template<typename T>
+  bool box<T>::timed_put(const T &new_val, const timespec &until)
+  {
+    mutex::lock l(m);
+
+    if(cond.timed_wait(l, until, not_bool_ref_pred(filled)))
+      {
+	filled = true;
+	val = new_val;
+	cond.wake_one();
+	return true;
+      }
+    else
+      return false;
+  }
+
+  template<typename T>
   template<typename Mutator>
   void box<T>::update(const Mutator &m)
   {

Modified: branches/aptitude-0.3/aptitude/tests/test_threads.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/tests/test_threads.cc	(original)
+++ branches/aptitude-0.3/aptitude/tests/test_threads.cc	Thu Sep  1 22:11:24 2005
@@ -24,11 +24,15 @@
 
 #include <iostream>
 
+#include <sys/time.h>
+#include <time.h>
+
 class TestThreads : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE(TestThreads);
 
   CPPUNIT_TEST(testBox);
+  CPPUNIT_TEST(testTimedTake);
   CPPUNIT_TEST(testEventQueue);
   CPPUNIT_TEST(testAutoDetach);
 
@@ -91,6 +95,35 @@
       }
   }
 
+  void testTimedTake()
+  {
+    timeval now;
+
+    threads::box<int> b;
+
+    gettimeofday(&now, NULL);
+    timespec timeout;
+    timeout.tv_sec = now.tv_sec + 2;
+    timeout.tv_nsec = now.tv_usec * 1000;
+
+    int dummy;
+
+    CPPUNIT_ASSERT(!b.timed_take(dummy, timeout));
+
+    timeval now2;
+    gettimeofday(&now2, NULL);
+
+    CPPUNIT_ASSERT(now2.tv_sec >= now.tv_sec + 2);
+    CPPUNIT_ASSERT(now2.tv_sec > now.tv_sec + 2 || now2.tv_usec >= now.tv_usec);
+
+
+    timeout.tv_sec = now2.tv_sec + 2;
+    timeout.tv_nsec = now2.tv_usec * 1000;
+    b.put(5);
+    CPPUNIT_ASSERT(b.timed_take(dummy, timeout));
+    CPPUNIT_ASSERT_EQUAL(5, dummy);
+  }
+
   class event_queue_write_thread
   {
     threads::event_queue<std::pair<int, int> > &eq;



More information about the Aptitude-svn-commit mailing list