[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