node: Extending processEvents API to allow processing thread management flexibility
The application now can request that the processing thread exists even
if there are no events to process. Face::shutdown need to be called to
terminate thread processing.
Change-Id: I2973d088edbb3765b6f33cb1324055b9dc2c50ec
diff --git a/include/ndn-cpp/face.hpp b/include/ndn-cpp/face.hpp
index 4071501..e006458 100644
--- a/include/ndn-cpp/face.hpp
+++ b/include/ndn-cpp/face.hpp
@@ -161,17 +161,21 @@
* This call will block forever (default timeout == 0) to process IO on the face.
* To exit, one expected to call face.shutdown() from one of the callback methods.
*
- * If timeout is specified, then processEvents will exit after this timeout, if not stopped earlier with face.shutdown().
+ * If positive timeout is specified, then processEvents will exit after this timeout,
+ * if not stopped earlier with face.shutdown() or when all active events finish.
* The call can be called repeatedly, if desired.
*
+ * If negative timeout is specified, then processEvents will not block and process only pending
+ * events.
+ *
* @throw This may throw an exception for reading data or in the callback for processing the data. If you
* call this from an main event loop, you may want to catch and log/disregard all exceptions.
*/
void
- processEvents(Milliseconds timeout = 0)
+ processEvents(Milliseconds timeout = 0, bool keepThread = false)
{
// Just call Node's processEvents.
- node_.processEvents(timeout);
+ node_.processEvents(timeout, keepThread);
}
/**
diff --git a/include/ndn-cpp/node.hpp b/include/ndn-cpp/node.hpp
index b28e91d..bbf89fd 100644
--- a/include/ndn-cpp/node.hpp
+++ b/include/ndn-cpp/node.hpp
@@ -126,14 +126,18 @@
* This call will block forever (default timeout == 0) to process IO on the face.
* To exit, one expected to call face.shutdown() from one of the callback methods.
*
- * If timeout is specified, then processEvents will exit after this timeout, if not stopped earlier with face.shutdown().
+ * If positive timeout is specified, then processEvents will exit after this timeout,
+ * if not stopped earlier with face.shutdown() or when all active events finish.
* The call can be called repeatedly, if desired.
*
+ * If negative timeout is specified, then processEvents will not block and process only pending
+ * events.
+ *
* @throw This may throw an exception for reading data or in the callback for processing the data. If you
* call this from an main event loop, you may want to catch and log/disregard all exceptions.
*/
void
- processEvents(Milliseconds timeout = 0);
+ processEvents(Milliseconds timeout = 0, bool keepThread = false);
const ptr_lib::shared_ptr<Transport>&
getTransport() { return transport_; }
@@ -316,6 +320,7 @@
private:
ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
+ ptr_lib::shared_ptr<boost::asio::io_service::work> ioServiceWork_; // needed if thread needs to be preserved
ptr_lib::shared_ptr<boost::asio::deadline_timer> pitTimeoutCheckTimer_;
bool pitTimeoutCheckTimerActive_;
ptr_lib::shared_ptr<boost::asio::deadline_timer> processEventsTimeoutTimer_;
diff --git a/src/node.cpp b/src/node.cpp
index dcbcf84..5dcbd7b 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -224,21 +224,34 @@
}
void
-Node::processEvents(Milliseconds timeout/* = 0 */)
+Node::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
{
- if (timeout > 0)
- {
- processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
- processEventsTimeoutTimer_->async_wait(fireProcessEventsTimeout);
- }
try
{
+ if (timeout < 0)
+ {
+ // do not block if timeout is negative, but process pending events
+ ioService_->poll();
+ return;
+ }
+
+ if (timeout > 0)
+ {
+ processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
+ processEventsTimeoutTimer_->async_wait(fireProcessEventsTimeout);
+ }
+
+ if (keepThread) {
+ // work will ensure that ioService_ is running until work object exists
+ ioServiceWork_ = ptr_lib::make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
+ }
+
ioService_->run();
- ioService_->reset();
}
catch(Node::ProcessEventsTimeout &)
{
// break
+ ioService_->reset();
}
}
@@ -276,7 +289,9 @@
if (registeredPrefixTable_.empty()) {
transport_->close();
- processEventsTimeoutTimer_->cancel();
+ if (!ioServiceWork_) {
+ processEventsTimeoutTimer_->cancel();
+ }
}
}
}
@@ -318,6 +333,9 @@
pitTimeoutCheckTimer_->cancel();
processEventsTimeoutTimer_->cancel();
pitTimeoutCheckTimerActive_ = false;
+
+ // This will ensure that io_service::work will stop
+ ioServiceWork_.reset();
}
Node::PendingInterestTable::iterator