cpp: TNonblockingServer: Allow unrun tasks to expire after a time limit
Enhance ThreadManager to allow a expiration time interval to be assigned
to tasks, and expire those tasks after that time limit has passed.
Enhance TNonblockingServer to utilize this capability so it can be used
for overload resilience.
Note: expired entries are only removed from the queue head, so the
mechanism in ThreadManager may not do what you expect if you have
heterogeneous expiration times. That's not an issue with
TNonblockingServer (which will give all tasks the same limit) and might
not be in other cases where most tasks have the same limit and the rest
execute quickly. A full-up timeout queue would be more complex and have
greater overhead than that used here. It's unnecessary for the task at
hand so I didn't go that route...
The TNonblocking interface is simple: a setTaskExpireTime() accepts a
64-bit millisecond argument. 0 means infinite. A getTaskExpireTime()
accessor completes the interface.
The ThreadManager interface involves an added argument to add() for the
expiration interval and a setExpireCallback() function for setting a
callback that is called for expired tasks (for this project this is
necessary to shut down the associated connection).
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@920673 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/concurrency/ThreadManager.h b/lib/cpp/src/concurrency/ThreadManager.h
index cbf08c0..95c4906 100644
--- a/lib/cpp/src/concurrency/ThreadManager.h
+++ b/lib/cpp/src/concurrency/ThreadManager.h
@@ -21,6 +21,7 @@
#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1
#include <boost/shared_ptr.hpp>
+#include <tr1/functional>
#include <sys/types.h>
#include "Thread.h"
@@ -56,6 +57,9 @@
ThreadManager() {}
public:
+ class Task;
+ typedef std::tr1::function<void(boost::shared_ptr<Runnable>)> ExpireCallback;
+
virtual ~ThreadManager() {}
/**
@@ -125,6 +129,11 @@
virtual size_t pendingTaskCountMax() const = 0;
/**
+ * Gets the number of tasks which have been expired without being run.
+ */
+ virtual size_t expiredTaskCount() = 0;
+
+ /**
* Adds a task to be executed at some time in the future by a worker thread.
*
* This method will block if pendingTaskCountMax() in not zero and pendingTaskCount()
@@ -138,10 +147,14 @@
* is specified. Specific cases:
* timeout = 0 : Wait forever to queue task.
* timeout = -1 : Return immediately if pending task count exceeds specified max
+ * @param expiration when nonzero, the number of milliseconds the task is valid
+ * to be run; if exceeded, the task will be dropped off the queue and not run.
*
* @throws TooManyPendingTasksException Pending task count exceeds max pending task count
*/
- virtual void add(boost::shared_ptr<Runnable>task, int64_t timeout=0LL) = 0;
+ virtual void add(boost::shared_ptr<Runnable>task,
+ int64_t timeout=0LL,
+ int64_t expiration=0LL) = 0;
/**
* Removes a pending task
@@ -155,6 +168,19 @@
*/
virtual boost::shared_ptr<Runnable> removeNextPending() = 0;
+ /**
+ * Remove tasks from front of task queue that have expired.
+ */
+ virtual void removeExpiredTasks() = 0;
+
+ /**
+ * Set a callback to be called when a task is expired and not run.
+ *
+ * @param expireCallback a function called with the shared_ptr<Runnable> for
+ * the expired task.
+ */
+ virtual void setExpireCallback(ExpireCallback expireCallback) = 0;
+
static boost::shared_ptr<ThreadManager> newThreadManager();
/**