BIND 10 trac2875, updated. c3c72a61ea2c2b9c609b6994a2f3482976de58dd [2875] Extract the coroutine scheduler to separate file

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jul 19 11:03:32 UTC 2013


The branch, trac2875 has been updated
       via  c3c72a61ea2c2b9c609b6994a2f3482976de58dd (commit)
      from  e83975b40b2c17297baf0e4a0fa44490dab17cd8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit c3c72a61ea2c2b9c609b6994a2f3482976de58dd
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Fri Jul 19 13:01:50 2013 +0200

    [2875] Extract the coroutine scheduler to separate file
    
    As it will be used by the layered experiment, the coroutine scheduler is
    extracted to separate file. It is not long, but the code is somewhat
    complex.

-----------------------------------------------------------------------

Summary of changes:
 src/bin/resolver/bench/Makefile.am           |    1 +
 src/bin/resolver/bench/coroutine_resolver.cc |   65 +--------------------
 src/bin/resolver/bench/scheduler.cc          |   81 ++++++++++++++++++++++++++
 src/bin/resolver/bench/scheduler.h           |   51 ++++++++++++++++
 4 files changed, 136 insertions(+), 62 deletions(-)
 create mode 100644 src/bin/resolver/bench/scheduler.cc
 create mode 100644 src/bin/resolver/bench/scheduler.h

-----------------------------------------------------------------------
diff --git a/src/bin/resolver/bench/Makefile.am b/src/bin/resolver/bench/Makefile.am
index 1aeaa32..468fb48 100644
--- a/src/bin/resolver/bench/Makefile.am
+++ b/src/bin/resolver/bench/Makefile.am
@@ -27,6 +27,7 @@ resolver_bench_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
 if BOOST_COROUTINES
 # The coroutine resolver needs the boost coroutines. Enable it only if available.
 resolver_bench_SOURCES += coroutine_resolver.h coroutine_resolver.cc
+resolver_bench_SOURCES += scheduler.h scheduler.cc
 resolver_bench_LDADD += -lboost_context
 AM_CPPFLAGS += -DBOOST_COROUTINES
 endif
diff --git a/src/bin/resolver/bench/coroutine_resolver.cc b/src/bin/resolver/bench/coroutine_resolver.cc
index 11738d9..c840945 100644
--- a/src/bin/resolver/bench/coroutine_resolver.cc
+++ b/src/bin/resolver/bench/coroutine_resolver.cc
@@ -13,12 +13,12 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <resolver/bench/coroutine_resolver.h>
+#include <resolver/bench/scheduler.h>
 
 #include <util/threads/thread.h>
 
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
-#include <boost/coroutine/all.hpp>
 
 using isc::util::thread::Thread;
 using isc::util::thread::Mutex;
@@ -46,17 +46,6 @@ CoroutineResolver::~CoroutineResolver() {
 
 namespace {
 
-// This is the callback passed to the AsyncWork. It'll be provided by
-// the scheduler and it will restore the coroutine.
-typedef boost::function<void()> SimpleCallback;
-// A bit of asynchronous work to be performed. The coroutine will
-// return this functor to the scheduler. The scheduler will execute
-// it and pass it a callback that should be executed once the work
-// is done, to reschedule.
-typedef boost::function<void(SimpleCallback)> AsyncWork;
-// A single coroutine, doing some work.
-typedef boost::coroutines::coroutine<AsyncWork()> Coroutine;
-
 void
 doneTask(bool* flag) {
     *flag = true;
@@ -106,60 +95,12 @@ void handleQuery(FakeQueryPtr query, Mutex* cache_mutex, Mutex* upstream_mutex,
     }
 }
 
-void
-handleCoroutine(Coroutine* cor, size_t* outstanding);
-
-void
-resumeCoroutine(Coroutine* cor, size_t* outstanding)
-{
-    // The coroutine is ready to run again. So do so.
-    (*cor)();
-    // Coroutine returned to us again. Check if it is still alive.
-    // This is not true recursion (with handleCoroutine) -- we call
-    // handleCoroutine, but that one does not call us directly, it
-    // schedules it trought the main loop. So the handleCoroutine
-    // that scheduled us is no longer on stack, so there's no risk
-    // of stack overflow.
-    handleCoroutine(cor, outstanding);
-}
-
-void
-handleCoroutine(Coroutine* cor, size_t* outstanding)
-{
-    if (*cor) {
-        // The coroutine is still alive. That means it returned some
-        // work to be done asynchronously, we need to schedule it.
-
-        // The return value of get() is a functor to be called with
-        // a callback to reschedule the coroutine once the work is done.
-        cor->get()(boost::bind(&resumeCoroutine, cor, outstanding));
-    } else {
-        // The coroutine terminated, the query is handled.
-        delete cor;
-        --*outstanding;
-    }
-}
-
 }
 
 void
 CoroutineResolver::run_instance(FakeInterface* interface) {
-    FakeQueryPtr query;
-    size_t outstanding = 0;
-    // Receive the queries and create coroutines for them.
-    while ((query = interface->receiveQuery())) {
-        ++outstanding;
-        // Create the coroutine and run the first part.
-        Coroutine *cor = new Coroutine(boost::bind(&handleQuery, query,
-                                                   &cache_mutex_,
-                                                   &upstream_mutex_, _1));
-        // Returned from the coroutine.
-        handleCoroutine(cor, &outstanding);
-    }
-    // Wait for all the queries to complete
-    while (outstanding > 0) {
-        interface->processEvents();
-    }
+    coroutineScheduler(boost::bind(&handleQuery, _1, &cache_mutex_,
+                                   &upstream_mutex_, _2), *interface);
 }
 
 size_t
diff --git a/src/bin/resolver/bench/scheduler.cc b/src/bin/resolver/bench/scheduler.cc
new file mode 100644
index 0000000..b556c79
--- /dev/null
+++ b/src/bin/resolver/bench/scheduler.cc
@@ -0,0 +1,81 @@
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <resolver/bench/scheduler.h>
+
+#include <boost/bind.hpp>
+
+namespace isc {
+namespace resolver {
+namespace bench {
+
+namespace {
+
+void
+handleCoroutine(Coroutine* cor, size_t* outstanding);
+
+void
+resumeCoroutine(Coroutine* cor, size_t* outstanding)
+{
+    // The coroutine is ready to run again. So do so.
+    (*cor)();
+    // Coroutine returned to us again. Check if it is still alive.
+    // This is not true recursion (with handleCoroutine) -- we call
+    // handleCoroutine, but that one does not call us directly, it
+    // schedules it trought the main loop. So the handleCoroutine
+    // that scheduled us is no longer on stack, so there's no risk
+    // of stack overflow.
+    handleCoroutine(cor, outstanding);
+}
+
+void
+handleCoroutine(Coroutine* cor, size_t* outstanding)
+{
+    if (*cor) {
+        // The coroutine is still alive. That means it returned some
+        // work to be done asynchronously, we need to schedule it.
+
+        // The return value of get() is a functor to be called with
+        // a callback to reschedule the coroutine once the work is done.
+        cor->get()(boost::bind(&resumeCoroutine, cor, outstanding));
+    } else {
+        // The coroutine terminated, the query is handled.
+        delete cor;
+        --*outstanding;
+    }
+}
+
+}
+
+void
+coroutineScheduler(const QueryHandler& handler, FakeInterface& interface) {
+    FakeQueryPtr query;
+    size_t outstanding = 0;
+    // Receive the queries and create coroutines for them.
+    while ((query = interface.receiveQuery())) {
+        ++outstanding;
+        // Create the coroutine and run the first part.
+        Coroutine *cor = new Coroutine(boost::bind(handler, query, _1));
+        // Returned from the coroutine.
+        handleCoroutine(cor, &outstanding);
+    }
+    // Wait for all the queries to complete
+    while (outstanding > 0) {
+        interface.processEvents();
+    }
+}
+
+}
+}
+}
diff --git a/src/bin/resolver/bench/scheduler.h b/src/bin/resolver/bench/scheduler.h
new file mode 100644
index 0000000..2e0b4c5
--- /dev/null
+++ b/src/bin/resolver/bench/scheduler.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef RESOLVER_BENCH_SCHEDULER_H
+#define RESOLVER_BENCH_SCHEDULER_H
+
+#include <resolver/bench/fake_resolution.h>
+
+#include <boost/function.hpp>
+#include <boost/coroutine/all.hpp>
+
+namespace isc {
+namespace resolver {
+namespace bench {
+
+class FakeInterface;
+
+// This is the callback passed to the AsyncWork. It'll be provided by
+// the scheduler and it will restore the coroutine.
+typedef boost::function<void()> SimpleCallback;
+// A bit of asynchronous work to be performed. The coroutine will
+// return this functor to the scheduler. The scheduler will execute
+// it and pass it a callback that should be executed once the work
+// is done, to reschedule.
+typedef boost::function<void(SimpleCallback)> AsyncWork;
+// A single coroutine, doing some work.
+typedef boost::coroutines::coroutine<AsyncWork()> Coroutine;
+// Function to handle one query
+typedef boost::function<void(const FakeQueryPtr&, Coroutine::caller_type&)>
+    QueryHandler;
+
+// Run the coroutine scheduler, launch one coroutine on each query.
+void
+coroutineScheduler(const QueryHandler& handler, FakeInterface& interface);
+
+}
+}
+}
+
+#endif



More information about the bind10-changes mailing list