From c5c9d83050872ecf3e0df0dbf8b7e0bf0ca26195 Mon Sep 17 00:00:00 2001 From: Benjamin Pflanz Date: Thu, 17 Jul 2014 16:24:27 -0400 Subject: [PATCH 01/12] Allow sleep to support std::chrono durations. --- mordor/sleep.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mordor/sleep.h b/mordor/sleep.h index 0457cbc9..67a636b1 100644 --- a/mordor/sleep.h +++ b/mordor/sleep.h @@ -2,6 +2,8 @@ #define __MORDOR_SLEEP_H__ // Copyright (c) 2009 - Mozy, Inc. +#include + namespace Mordor { class TimerManager; @@ -11,6 +13,14 @@ class TimerManager; /// @param us How long to sleep, in microseconds void sleep(unsigned long long us); +template +inline void sleep(std::chrono::duration duration) +{ + auto rescaled = std::chrono::duration_cast( + duration); + sleep(rescaled.count()); +} + /// Suspend execution of the current Fiber /// @note This will use the TimerManager to yield the current Fiber and allow /// other Fibers to run until this Fiber is ready to run again. @@ -20,6 +30,15 @@ void sleep(unsigned long long us); /// @pre Scheduler::getThis() != NULL void sleep(TimerManager &timerManager, unsigned long long us); +template +inline void sleep(TimerManager & timerManager, + std::chrono::duration duration) +{ + auto rescaled = std::chrono::duration_cast( + duration); + sleep(timerManager, rescaled.count()); +} + } #endif From c079ad30d0cd566382de4f08806aa24a9686dcc2 Mon Sep 17 00:00:00 2001 From: Benjamin Pflanz Date: Wed, 6 Aug 2014 16:16:10 -0400 Subject: [PATCH 02/12] Add boost dependencies to libs. --- Makefile.am | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index b0d3837c..20a9ef1a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -232,7 +232,9 @@ mordor_pq_libmordorpq_la_SOURCES= \ mordor_pq_libmordorpq_la_CPPFLAGS=-I$(top_srcdir) -include mordor/pch.h $(AM_CPPFLAGS) mordor_pq_libmordorpq_la_LDFLAGS=$(POSTGRESQL_LDFLAGS) -mordor_pq_libmordorpq_la_LIBADD=mordor/libmordor.la +mordor_pq_libmordorpq_la_LIBADD= \ + mordor/libmordor.la \ + $(BOOST_SYSTEM_LIB) if HAVE_PROTOBUF lib_LTLIBRARIES+=mordor/libmordorprotobuf.la @@ -314,7 +316,10 @@ mordor_test_libmordortest_la_SOURCES= \ mordor/test/stdoutlistener.cpp \ mordor/test/test.cpp -mordor_test_libmordortest_la_LIBADD=mordor/libmordor.la +mordor_test_libmordortest_la_LIBADD= \ + mordor/libmordor.la \ + $(BOOST_REGEX_LIB) \ + $(BOOST_SYSTEM_LIB) check_PROGRAMS=mordor/tests/run_tests mordor_tests_run_tests_SOURCES= \ @@ -433,7 +438,6 @@ mordor_examples_echoserver_LDADD=mordor/libmordor.la \ $(SYSTEMCONFIGURATION_FRAMEWORK_LIBS) \ $(BOOST_SYSTEM_LIB) \ $(BOOST_THREAD_LIB) - mordor_examples_iombench_SOURCES= \ mordor/examples/iombench.cpp \ From 19be25d93f5a9ea773652980f9513620630c1b18 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Tue, 2 Sep 2014 11:20:25 -0400 Subject: [PATCH 03/12] Accidentally was linking this to jemalloc before. --- Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index b0d3837c..56d8392e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -447,7 +447,6 @@ mordor_examples_iombench_LDADD=mordor/libmordor.la \ mordor_examples_simplehttpfileserver_SOURCES=mordor/examples/simplehttpfileserver.cpp mordor_examples_simplehttpfileserver_LDADD=mordor/libmordor.la \ - -ljemalloc \ $(BOOST_SYSTEM_LIB) \ $(BOOST_THREAD_LIB) \ $(CORESERVICES_FRAMEWORK_LIBS) \ From 6a0fbd6bf7df307eb7b1bb8a0d5efd5d65dac598 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Tue, 2 Sep 2014 13:01:54 -0400 Subject: [PATCH 04/12] Use relative paths for includes. endian.h on my system conflitcs with a system header. --- Makefile.am | 14 +++++++------- mordor/examples/udpstats.cpp | 8 ++++---- mordor/fiber.cpp | 2 +- mordor/http/http_parser.rl | 6 +++--- mordor/json.rl | 8 ++++---- mordor/pch.h | 2 +- mordor/pq/tests/pq.cpp | 30 +++++++++++++++--------------- mordor/streams/fd.cpp | 2 +- mordor/tests/file_stream.cpp | 6 +++--- mordor/tests/hmac.cpp | 6 +++--- mordor/tests/iomanager.cpp | 2 +- mordor/tests/run_tests.cpp | 14 +++++++------- mordor/tests/statistics.cpp | 4 ++-- mordor/tests/stream.cpp | 4 ++-- mordor/tests/timeout_stream.cpp | 12 ++++++------ mordor/tests/zlib.cpp | 20 ++++++++++---------- mordor/uri.rl | 5 ++--- mordor/xml/xml_parser.rl | 4 ++-- 18 files changed, 74 insertions(+), 75 deletions(-) diff --git a/Makefile.am b/Makefile.am index 56d8392e..562f34fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS=-I m4 AUTOMAKE_OPTIONS=nostdinc subdir-objects -AM_CPPFLAGS=$(OPENSSL_INCLUDES) $(BOOST_CPPFLAGS) $(POSTGRESQL_CFLAGS) $(INCICONV) $(VALGRIND_CPPFLAGS) -I$(top_srcdir) +AM_CPPFLAGS=$(OPENSSL_INCLUDES) $(BOOST_CPPFLAGS) $(POSTGRESQL_CFLAGS) $(INCICONV) $(VALGRIND_CPPFLAGS) AM_CXXFLAGS=-Wall -Werror -fno-strict-aliasing -std=c++11 nobase_include_HEADERS= \ @@ -193,7 +193,7 @@ mordor_libmordor_la_SOURCES= \ mordor/platform/cxa_exception.cpp \ mordor/platform/unix_fiber.cpp -mordor_libmordor_la_CPPFLAGS=-I$(top_srcdir) -include mordor/pch.h $(AM_CPPFLAGS) +mordor_libmordor_la_CPPFLAGS=-include mordor/pch.h $(AM_CPPFLAGS) mordor_libmordor_la_LDFLAGS= \ $(OPENSSL_LDFLAGS) \ $(BOOST_LDFLAGS) \ @@ -230,7 +230,7 @@ mordor_pq_libmordorpq_la_SOURCES= \ mordor/pq/result.cpp \ mordor/pq/transaction.cpp -mordor_pq_libmordorpq_la_CPPFLAGS=-I$(top_srcdir) -include mordor/pch.h $(AM_CPPFLAGS) +mordor_pq_libmordorpq_la_CPPFLAGS=-include mordor/pch.h $(AM_CPPFLAGS) mordor_pq_libmordorpq_la_LDFLAGS=$(POSTGRESQL_LDFLAGS) mordor_pq_libmordorpq_la_LIBADD=mordor/libmordor.la @@ -240,7 +240,7 @@ endif mordor_libmordorprotobuf_la_SOURCES=mordor/protobuf.cpp mordor_libmordorprotobuf_la_LDFLAGS=$(PROTOBUF_LIBS) -mordor_libmordorprotobuf_la_CPPFLAGS=-I$(top_srcdir) $(PROTOBUF_CFLAGS) $(AM_CPPFLAGS) +mordor_libmordorprotobuf_la_CPPFLAGS=$(PROTOBUF_CFLAGS) $(AM_CPPFLAGS) mordor_libmordorprotobuf_la_LIBADD=mordor/libmordor.la if HAVE_LIBYAML @@ -249,7 +249,7 @@ endif mordor_libmordoryaml_la_SOURCES=mordor/yaml.cpp mordor_libmordoryaml_la_LDFLAGS=$(LIBYAML) -mordor_libmordoryaml_la_CPPFLAGS=-I$(top_srcdir) $(AM_CPPFLAGS) +mordor_libmordoryaml_la_CPPFLAGS=$(AM_CPPFLAGS) mordor_libmordoryaml_la_LIBADD=mordor/libmordor.la if HAVE_LIBSSH2 @@ -261,7 +261,7 @@ mordor_libmordorssh_la_SOURCES= \ mordor/ssh/channel.cpp \ mordor/ssh/session.cpp mordor_libmordorssh_la_LDFLAGS=$(LIBSSH2) -mordor_libmordorssh_la_CPPFLAGS=-I$(top_srcdir) $(AM_CPPFLAGS) +mordor_libmordorssh_la_CPPFLAGS=$(AM_CPPFLAGS) mordor_libmordorssh_la_LIBADD=mordor/libmordor.la pkgconfigdir=$(libdir)/pkgconfig @@ -366,7 +366,7 @@ mordor_tests_run_tests_SOURCES= \ mordor/tests/zlib.cpp \ mordor/tests/crypto.cpp -mordor_tests_run_tests_CPPFLAGS=-I$(top_builddir) -include mordor/pch.h $(AM_CPPFLAGS) +mordor_tests_run_tests_CPPFLAGS=-include mordor/pch.h $(AM_CPPFLAGS) mordor_tests_run_tests_LDADD=mordor/libmordor.la mordor/test/libmordortest.la \ $(OPENSSL_LIBS) \ $(BOOST_THREAD_LIB) \ diff --git a/mordor/examples/udpstats.cpp b/mordor/examples/udpstats.cpp index 35dc59a6..4a4bbc52 100644 --- a/mordor/examples/udpstats.cpp +++ b/mordor/examples/udpstats.cpp @@ -4,10 +4,10 @@ #include -#include "mordor/config.h" -#include "mordor/iomanager.h" -#include "mordor/socket.h" -#include "mordor/statistics.h" +#include "../config.h" +#include "../iomanager.h" +#include "../socket.h" +#include "../statistics.h" using namespace Mordor; diff --git a/mordor/fiber.cpp b/mordor/fiber.cpp index 0839e29e..a27ba775 100644 --- a/mordor/fiber.cpp +++ b/mordor/fiber.cpp @@ -5,7 +5,7 @@ #include "fiber.h" #ifdef HAVE_CONFIG_H -#include "autoconfig.h" +#include "../autoconfig.h" #endif #ifdef HAVE_VALGRIND_VALGRIND_H diff --git a/mordor/http/http_parser.rl b/mordor/http/http_parser.rl index c6ab10d3..bfaa04ce 100644 --- a/mordor/http/http_parser.rl +++ b/mordor/http/http_parser.rl @@ -1,14 +1,14 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/pch.h" +#include "../pch.h" -#include "mordor/http/parser.h" +#include "parser.h" #include #include #include -#include "mordor/version.h" +#include "../version.h" namespace Mordor { diff --git a/mordor/json.rl b/mordor/json.rl index a8aab994..ab756b57 100644 --- a/mordor/json.rl +++ b/mordor/json.rl @@ -1,11 +1,11 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/pch.h" +#include "pch.h" -#include "mordor/json.h" +#include "json.h" -#include "mordor/assert.h" -#include "mordor/string.h" +#include "assert.h" +#include "string.h" namespace Mordor { namespace JSON { diff --git a/mordor/pch.h b/mordor/pch.h index 0d9c4f8e..5462b3e3 100644 --- a/mordor/pch.h +++ b/mordor/pch.h @@ -2,7 +2,7 @@ #define __MORDOR_PCH_H__ #ifdef HAVE_CONFIG_H -#include "autoconfig.h" +#include "../autoconfig.h" #endif #include "version.h" diff --git a/mordor/pq/tests/pq.cpp b/mordor/pq/tests/pq.cpp index 6ea4ca8c..6ffa84ef 100644 --- a/mordor/pq/tests/pq.cpp +++ b/mordor/pq/tests/pq.cpp @@ -1,25 +1,25 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../../predef.h" #include #include -#include "mordor/config.h" -#include "mordor/fibersynchronization.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/pq/connection.h" -#include "mordor/pq/exception.h" -#include "mordor/pq/transaction.h" -#include "mordor/version.h" -#include "mordor/statistics.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/transfer.h" -#include "mordor/test/antxmllistener.h" -#include "mordor/test/test.h" -#include "mordor/test/stdoutlistener.h" +#include "../../config.h" +#include "../../fibersynchronization.h" +#include "../../iomanager.h" +#include "../../main.h" +#include "../../pq/connection.h" +#include "../../pq/exception.h" +#include "../../pq/transaction.h" +#include "../../version.h" +#include "../../statistics.h" +#include "../../streams/memory.h" +#include "../../streams/transfer.h" +#include "../../test/antxmllistener.h" +#include "../../test/test.h" +#include "../../test/stdoutlistener.h" using namespace Mordor; using namespace Mordor::PQ; diff --git a/mordor/streams/fd.cpp b/mordor/streams/fd.cpp index 75955657..3bb4770d 100644 --- a/mordor/streams/fd.cpp +++ b/mordor/streams/fd.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/pch.h" +#include "../pch.h" #include "fd.h" diff --git a/mordor/tests/file_stream.cpp b/mordor/tests/file_stream.cpp index 2814cb75..8c644672 100644 --- a/mordor/tests/file_stream.cpp +++ b/mordor/tests/file_stream.cpp @@ -1,9 +1,9 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/pch.h" +#include "../pch.h" -#include "mordor/streams/file.h" -#include "mordor/test/test.h" +#include "../streams/file.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/hmac.cpp b/mordor/tests/hmac.cpp index 21ebaa3a..3f073ca2 100644 --- a/mordor/tests/hmac.cpp +++ b/mordor/tests/hmac.cpp @@ -1,7 +1,7 @@ -#include "mordor/pch.h" +#include "../pch.h" -#include "mordor/string.h" -#include "mordor/test/test.h" +#include "../string.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/iomanager.cpp b/mordor/tests/iomanager.cpp index cad90bc3..071627ff 100644 --- a/mordor/tests/iomanager.cpp +++ b/mordor/tests/iomanager.cpp @@ -96,7 +96,7 @@ namespace { class TickleAccessibleIOManager : public IOManager { public: - void tickle() { IOManager::tickle(); } + virtual void tickle() { IOManager::tickle(); } }; } diff --git a/mordor/tests/run_tests.cpp b/mordor/tests/run_tests.cpp index 2f837af4..7c182c6c 100644 --- a/mordor/tests/run_tests.cpp +++ b/mordor/tests/run_tests.cpp @@ -2,13 +2,13 @@ #include -#include "mordor/config.h" -#include "mordor/main.h" -#include "mordor/version.h" -#include "mordor/statistics.h" -#include "mordor/test/antxmllistener.h" -#include "mordor/test/compoundlistener.h" -#include "mordor/test/stdoutlistener.h" +#include "../config.h" +#include "../main.h" +#include "../version.h" +#include "../statistics.h" +#include "../test/antxmllistener.h" +#include "../test/compoundlistener.h" +#include "../test/stdoutlistener.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/statistics.cpp b/mordor/tests/statistics.cpp index 3bd47e59..eddbd0b2 100644 --- a/mordor/tests/statistics.cpp +++ b/mordor/tests/statistics.cpp @@ -1,5 +1,5 @@ -#include "mordor/statistics.h" -#include "mordor/test/test.h" +#include "../statistics.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/stream.cpp b/mordor/tests/stream.cpp index 2293209e..aaeb0879 100644 --- a/mordor/tests/stream.cpp +++ b/mordor/tests/stream.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/streams/stream.h" -#include "mordor/test/test.h" +#include "../streams/stream.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/timeout_stream.cpp b/mordor/tests/timeout_stream.cpp index bf068cd3..3c1b46ad 100644 --- a/mordor/tests/timeout_stream.cpp +++ b/mordor/tests/timeout_stream.cpp @@ -2,12 +2,12 @@ #include -#include "mordor/iomanager.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/delay.h" -#include "mordor/streams/pipe.h" -#include "mordor/streams/timeout.h" -#include "mordor/test/test.h" +#include "../iomanager.h" +#include "../streams/buffer.h" +#include "../streams/delay.h" +#include "../streams/pipe.h" +#include "../streams/timeout.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/zlib.cpp b/mordor/tests/zlib.cpp index a431868b..b037c188 100755 --- a/mordor/tests/zlib.cpp +++ b/mordor/tests/zlib.cpp @@ -1,18 +1,18 @@ -#include "mordor/pch.h" +#include "../pch.h" #ifdef HAVE_CONFIG_H -#include "autoconfig.h" +#include "../../autoconfig.h" #endif -#include "mordor/exception.h" +#include "../exception.h" -#include "mordor/streams/deflate.h" -#include "mordor/streams/gzip.h" -#include "mordor/streams/lzma2.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/singleplex.h" -#include "mordor/streams/zlib.h" -#include "mordor/test/test.h" +#include "../streams/deflate.h" +#include "../streams/gzip.h" +#include "../streams/lzma2.h" +#include "../streams/memory.h" +#include "../streams/singleplex.h" +#include "../streams/zlib.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/uri.rl b/mordor/uri.rl index 83d4aa7d..2df00175 100644 --- a/mordor/uri.rl +++ b/mordor/uri.rl @@ -3,9 +3,8 @@ ragel uri.rl -G2 -o uri.cpp */ -#include "mordor/pch.h" - -#include "mordor/uri.h" +#include "pch.h" +#include "uri.h" #include diff --git a/mordor/xml/xml_parser.rl b/mordor/xml/xml_parser.rl index fe616ffa..5149dc09 100644 --- a/mordor/xml/xml_parser.rl +++ b/mordor/xml/xml_parser.rl @@ -1,8 +1,8 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/pch.h" +#include "../pch.h" -#include "mordor/xml/parser.h" +#include "parser.h" using namespace Mordor; From 2c8401695196d1349b82a88b0baefc4a755a5f13 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Tue, 2 Sep 2014 13:37:15 -0400 Subject: [PATCH 05/12] Handy log message. --- mordor/examples/iombench.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mordor/examples/iombench.cpp b/mordor/examples/iombench.cpp index 7f5d52af..3bc5b6ad 100644 --- a/mordor/examples/iombench.cpp +++ b/mordor/examples/iombench.cpp @@ -303,6 +303,8 @@ MORDOR_MAIN(int argc, char *argv[]) NetBench bench(argc, argv); Config::loadFromEnvironment(); + + MORDOR_LOG_INFO(g_log) << "Running " << g_iomThreads->val() << " threads"; IOManager iom(g_iomThreads->val()); IOMBenchServer server(iom); From 2bc4f1603db19d73ce8828c07ed0d31c53ae63a4 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Tue, 2 Sep 2014 13:49:50 -0400 Subject: [PATCH 06/12] Squash me, relative path cleanup. --- mordor/examples/cat.cpp | 14 +++---- mordor/examples/decodebacktrace.cpp | 10 ++--- mordor/examples/echoserver.cpp | 22 +++++------ mordor/examples/iombench.cpp | 14 +++---- mordor/examples/netbench.cpp | 2 +- mordor/examples/simpleappserver.cpp | 18 ++++----- mordor/examples/simpleclient.cpp | 12 +++--- mordor/examples/simplehttpfileserver.cpp | 20 +++++----- mordor/examples/tunnel.cpp | 26 ++++++------ mordor/examples/udpstats.cpp | 2 +- mordor/examples/wget.cpp | 32 +++++++-------- mordor/http/auth.cpp | 4 +- mordor/http/auth.h | 2 +- mordor/http/basic.cpp | 2 +- mordor/http/broker.cpp | 20 +++++----- mordor/http/broker.h | 2 +- mordor/http/chunked.cpp | 6 +-- mordor/http/chunked.h | 4 +- mordor/http/client.cpp | 26 ++++++------ mordor/http/connection.cpp | 12 +++--- mordor/http/connection.h | 2 +- mordor/http/digest.cpp | 4 +- mordor/http/http.cpp | 2 +- mordor/http/http.h | 8 ++-- mordor/http/multipart.cpp | 12 +++--- mordor/http/negotiate.cpp | 4 +- mordor/http/oauth.cpp | 4 +- mordor/http/parser.h | 2 +- mordor/http/proxy.cpp | 24 ++++++------ mordor/http/proxy.h | 6 +-- mordor/http/server.cpp | 12 +++--- mordor/http/servlet.cpp | 2 +- mordor/http/servlet.h | 4 +- mordor/http/servlets/config.cpp | 16 ++++---- mordor/http/servlets/config.h | 2 +- mordor/log.cpp | 4 +- mordor/pq/connection.cpp | 8 ++-- mordor/pq/connectionpool.cpp | 10 ++--- mordor/pq/connectionpool.h | 2 +- mordor/pq/copy.cpp | 12 +++--- mordor/pq/exception.cpp | 4 +- mordor/pq/exception.h | 2 +- mordor/pq/preparedstatement.cpp | 10 ++--- mordor/pq/result.cpp | 8 ++-- mordor/pq/transaction.cpp | 4 +- mordor/protobuf.cpp | 4 +- mordor/socks.cpp | 6 +-- mordor/socks.h | 2 +- mordor/ssh/agent.cpp | 2 +- mordor/ssh/agent.h | 2 +- mordor/ssh/channel.cpp | 4 +- mordor/ssh/channel.h | 2 +- mordor/ssh/session.cpp | 8 ++-- mordor/streams/buffer.cpp | 4 +- mordor/streams/buffer.h | 2 +- mordor/streams/buffered.cpp | 6 +-- mordor/streams/cat.cpp | 2 +- mordor/streams/crypto.cpp | 4 +- mordor/streams/delay.h | 4 +- mordor/streams/efs.cpp | 6 +-- mordor/streams/fd.cpp | 4 +- mordor/streams/file.cpp | 4 +- mordor/streams/file.h | 2 +- mordor/streams/filter.cpp | 2 +- mordor/streams/handle.cpp | 6 +-- mordor/streams/handle.h | 2 +- mordor/streams/hash.cpp | 4 +- mordor/streams/http.cpp | 6 +-- mordor/streams/http.h | 6 +-- mordor/streams/limited.cpp | 2 +- mordor/streams/lzma2.cpp | 6 +-- mordor/streams/memory.cpp | 2 +- mordor/streams/namedpipe.cpp | 10 ++--- mordor/streams/null.h | 2 +- mordor/streams/pipe.cpp | 6 +-- mordor/streams/random.cpp | 4 +- mordor/streams/scheduler.h | 2 +- mordor/streams/singleplex.cpp | 2 +- mordor/streams/socket.cpp | 4 +- mordor/streams/ssl.cpp | 6 +-- mordor/streams/std.cpp | 2 +- mordor/streams/std.h | 2 +- mordor/streams/stream.cpp | 2 +- mordor/streams/stream.h | 2 +- mordor/streams/tee.cpp | 8 ++-- mordor/streams/temp.cpp | 4 +- mordor/streams/throttle.cpp | 8 ++-- mordor/streams/timeout.cpp | 10 ++--- mordor/streams/timeout.h | 2 +- mordor/streams/transfer.cpp | 12 +++--- mordor/streams/zero.h | 2 +- mordor/streams/zlib.cpp | 6 +-- mordor/streams/zlib.h | 2 +- mordor/string.cpp | 4 +- mordor/test/antxmllistener.cpp | 12 +++--- mordor/test/stdoutlistener.cpp | 4 +- mordor/test/test.cpp | 8 ++-- mordor/test/test.h | 2 +- mordor/tests/buffer.cpp | 4 +- mordor/tests/http_client.cpp | 50 ++++++++++++------------ mordor/tests/http_parser.cpp | 14 +++---- mordor/tests/iomanager.cpp | 10 ++--- mordor/tests/iomanager_iocp.cpp | 4 +- mordor/tests/pipe_stream.cpp | 16 ++++---- mordor/tests/ragel.cpp | 10 ++--- mordor/tests/rate_limiter.cpp | 8 ++-- mordor/tests/scheduler.cpp | 14 +++---- mordor/tests/socket.cpp | 10 ++--- mordor/tests/ssl_stream.cpp | 22 +++++------ mordor/tests/string.cpp | 4 +- mordor/tests/temp_stream.cpp | 4 +- mordor/tests/thread.cpp | 6 +-- mordor/tests/timer.cpp | 6 +-- mordor/tests/transfer_stream.cpp | 8 ++-- mordor/tests/unicode.cpp | 6 +-- mordor/tests/uri.cpp | 6 +-- mordor/tests/util.cpp | 4 +- mordor/tests/xml.cpp | 6 +-- mordor/uri.h | 2 +- mordor/xml/dom_parser.cpp | 4 +- mordor/xml/dom_parser.h | 4 +- mordor/xml/parser.h | 2 +- mordor/zip.cpp | 20 +++++----- 123 files changed, 447 insertions(+), 447 deletions(-) diff --git a/mordor/examples/cat.cpp b/mordor/examples/cat.cpp index 628ad29f..c1f5d83f 100644 --- a/mordor/examples/cat.cpp +++ b/mordor/examples/cat.cpp @@ -1,15 +1,15 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include -#include "mordor/config.h" -#include "mordor/main.h" -#include "mordor/streams/file.h" -#include "mordor/streams/std.h" -#include "mordor/streams/transfer.h" -#include "mordor/workerpool.h" +#include "../config.h" +#include "../main.h" +#include "../streams/file.h" +#include "../streams/std.h" +#include "../streams/transfer.h" +#include "../workerpool.h" using namespace Mordor; diff --git a/mordor/examples/decodebacktrace.cpp b/mordor/examples/decodebacktrace.cpp index d8361ff2..078e878d 100644 --- a/mordor/examples/decodebacktrace.cpp +++ b/mordor/examples/decodebacktrace.cpp @@ -1,15 +1,15 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include #include -#include "mordor/config.h" -#include "mordor/main.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/std.h" +#include "../config.h" +#include "../main.h" +#include "../streams/buffered.h" +#include "../streams/std.h" using namespace Mordor; diff --git a/mordor/examples/echoserver.cpp b/mordor/examples/echoserver.cpp index d679402e..9b784ac1 100644 --- a/mordor/examples/echoserver.cpp +++ b/mordor/examples/echoserver.cpp @@ -1,20 +1,20 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" -#include "mordor/config.h" -#include "mordor/daemon.h" -#include "mordor/http/multipart.h" -#include "mordor/http/server.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/socket.h" +#include "../config.h" +#include "../daemon.h" +#include "../http/multipart.h" +#include "../http/server.h" +#include "../iomanager.h" +#include "../main.h" +#include "../socket.h" #ifdef WINDOWS -#include "mordor/streams/namedpipe.h" +#include "../streams/namedpipe.h" #endif -#include "mordor/streams/socket.h" -#include "mordor/streams/transfer.h" +#include "../streams/socket.h" +#include "../streams/transfer.h" using namespace Mordor; diff --git a/mordor/examples/iombench.cpp b/mordor/examples/iombench.cpp index 3bc5b6ad..6ce90f91 100644 --- a/mordor/examples/iombench.cpp +++ b/mordor/examples/iombench.cpp @@ -4,7 +4,7 @@ // Can act as both the client and the server. // -#include "mordor/predef.h" +#include "../predef.h" #include "netbench.h" @@ -12,12 +12,12 @@ #include -#include "mordor/config.h" -#include "mordor/fibersynchronization.h" -#include "mordor/iomanager.h" -#include "mordor/log.h" -#include "mordor/main.h" -#include "mordor/socket.h" +#include "../config.h" +#include "../fibersynchronization.h" +#include "../iomanager.h" +#include "../log.h" +#include "../main.h" +#include "../socket.h" using namespace Mordor; diff --git a/mordor/examples/netbench.cpp b/mordor/examples/netbench.cpp index c9034737..3f9050a0 100644 --- a/mordor/examples/netbench.cpp +++ b/mordor/examples/netbench.cpp @@ -1,6 +1,6 @@ #include "netbench.h" -#include "mordor/version.h" +#include "../version.h" #include #ifndef WINDOWS diff --git a/mordor/examples/simpleappserver.cpp b/mordor/examples/simpleappserver.cpp index 463aae38..7a0a3792 100644 --- a/mordor/examples/simpleappserver.cpp +++ b/mordor/examples/simpleappserver.cpp @@ -1,17 +1,17 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include -#include "mordor/config.h" -#include "mordor/http/server.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/socket.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/socket.h" -#include "mordor/streams/transfer.h" +#include "../config.h" +#include "../http/server.h" +#include "../iomanager.h" +#include "../main.h" +#include "../socket.h" +#include "../streams/memory.h" +#include "../streams/socket.h" +#include "../streams/transfer.h" using namespace Mordor; diff --git a/mordor/examples/simpleclient.cpp b/mordor/examples/simpleclient.cpp index 6c195312..8b456da7 100644 --- a/mordor/examples/simpleclient.cpp +++ b/mordor/examples/simpleclient.cpp @@ -1,14 +1,14 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include -#include "mordor/config.h" -#include "mordor/fiber.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/socket.h" +#include "../config.h" +#include "../fiber.h" +#include "../iomanager.h" +#include "../main.h" +#include "../socket.h" using namespace Mordor; diff --git a/mordor/examples/simplehttpfileserver.cpp b/mordor/examples/simplehttpfileserver.cpp index 0e53557b..22c70940 100644 --- a/mordor/examples/simplehttpfileserver.cpp +++ b/mordor/examples/simplehttpfileserver.cpp @@ -1,19 +1,19 @@ -#include "mordor/predef.h" +#include "../predef.h" #include #include #include -#include "mordor/config.h" -#include "mordor/http/server.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/socket.h" -#include "mordor/streams/file.h" -#include "mordor/streams/socket.h" -#include "mordor/streams/transfer.h" -#include "mordor/streams/ssl.h" +#include "../config.h" +#include "../http/server.h" +#include "../iomanager.h" +#include "../main.h" +#include "../socket.h" +#include "../streams/file.h" +#include "../streams/socket.h" +#include "../streams/transfer.h" +#include "../streams/ssl.h" using namespace Mordor; diff --git a/mordor/examples/tunnel.cpp b/mordor/examples/tunnel.cpp index 1b4802af..8862759e 100644 --- a/mordor/examples/tunnel.cpp +++ b/mordor/examples/tunnel.cpp @@ -1,23 +1,23 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include #include namespace barg = std::placeholders; -#include "mordor/config.h" -#include "mordor/http/auth.h" -#include "mordor/http/client.h" -#include "mordor/http/proxy.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/socket.h" -#include "mordor/streams/duplex.h" -#include "mordor/streams/socket.h" -#include "mordor/streams/ssl.h" -#include "mordor/streams/std.h" -#include "mordor/streams/transfer.h" +#include "../config.h" +#include "../http/auth.h" +#include "../http/client.h" +#include "../http/proxy.h" +#include "../iomanager.h" +#include "../main.h" +#include "../socket.h" +#include "../streams/duplex.h" +#include "../streams/socket.h" +#include "../streams/ssl.h" +#include "../streams/std.h" +#include "../streams/transfer.h" using namespace Mordor; diff --git a/mordor/examples/udpstats.cpp b/mordor/examples/udpstats.cpp index 4a4bbc52..b5f57812 100644 --- a/mordor/examples/udpstats.cpp +++ b/mordor/examples/udpstats.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include diff --git a/mordor/examples/wget.cpp b/mordor/examples/wget.cpp index 1b661cef..79607d9c 100644 --- a/mordor/examples/wget.cpp +++ b/mordor/examples/wget.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include #include @@ -8,21 +8,21 @@ namespace barg = std::placeholders; #include -#include "mordor/config.h" -#include "mordor/exception.h" -#include "mordor/http/auth.h" -#include "mordor/http/broker.h" -#include "mordor/http/client.h" -#include "mordor/http/multipart.h" -#include "mordor/http/proxy.h" -#include "mordor/iomanager.h" -#include "mordor/main.h" -#include "mordor/sleep.h" -#include "mordor/socket.h" -#include "mordor/streams/socket.h" -#include "mordor/streams/ssl.h" -#include "mordor/streams/std.h" -#include "mordor/streams/transfer.h" +#include "../config.h" +#include "../exception.h" +#include "../http/auth.h" +#include "../http/broker.h" +#include "../http/client.h" +#include "../http/multipart.h" +#include "../http/proxy.h" +#include "../iomanager.h" +#include "../main.h" +#include "../sleep.h" +#include "../socket.h" +#include "../streams/socket.h" +#include "../streams/ssl.h" +#include "../streams/std.h" +#include "../streams/transfer.h" using namespace Mordor; namespace po = boost::program_options; diff --git a/mordor/http/auth.cpp b/mordor/http/auth.cpp index 2b15ba24..08787726 100644 --- a/mordor/http/auth.cpp +++ b/mordor/http/auth.cpp @@ -5,12 +5,12 @@ #include "basic.h" #include "client.h" #include "digest.h" -#include "mordor/socket.h" +#include "../socket.h" #ifdef WINDOWS #include "negotiate.h" #elif defined (OSX) -#include "mordor/util.h" +#include "../util.h" #include #include diff --git a/mordor/http/auth.h b/mordor/http/auth.h index e0472888..d1724ac5 100644 --- a/mordor/http/auth.h +++ b/mordor/http/auth.h @@ -5,7 +5,7 @@ #include #include "broker.h" -#include "mordor/version.h" +#include "../version.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/basic.cpp b/mordor/http/basic.cpp index fed79528..7d649de2 100644 --- a/mordor/http/basic.cpp +++ b/mordor/http/basic.cpp @@ -3,7 +3,7 @@ #include "basic.h" #include "http.h" -#include "mordor/string.h" +#include "../string.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/broker.cpp b/mordor/http/broker.cpp index d9989f4b..2968c8f2 100644 --- a/mordor/http/broker.cpp +++ b/mordor/http/broker.cpp @@ -4,16 +4,16 @@ #include "auth.h" #include "client.h" -#include "mordor/fiber.h" -#include "mordor/future.h" -#include "mordor/iomanager.h" -#include "mordor/log.h" -#include "mordor/socks.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/pipe.h" -#include "mordor/streams/socket.h" -#include "mordor/streams/ssl.h" -#include "mordor/streams/timeout.h" +#include "../fiber.h" +#include "../future.h" +#include "../iomanager.h" +#include "../log.h" +#include "../socks.h" +#include "../streams/buffered.h" +#include "../streams/pipe.h" +#include "../streams/socket.h" +#include "../streams/ssl.h" +#include "../streams/timeout.h" #include "proxy.h" #include "server.h" diff --git a/mordor/http/broker.h b/mordor/http/broker.h index 5cf238ef..65559631 100644 --- a/mordor/http/broker.h +++ b/mordor/http/broker.h @@ -5,7 +5,7 @@ #include #include "http.h" -#include "mordor/fibersynchronization.h" +#include "../fibersynchronization.h" #include #include diff --git a/mordor/http/chunked.cpp b/mordor/http/chunked.cpp index 68e65406..145de0c0 100644 --- a/mordor/http/chunked.cpp +++ b/mordor/http/chunked.cpp @@ -5,9 +5,9 @@ #include #include -#include "mordor/assert.h" -#include "mordor/streams/buffer.h" -#include "mordor/version.h" +#include "../assert.h" +#include "../streams/buffer.h" +#include "../version.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/chunked.h b/mordor/http/chunked.h index e9329490..f1b8933b 100644 --- a/mordor/http/chunked.h +++ b/mordor/http/chunked.h @@ -2,8 +2,8 @@ #define __MORDOR_HTTP_CHUNKED_H__ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/exception.h" -#include "mordor/streams/filter.h" +#include "../exception.h" +#include "../streams/filter.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/client.cpp b/mordor/http/client.cpp index 17a1e30d..22135128 100644 --- a/mordor/http/client.cpp +++ b/mordor/http/client.cpp @@ -8,19 +8,19 @@ #include "broker.h" #include "chunked.h" -#include "mordor/assert.h" -#include "mordor/fiber.h" -#include "mordor/log.h" -#include "mordor/scheduler.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/limited.h" -#include "mordor/streams/notify.h" -#include "mordor/streams/null.h" -#include "mordor/streams/timeout.h" -#include "mordor/streams/transfer.h" -#include "mordor/timer.h" -#include "mordor/util.h" -#include "mordor/socket.h" +#include "../assert.h" +#include "../fiber.h" +#include "../log.h" +#include "../scheduler.h" +#include "../streams/buffer.h" +#include "../streams/limited.h" +#include "../streams/notify.h" +#include "../streams/null.h" +#include "../streams/timeout.h" +#include "../streams/transfer.h" +#include "../timer.h" +#include "../util.h" +#include "../socket.h" #include "multipart.h" #include "parser.h" diff --git a/mordor/http/connection.cpp b/mordor/http/connection.cpp index f27f447f..78e9f678 100644 --- a/mordor/http/connection.cpp +++ b/mordor/http/connection.cpp @@ -3,12 +3,12 @@ #include "connection.h" #include "chunked.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/gzip.h" -#include "mordor/streams/limited.h" -#include "mordor/streams/notify.h" -#include "mordor/streams/singleplex.h" -#include "mordor/streams/zlib.h" +#include "../streams/buffered.h" +#include "../streams/gzip.h" +#include "../streams/limited.h" +#include "../streams/notify.h" +#include "../streams/singleplex.h" +#include "../streams/zlib.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/connection.h b/mordor/http/connection.h index e8c532e2..8f80597e 100644 --- a/mordor/http/connection.h +++ b/mordor/http/connection.h @@ -9,7 +9,7 @@ #include // Mordor -#include "mordor/anymap.h" +#include "../anymap.h" #include "http.h" namespace Mordor { diff --git a/mordor/http/digest.cpp b/mordor/http/digest.cpp index c95c45e1..355407ae 100644 --- a/mordor/http/digest.cpp +++ b/mordor/http/digest.cpp @@ -2,8 +2,8 @@ #include "digest.h" -#include "mordor/string.h" -#include "mordor/timer.h" +#include "../string.h" +#include "../timer.h" #include "parser.h" namespace Mordor { diff --git a/mordor/http/http.cpp b/mordor/http/http.cpp index cc758f39..d0e65d3a 100644 --- a/mordor/http/http.cpp +++ b/mordor/http/http.cpp @@ -6,7 +6,7 @@ #include #include -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/http.h b/mordor/http/http.h index 6a350e90..e0bfbe3a 100644 --- a/mordor/http/http.h +++ b/mordor/http/http.h @@ -10,10 +10,10 @@ #include #include -#include "mordor/predef.h" -#include "mordor/string.h" -#include "mordor/uri.h" -#include "mordor/version.h" +#include "../predef.h" +#include "../string.h" +#include "../uri.h" +#include "../version.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/multipart.cpp b/mordor/http/multipart.cpp index 55fd616b..77f8f0a8 100644 --- a/mordor/http/multipart.cpp +++ b/mordor/http/multipart.cpp @@ -3,12 +3,12 @@ #include "multipart.h" -#include "mordor/assert.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/notify.h" -#include "mordor/streams/null.h" -#include "mordor/streams/transfer.h" +#include "../assert.h" +#include "../streams/buffer.h" +#include "../streams/buffered.h" +#include "../streams/notify.h" +#include "../streams/null.h" +#include "../streams/transfer.h" #include "parser.h" namespace Mordor { diff --git a/mordor/http/negotiate.cpp b/mordor/http/negotiate.cpp index 92c384d6..9a92d007 100644 --- a/mordor/http/negotiate.cpp +++ b/mordor/http/negotiate.cpp @@ -3,8 +3,8 @@ #include "negotiate.h" #include "http.h" -#include "mordor/log.h" -#include "mordor/string.h" +#include "../log.h" +#include "../string.h" #pragma comment(lib, "secur32.lib") diff --git a/mordor/http/oauth.cpp b/mordor/http/oauth.cpp index 50c58b1c..d1eee773 100644 --- a/mordor/http/oauth.cpp +++ b/mordor/http/oauth.cpp @@ -3,8 +3,8 @@ #include "oauth.h" #include "client.h" -#include "mordor/date_time.h" -#include "mordor/streams/stream.h" +#include "../date_time.h" +#include "../streams/stream.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/parser.h b/mordor/http/parser.h index c7b6c8f1..2279a8dc 100644 --- a/mordor/http/parser.h +++ b/mordor/http/parser.h @@ -3,7 +3,7 @@ // Copyright (c) 2009 - Mozy, Inc. #include "http.h" -#include "mordor/ragel.h" +#include "../ragel.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/proxy.cpp b/mordor/http/proxy.cpp index c4479694..f082d216 100644 --- a/mordor/http/proxy.cpp +++ b/mordor/http/proxy.cpp @@ -3,23 +3,23 @@ #include "proxy.h" #include #include -#include "mordor/config.h" -#include "mordor/http/broker.h" -#include "mordor/http/client.h" -#include "mordor/socket.h" +#include "../config.h" +#include "../http/broker.h" +#include "../http/client.h" +#include "../socket.h" #ifdef WINDOWS -#include "mordor/runtime_linking.h" +#include "../runtime_linking.h" #elif defined (OSX) #include #include -#include "mordor/util.h" -#include "mordor/streams/file.h" -#include "mordor/streams/http.h" -#include "mordor/streams/limited.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/transfer.h" -#include "mordor/sleep.h" +#include "../util.h" +#include "../streams/file.h" +#include "../streams/http.h" +#include "../streams/limited.h" +#include "../streams/memory.h" +#include "../streams/transfer.h" +#include "../sleep.h" #endif namespace Mordor { diff --git a/mordor/http/proxy.h b/mordor/http/proxy.h index f5ad3cc4..cfb110ef 100644 --- a/mordor/http/proxy.h +++ b/mordor/http/proxy.h @@ -2,7 +2,7 @@ #define __MORDOR_HTTP_PROXY_H__ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/uri.h" +#include "../uri.h" #ifdef WINDOWS #include @@ -10,8 +10,8 @@ #include #include #include -#include "mordor/util.h" -#include "mordor/http/broker.h" +#include "../util.h" +#include "../http/broker.h" #endif namespace Mordor { diff --git a/mordor/http/server.cpp b/mordor/http/server.cpp index 9d22c82a..20b3fb59 100644 --- a/mordor/http/server.cpp +++ b/mordor/http/server.cpp @@ -3,12 +3,12 @@ #include "server.h" -#include "mordor/fiber.h" -#include "mordor/scheduler.h" -#include "mordor/socket.h" -#include "mordor/streams/null.h" -#include "mordor/streams/transfer.h" -#include "mordor/timer.h" +#include "../fiber.h" +#include "../scheduler.h" +#include "../socket.h" +#include "../streams/null.h" +#include "../streams/transfer.h" +#include "../timer.h" #include "multipart.h" #include "parser.h" diff --git a/mordor/http/servlet.cpp b/mordor/http/servlet.cpp index bde37977..6e78c3fc 100644 --- a/mordor/http/servlet.cpp +++ b/mordor/http/servlet.cpp @@ -2,7 +2,7 @@ #include "servlet.h" -#include "mordor/assert.h" +#include "../assert.h" #include "server.h" namespace Mordor { diff --git a/mordor/http/servlet.h b/mordor/http/servlet.h index 4f1a8b30..555005d1 100644 --- a/mordor/http/servlet.h +++ b/mordor/http/servlet.h @@ -4,8 +4,8 @@ #include -#include "mordor/factory.h" -#include "mordor/uri.h" +#include "../factory.h" +#include "../uri.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/servlets/config.cpp b/mordor/http/servlets/config.cpp index 4069a028..c97c1881 100644 --- a/mordor/http/servlets/config.cpp +++ b/mordor/http/servlets/config.cpp @@ -1,14 +1,14 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/http/servlets/config.h" +#include "config.h" -#include "mordor/config.h" -#include "mordor/http/server.h" -#include "mordor/json.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/limited.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/transfer.h" +#include "../../config.h" +#include "../server.h" +#include "../../json.h" +#include "../../streams/buffered.h" +#include "../../streams/limited.h" +#include "../../streams/memory.h" +#include "../../streams/transfer.h" namespace Mordor { namespace HTTP { diff --git a/mordor/http/servlets/config.h b/mordor/http/servlets/config.h index 65765c72..c19eeda2 100644 --- a/mordor/http/servlets/config.h +++ b/mordor/http/servlets/config.h @@ -3,7 +3,7 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/http/servlet.h" +#include "../servlet.h" namespace Mordor { namespace HTTP { diff --git a/mordor/log.cpp b/mordor/log.cpp index 4787786b..d1fd7533 100644 --- a/mordor/log.cpp +++ b/mordor/log.cpp @@ -16,8 +16,8 @@ #include "assert.h" #include "config.h" #include "fiber.h" -#include "mordor/streams/file.h" -#include "mordor/string.h" +#include "streams/file.h" +#include "string.h" #include "timer.h" namespace Mordor { diff --git a/mordor/pq/connection.cpp b/mordor/pq/connection.cpp index 0a5792cf..07bb6f88 100644 --- a/mordor/pq/connection.cpp +++ b/mordor/pq/connection.cpp @@ -1,12 +1,12 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "connection.h" -#include "mordor/assert.h" -#include "mordor/iomanager.h" -#include "mordor/log.h" +#include "../assert.h" +#include "../iomanager.h" +#include "../log.h" #include "exception.h" diff --git a/mordor/pq/connectionpool.cpp b/mordor/pq/connectionpool.cpp index c0051390..2687ea7a 100644 --- a/mordor/pq/connectionpool.cpp +++ b/mordor/pq/connectionpool.cpp @@ -1,14 +1,14 @@ // Copyright (c) 2010 Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "connectionpool.h" -#include "mordor/config.h" -#include "mordor/iomanager.h" -#include "mordor/log.h" -#include "mordor/util.h" +#include "../config.h" +#include "../iomanager.h" +#include "../log.h" +#include "../util.h" #include "connection.h" diff --git a/mordor/pq/connectionpool.h b/mordor/pq/connectionpool.h index 331c3008..55bb5990 100644 --- a/mordor/pq/connectionpool.h +++ b/mordor/pq/connectionpool.h @@ -4,7 +4,7 @@ #include -#include "mordor/fibersynchronization.h" +#include "../fibersynchronization.h" namespace Mordor { diff --git a/mordor/pq/copy.cpp b/mordor/pq/copy.cpp index b7f1c51a..ab16fda6 100644 --- a/mordor/pq/copy.cpp +++ b/mordor/pq/copy.cpp @@ -1,12 +1,12 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" -#include "mordor/assert.h" -#include "mordor/iomanager.h" -#include "mordor/log.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/stream.h" +#include "../assert.h" +#include "../iomanager.h" +#include "../log.h" +#include "../streams/buffer.h" +#include "../streams/stream.h" #include "connection.h" #include "exception.h" diff --git a/mordor/pq/exception.cpp b/mordor/pq/exception.cpp index db90ebc7..ada05038 100644 --- a/mordor/pq/exception.cpp +++ b/mordor/pq/exception.cpp @@ -1,10 +1,10 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "exception.h" -#include "mordor/log.h" +#include "../log.h" namespace Mordor { namespace PQ { diff --git a/mordor/pq/exception.h b/mordor/pq/exception.h index da3116d4..90acd8a9 100644 --- a/mordor/pq/exception.h +++ b/mordor/pq/exception.h @@ -4,7 +4,7 @@ #include -#include "mordor/exception.h" +#include "../exception.h" namespace Mordor { namespace PQ { diff --git a/mordor/pq/preparedstatement.cpp b/mordor/pq/preparedstatement.cpp index 3112d063..28d4c53b 100644 --- a/mordor/pq/preparedstatement.cpp +++ b/mordor/pq/preparedstatement.cpp @@ -1,13 +1,13 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "preparedstatement.h" -#include "mordor/assert.h" -#include "mordor/endian.h" -#include "mordor/log.h" -#include "mordor/iomanager.h" +#include "../assert.h" +#include "../endian.h" +#include "../log.h" +#include "../iomanager.h" #include "connection.h" #include "exception.h" diff --git a/mordor/pq/result.cpp b/mordor/pq/result.cpp index a377fe19..3f723567 100644 --- a/mordor/pq/result.cpp +++ b/mordor/pq/result.cpp @@ -1,14 +1,14 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "result.h" #include -#include "mordor/assert.h" -#include "mordor/endian.h" -#include "mordor/socket.h" +#include "../assert.h" +#include "../endian.h" +#include "../socket.h" #define BOOLOID 16 #define CHAROID 18 diff --git a/mordor/pq/transaction.cpp b/mordor/pq/transaction.cpp index 90ccd874..c2e35475 100644 --- a/mordor/pq/transaction.cpp +++ b/mordor/pq/transaction.cpp @@ -1,10 +1,10 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "transaction.h" -#include "mordor/assert.h" +#include "../assert.h" #include "connection.h" diff --git a/mordor/protobuf.cpp b/mordor/protobuf.cpp index 197c191e..d04ca792 100644 --- a/mordor/protobuf.cpp +++ b/mordor/protobuf.cpp @@ -2,8 +2,8 @@ #include "protobuf.h" -#include "mordor/assert.h" -#include "mordor/streams/buffer.h" +#include "assert.h" +#include "streams/buffer.h" #ifdef MSVC // Disable some warnings, but only while diff --git a/mordor/socks.cpp b/mordor/socks.cpp index 2f282931..9c931f56 100644 --- a/mordor/socks.cpp +++ b/mordor/socks.cpp @@ -2,9 +2,9 @@ #include "socks.h" -#include "mordor/http/broker.h" -#include "mordor/socket.h" -#include "mordor/streams/stream.h" +#include "http/broker.h" +#include "socket.h" +#include "streams/stream.h" namespace Mordor { namespace SOCKS { diff --git a/mordor/socks.h b/mordor/socks.h index 1a22dcae..f7c38be3 100644 --- a/mordor/socks.h +++ b/mordor/socks.h @@ -3,7 +3,7 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/exception.h" +#include "exception.h" namespace Mordor { diff --git a/mordor/ssh/agent.cpp b/mordor/ssh/agent.cpp index 842005ab..cade6054 100644 --- a/mordor/ssh/agent.cpp +++ b/mordor/ssh/agent.cpp @@ -4,7 +4,7 @@ #include -#include "mordor/exception.h" +#include "../exception.h" namespace Mordor { namespace SSH { diff --git a/mordor/ssh/agent.h b/mordor/ssh/agent.h index 112bf1dc..100ab885 100644 --- a/mordor/ssh/agent.h +++ b/mordor/ssh/agent.h @@ -4,7 +4,7 @@ #include -#include "mordor/fibersynchronization.h" +#include "../fibersynchronization.h" namespace Mordor { diff --git a/mordor/ssh/channel.cpp b/mordor/ssh/channel.cpp index 7dc56e60..7091c7a7 100644 --- a/mordor/ssh/channel.cpp +++ b/mordor/ssh/channel.cpp @@ -2,8 +2,8 @@ #include "channel.h" -#include "mordor/exception.h" -#include "mordor/log.h" +#include "../exception.h" +#include "../log.h" #include "session.h" namespace Mordor { diff --git a/mordor/ssh/channel.h b/mordor/ssh/channel.h index b16a1ca7..9832bfb5 100644 --- a/mordor/ssh/channel.h +++ b/mordor/ssh/channel.h @@ -4,7 +4,7 @@ #include -#include "mordor/streams/stream.h" +#include "../streams/stream.h" namespace Mordor { namespace SSH { diff --git a/mordor/ssh/session.cpp b/mordor/ssh/session.cpp index e98eec70..07cb861b 100644 --- a/mordor/ssh/session.cpp +++ b/mordor/ssh/session.cpp @@ -6,10 +6,10 @@ #include "agent.h" #include "channel.h" -#include "mordor/exception.h" -#include "mordor/iomanager.h" -#include "mordor/log.h" -#include "mordor/socket.h" +#include "../exception.h" +#include "../iomanager.h" +#include "../log.h" +#include "../socket.h" namespace { diff --git a/mordor/streams/buffer.cpp b/mordor/streams/buffer.cpp index cbca1917..449a45c0 100644 --- a/mordor/streams/buffer.cpp +++ b/mordor/streams/buffer.cpp @@ -5,8 +5,8 @@ #include #include -#include "mordor/assert.h" -#include "mordor/util.h" +#include "../assert.h" +#include "../util.h" #ifdef WINDOWS static u_long iovLength(size_t length) diff --git a/mordor/streams/buffer.h b/mordor/streams/buffer.h index 029df7ea..f22c165f 100644 --- a/mordor/streams/buffer.h +++ b/mordor/streams/buffer.h @@ -6,7 +6,7 @@ #include -#include "mordor/socket.h" +#include "../socket.h" namespace Mordor { diff --git a/mordor/streams/buffered.cpp b/mordor/streams/buffered.cpp index 1583211e..211bbb8b 100644 --- a/mordor/streams/buffered.cpp +++ b/mordor/streams/buffered.cpp @@ -2,9 +2,9 @@ #include "buffered.h" -#include "mordor/config.h" -#include "mordor/exception.h" -#include "mordor/log.h" +#include "../config.h" +#include "../exception.h" +#include "../log.h" namespace Mordor { diff --git a/mordor/streams/cat.cpp b/mordor/streams/cat.cpp index 4ce34388..e1a797d1 100644 --- a/mordor/streams/cat.cpp +++ b/mordor/streams/cat.cpp @@ -2,7 +2,7 @@ #include "cat.h" -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { diff --git a/mordor/streams/crypto.cpp b/mordor/streams/crypto.cpp index 3e220f01..f70fb294 100755 --- a/mordor/streams/crypto.cpp +++ b/mordor/streams/crypto.cpp @@ -1,7 +1,7 @@ #include "crypto.h" #include "ssl.h" // for OpenSSLException -#include "mordor/assert.h" -#include "mordor/streams/random.h" +#include "../assert.h" +#include "../streams/random.h" namespace Mordor { diff --git a/mordor/streams/delay.h b/mordor/streams/delay.h index 149b8f9f..781fb528 100644 --- a/mordor/streams/delay.h +++ b/mordor/streams/delay.h @@ -1,8 +1,8 @@ #ifndef __MORDOR_DELAY_STREAM_H_ #define __MORDOR_DELAY_STREAM_H_ -#include "mordor/sleep.h" -#include "mordor/streams/filter.h" +#include "../sleep.h" +#include "../streams/filter.h" namespace Mordor { diff --git a/mordor/streams/efs.cpp b/mordor/streams/efs.cpp index c4a6ef5f..b55892e0 100644 --- a/mordor/streams/efs.cpp +++ b/mordor/streams/efs.cpp @@ -4,9 +4,9 @@ #include "efs.h" #include "buffer.h" -#include "mordor/assert.h" -#include "mordor/fiber.h" -#include "mordor/string.h" +#include "../assert.h" +#include "../fiber.h" +#include "../string.h" namespace Mordor { diff --git a/mordor/streams/fd.cpp b/mordor/streams/fd.cpp index 3bb4770d..3275ebfa 100644 --- a/mordor/streams/fd.cpp +++ b/mordor/streams/fd.cpp @@ -12,8 +12,8 @@ #include #include "buffer.h" -#include "mordor/assert.h" -#include "mordor/iomanager.h" +#include "../assert.h" +#include "../iomanager.h" namespace Mordor { diff --git a/mordor/streams/file.cpp b/mordor/streams/file.cpp index 93c63563..5324a1af 100644 --- a/mordor/streams/file.cpp +++ b/mordor/streams/file.cpp @@ -2,8 +2,8 @@ #include "file.h" -#include "mordor/assert.h" -#include "mordor/string.h" +#include "../assert.h" +#include "../string.h" namespace Mordor { diff --git a/mordor/streams/file.h b/mordor/streams/file.h index 7f8767d1..bb87a308 100644 --- a/mordor/streams/file.h +++ b/mordor/streams/file.h @@ -2,7 +2,7 @@ #define __MORDOR_FILE_STREAM_H__ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/version.h" +#include "../version.h" #ifdef WINDOWS #include "handle.h" diff --git a/mordor/streams/filter.cpp b/mordor/streams/filter.cpp index 4676b186..ff309f2b 100644 --- a/mordor/streams/filter.cpp +++ b/mordor/streams/filter.cpp @@ -2,7 +2,7 @@ #include "filter.h" -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { diff --git a/mordor/streams/handle.cpp b/mordor/streams/handle.cpp index ab83f0f0..4494fa77 100644 --- a/mordor/streams/handle.cpp +++ b/mordor/streams/handle.cpp @@ -2,9 +2,9 @@ #include "handle.h" -#include "mordor/assert.h" -#include "mordor/log.h" -#include "mordor/runtime_linking.h" +#include "../assert.h" +#include "../log.h" +#include "../runtime_linking.h" namespace Mordor { diff --git a/mordor/streams/handle.h b/mordor/streams/handle.h index 6bf5abf1..e39e3471 100644 --- a/mordor/streams/handle.h +++ b/mordor/streams/handle.h @@ -4,7 +4,7 @@ #include -#include "mordor/iomanager.h" +#include "../iomanager.h" #include "stream.h" namespace Mordor { diff --git a/mordor/streams/hash.cpp b/mordor/streams/hash.cpp index 79c58948..7c3639e5 100644 --- a/mordor/streams/hash.cpp +++ b/mordor/streams/hash.cpp @@ -3,8 +3,8 @@ #include "hash.h" #include "buffer.h" -#include "mordor/assert.h" -#include "mordor/endian.h" +#include "../assert.h" +#include "../endian.h" namespace barg = std::placeholders; diff --git a/mordor/streams/http.cpp b/mordor/streams/http.cpp index 96924acc..ba2e6991 100644 --- a/mordor/streams/http.cpp +++ b/mordor/streams/http.cpp @@ -2,9 +2,9 @@ #include "http.h" -#include "mordor/fiber.h" -#include "mordor/http/client.h" -#include "mordor/socket.h" +#include "../fiber.h" +#include "../http/client.h" +#include "../socket.h" #include "null.h" #include "transfer.h" diff --git a/mordor/streams/http.h b/mordor/streams/http.h index ee23981d..ea25e7d7 100644 --- a/mordor/streams/http.h +++ b/mordor/streams/http.h @@ -3,9 +3,9 @@ // Copyright (c) 2009 - Mozy, Inc. #include "filter.h" -#include "mordor/exception.h" -#include "mordor/future.h" -#include "mordor/http/broker.h" +#include "../exception.h" +#include "../future.h" +#include "../http/broker.h" namespace Mordor { diff --git a/mordor/streams/limited.cpp b/mordor/streams/limited.cpp index 335e582e..9fb82663 100644 --- a/mordor/streams/limited.cpp +++ b/mordor/streams/limited.cpp @@ -4,7 +4,7 @@ #include -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { diff --git a/mordor/streams/lzma2.cpp b/mordor/streams/lzma2.cpp index f7017a69..aed43e6a 100644 --- a/mordor/streams/lzma2.cpp +++ b/mordor/streams/lzma2.cpp @@ -1,8 +1,8 @@ #include "lzma2.h" -#include "mordor/assert.h" -#include "mordor/exception.h" -#include "mordor/log.h" +#include "../assert.h" +#include "../exception.h" +#include "../log.h" #ifdef MSVC #pragma comment(lib, "liblzma") diff --git a/mordor/streams/memory.cpp b/mordor/streams/memory.cpp index 9035f433..3aa97c11 100644 --- a/mordor/streams/memory.cpp +++ b/mordor/streams/memory.cpp @@ -4,7 +4,7 @@ #include -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { diff --git a/mordor/streams/namedpipe.cpp b/mordor/streams/namedpipe.cpp index 66018ed8..00788767 100644 --- a/mordor/streams/namedpipe.cpp +++ b/mordor/streams/namedpipe.cpp @@ -2,11 +2,11 @@ #include "namedpipe.h" -#include "mordor/assert.h" -#include "mordor/exception.h" -#include "mordor/log.h" -#include "mordor/runtime_linking.h" -#include "mordor/string.h" +#include "../assert.h" +#include "../exception.h" +#include "../log.h" +#include "../runtime_linking.h" +#include "../string.h" namespace Mordor { diff --git a/mordor/streams/null.h b/mordor/streams/null.h index 8b1104d4..1e44ef43 100644 --- a/mordor/streams/null.h +++ b/mordor/streams/null.h @@ -3,7 +3,7 @@ // Copyright (c) 2009 - Mozy, Inc. #include "stream.h" -#include "mordor/util.h" +#include "../util.h" namespace Mordor { diff --git a/mordor/streams/pipe.cpp b/mordor/streams/pipe.cpp index e91d0e1b..1148d445 100644 --- a/mordor/streams/pipe.cpp +++ b/mordor/streams/pipe.cpp @@ -6,9 +6,9 @@ #include "buffer.h" #include "file.h" -#include "mordor/assert.h" -#include "mordor/fiber.h" -#include "mordor/scheduler.h" +#include "../assert.h" +#include "../fiber.h" +#include "../scheduler.h" #include "stream.h" #ifdef OSX diff --git a/mordor/streams/random.cpp b/mordor/streams/random.cpp index 61348989..6d273773 100644 --- a/mordor/streams/random.cpp +++ b/mordor/streams/random.cpp @@ -5,8 +5,8 @@ #include "ssl.h" #endif -#include "mordor/endian.h" -#include "mordor/exception.h" +#include "../endian.h" +#include "../exception.h" namespace Mordor { diff --git a/mordor/streams/scheduler.h b/mordor/streams/scheduler.h index ecbbf0e0..daa993aa 100644 --- a/mordor/streams/scheduler.h +++ b/mordor/streams/scheduler.h @@ -3,7 +3,7 @@ // Copyright (c) 2009 - Mozy, Inc. #include "filter.h" -#include "mordor/scheduler.h" +#include "../scheduler.h" namespace Mordor { diff --git a/mordor/streams/singleplex.cpp b/mordor/streams/singleplex.cpp index 25888cd5..74a1d321 100644 --- a/mordor/streams/singleplex.cpp +++ b/mordor/streams/singleplex.cpp @@ -2,7 +2,7 @@ #include "singleplex.h" -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { diff --git a/mordor/streams/socket.cpp b/mordor/streams/socket.cpp index 21e2e640..4d6f23da 100644 --- a/mordor/streams/socket.cpp +++ b/mordor/streams/socket.cpp @@ -3,8 +3,8 @@ #include "socket.h" #include "buffer.h" -#include "mordor/assert.h" -#include "mordor/socket.h" +#include "../assert.h" +#include "../socket.h" namespace Mordor { diff --git a/mordor/streams/ssl.cpp b/mordor/streams/ssl.cpp index a3135b8d..d977e6ba 100644 --- a/mordor/streams/ssl.cpp +++ b/mordor/streams/ssl.cpp @@ -7,9 +7,9 @@ #include #include -#include "mordor/assert.h" -#include "mordor/log.h" -#include "mordor/util.h" +#include "../assert.h" +#include "../log.h" +#include "../util.h" #ifdef MSVC #pragma comment(lib, "libeay32") diff --git a/mordor/streams/std.cpp b/mordor/streams/std.cpp index 15267ade..184e47fd 100644 --- a/mordor/streams/std.cpp +++ b/mordor/streams/std.cpp @@ -2,7 +2,7 @@ #include "std.h" -#include "mordor/exception.h" +#include "../exception.h" namespace Mordor { diff --git a/mordor/streams/std.h b/mordor/streams/std.h index bc5d0628..87d9b470 100644 --- a/mordor/streams/std.h +++ b/mordor/streams/std.h @@ -2,7 +2,7 @@ #define __MORDOR_STD_STREAM_H__ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/version.h" +#include "../version.h" #ifdef WINDOWS #include "handle.h" diff --git a/mordor/streams/stream.cpp b/mordor/streams/stream.cpp index a55fa616..19bb90da 100644 --- a/mordor/streams/stream.cpp +++ b/mordor/streams/stream.cpp @@ -7,7 +7,7 @@ #include #include "buffer.h" -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { diff --git a/mordor/streams/stream.h b/mordor/streams/stream.h index c84e71f7..c95179f5 100644 --- a/mordor/streams/stream.h +++ b/mordor/streams/stream.h @@ -6,7 +6,7 @@ #include -#include "mordor/predef.h" +#include "../predef.h" namespace Mordor { diff --git a/mordor/streams/tee.cpp b/mordor/streams/tee.cpp index 0e2bf91a..4f4fa0bd 100644 --- a/mordor/streams/tee.cpp +++ b/mordor/streams/tee.cpp @@ -6,10 +6,10 @@ namespace barg = std::placeholders; #include "tee.h" -#include "mordor/assert.h" -#include "mordor/log.h" -#include "mordor/parallel.h" -#include "mordor/streams/buffer.h" +#include "../assert.h" +#include "../log.h" +#include "../parallel.h" +#include "../streams/buffer.h" namespace Mordor { diff --git a/mordor/streams/temp.cpp b/mordor/streams/temp.cpp index 1e649ffc..bc82604b 100644 --- a/mordor/streams/temp.cpp +++ b/mordor/streams/temp.cpp @@ -2,8 +2,8 @@ #include "temp.h" -#include "mordor/config.h" -#include "mordor/string.h" +#include "../config.h" +#include "../string.h" namespace Mordor { diff --git a/mordor/streams/throttle.cpp b/mordor/streams/throttle.cpp index bcb33410..09f790fc 100644 --- a/mordor/streams/throttle.cpp +++ b/mordor/streams/throttle.cpp @@ -2,10 +2,10 @@ #include "throttle.h" -#include "mordor/assert.h" -#include "mordor/log.h" -#include "mordor/sleep.h" -#include "mordor/timer.h" +#include "../assert.h" +#include "../log.h" +#include "../sleep.h" +#include "../timer.h" namespace Mordor { diff --git a/mordor/streams/timeout.cpp b/mordor/streams/timeout.cpp index 6af7841f..e160d81a 100644 --- a/mordor/streams/timeout.cpp +++ b/mordor/streams/timeout.cpp @@ -2,11 +2,11 @@ #include "timeout.h" -#include "mordor/assert.h" -#include "mordor/exception.h" -#include "mordor/log.h" -#include "mordor/socket.h" -#include "mordor/timer.h" +#include "../assert.h" +#include "../exception.h" +#include "../log.h" +#include "../socket.h" +#include "../timer.h" namespace Mordor { diff --git a/mordor/streams/timeout.h b/mordor/streams/timeout.h index 7327ca44..39adcf9f 100644 --- a/mordor/streams/timeout.h +++ b/mordor/streams/timeout.h @@ -3,7 +3,7 @@ // Copyright (c) 2010 - Mozy, Inc. #include "filter.h" -#include "mordor/fibersynchronization.h" +#include "../fibersynchronization.h" namespace Mordor { diff --git a/mordor/streams/transfer.cpp b/mordor/streams/transfer.cpp index c203c5e8..94bc9034 100644 --- a/mordor/streams/transfer.cpp +++ b/mordor/streams/transfer.cpp @@ -3,12 +3,12 @@ #include "transfer.h" -#include "mordor/assert.h" -#include "mordor/config.h" -#include "mordor/fiber.h" -#include "mordor/parallel.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/null.h" +#include "../assert.h" +#include "../config.h" +#include "../fiber.h" +#include "../parallel.h" +#include "../streams/buffer.h" +#include "../streams/null.h" #include "stream.h" namespace Mordor { diff --git a/mordor/streams/zero.h b/mordor/streams/zero.h index c472bc42..8bb1039c 100644 --- a/mordor/streams/zero.h +++ b/mordor/streams/zero.h @@ -3,7 +3,7 @@ // Copyright (c) 2012 - VMware, Inc. #include "stream.h" -#include "mordor/util.h" +#include "../util.h" namespace Mordor { diff --git a/mordor/streams/zlib.cpp b/mordor/streams/zlib.cpp index e0d23319..8e1e560b 100644 --- a/mordor/streams/zlib.cpp +++ b/mordor/streams/zlib.cpp @@ -2,9 +2,9 @@ #include "zlib.h" -#include "mordor/assert.h" -#include "mordor/exception.h" -#include "mordor/log.h" +#include "../assert.h" +#include "../exception.h" +#include "../log.h" #ifdef MSVC #pragma comment(lib, "zdll") diff --git a/mordor/streams/zlib.h b/mordor/streams/zlib.h index 9cdca635..4d83c51a 100644 --- a/mordor/streams/zlib.h +++ b/mordor/streams/zlib.h @@ -6,7 +6,7 @@ #include "buffer.h" #include "filter.h" -#include "mordor/exception.h" +#include "../exception.h" namespace Mordor { diff --git a/mordor/string.cpp b/mordor/string.cpp index b48067c8..6ac6b836 100644 --- a/mordor/string.cpp +++ b/mordor/string.cpp @@ -14,8 +14,8 @@ #endif #endif -#include "mordor/string.h" -#include "mordor/util.h" +#include "string.h" +#include "util.h" #include "assert.h" #include "exception.h" diff --git a/mordor/test/antxmllistener.cpp b/mordor/test/antxmllistener.cpp index 0a0f7a7e..86f7dd6a 100644 --- a/mordor/test/antxmllistener.cpp +++ b/mordor/test/antxmllistener.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "antxmllistener.h" @@ -8,11 +8,11 @@ #include -#include "mordor/config.h" -#include "mordor/log.h" -#include "mordor/streams/file.h" -#include "mordor/string.h" -#include "mordor/timer.h" +#include "../config.h" +#include "../log.h" +#include "../streams/file.h" +#include "../string.h" +#include "../timer.h" namespace Mordor { namespace Test { diff --git a/mordor/test/stdoutlistener.cpp b/mordor/test/stdoutlistener.cpp index 8abacb4f..53dec1d9 100644 --- a/mordor/test/stdoutlistener.cpp +++ b/mordor/test/stdoutlistener.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" -#include "mordor/config.h" +#include "../predef.h" +#include "../config.h" #include "stdoutlistener.h" #include diff --git a/mordor/test/test.cpp b/mordor/test/test.cpp index 6ce12b05..53e8fea0 100644 --- a/mordor/test/test.cpp +++ b/mordor/test/test.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/predef.h" +#include "../predef.h" #include "test.h" @@ -8,9 +8,9 @@ #include -#include "mordor/config.h" -#include "mordor/sleep.h" -#include "mordor/timer.h" +#include "../config.h" +#include "../sleep.h" +#include "../timer.h" #ifdef WINDOWS #include diff --git a/mordor/test/test.h b/mordor/test/test.h index f6d1fdaf..ea1d9afa 100644 --- a/mordor/test/test.h +++ b/mordor/test/test.h @@ -7,7 +7,7 @@ #include #include -#include "mordor/assert.h" +#include "../assert.h" namespace Mordor { namespace Test { diff --git a/mordor/tests/buffer.cpp b/mordor/tests/buffer.cpp index e5598709..345639b5 100644 --- a/mordor/tests/buffer.cpp +++ b/mordor/tests/buffer.cpp @@ -1,8 +1,8 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/streams/buffer.h" -#include "mordor/test/test.h" +#include "../streams/buffer.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/http_client.cpp b/mordor/tests/http_client.cpp index a0d6a583..090e08b2 100644 --- a/mordor/tests/http_client.cpp +++ b/mordor/tests/http_client.cpp @@ -6,31 +6,31 @@ #endif -#include "mordor/fiber.h" -#include "mordor/http/broker.h" -#include "mordor/http/client.h" -#include "mordor/http/multipart.h" -#include "mordor/http/parser.h" -#include "mordor/http/server.h" -#include "mordor/http/servlet.h" -#include "mordor/iomanager.h" -#include "mordor/scheduler.h" -#include "mordor/sleep.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/cat.h" -#include "mordor/streams/duplex.h" -#include "mordor/streams/limited.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/notify.h" -#include "mordor/streams/null.h" -#include "mordor/streams/pipe.h" -#include "mordor/streams/random.h" -#include "mordor/streams/ssl.h" -#include "mordor/streams/test.h" -#include "mordor/streams/transfer.h" -#include "mordor/test/test.h" -#include "mordor/util.h" -#include "mordor/workerpool.h" +#include "../fiber.h" +#include "../http/broker.h" +#include "../http/client.h" +#include "../http/multipart.h" +#include "../http/parser.h" +#include "../http/server.h" +#include "../http/servlet.h" +#include "../iomanager.h" +#include "../scheduler.h" +#include "../sleep.h" +#include "../streams/buffered.h" +#include "../streams/cat.h" +#include "../streams/duplex.h" +#include "../streams/limited.h" +#include "../streams/memory.h" +#include "../streams/notify.h" +#include "../streams/null.h" +#include "../streams/pipe.h" +#include "../streams/random.h" +#include "../streams/ssl.h" +#include "../streams/test.h" +#include "../streams/transfer.h" +#include "../test/test.h" +#include "../util.h" +#include "../workerpool.h" using namespace Mordor; using namespace Mordor::HTTP; diff --git a/mordor/tests/http_parser.cpp b/mordor/tests/http_parser.cpp index 66c49d13..867012b2 100644 --- a/mordor/tests/http_parser.cpp +++ b/mordor/tests/http_parser.cpp @@ -1,13 +1,13 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/http/parser.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/duplex.h" -#include "mordor/streams/memory.h" -#include "mordor/streams/null.h" -#include "mordor/test/test.h" -#include "mordor/util.h" +#include "../http/parser.h" +#include "../streams/buffered.h" +#include "../streams/duplex.h" +#include "../streams/memory.h" +#include "../streams/null.h" +#include "../test/test.h" +#include "../util.h" using namespace Mordor; using namespace Mordor::HTTP; diff --git a/mordor/tests/iomanager.cpp b/mordor/tests/iomanager.cpp index 071627ff..f8d3e822 100644 --- a/mordor/tests/iomanager.cpp +++ b/mordor/tests/iomanager.cpp @@ -1,11 +1,11 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/future.h" -#include "mordor/iomanager.h" -#include "mordor/sleep.h" -#include "mordor/streams/pipe.h" -#include "mordor/test/test.h" +#include "../future.h" +#include "../iomanager.h" +#include "../sleep.h" +#include "../streams/pipe.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/iomanager_iocp.cpp b/mordor/tests/iomanager_iocp.cpp index e10b4881..8802ca0a 100644 --- a/mordor/tests/iomanager_iocp.cpp +++ b/mordor/tests/iomanager_iocp.cpp @@ -3,8 +3,8 @@ #ifdef WINDOWS -#include "mordor/iomanager.h" -#include "mordor/test/test.h" +#include "../iomanager.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/pipe_stream.cpp b/mordor/tests/pipe_stream.cpp index 33d9838c..d0d96a9f 100644 --- a/mordor/tests/pipe_stream.cpp +++ b/mordor/tests/pipe_stream.cpp @@ -1,14 +1,14 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/exception.h" -#include "mordor/fiber.h" -#include "mordor/scheduler.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/stream.h" -#include "mordor/streams/pipe.h" -#include "mordor/test/test.h" -#include "mordor/workerpool.h" +#include "../exception.h" +#include "../fiber.h" +#include "../scheduler.h" +#include "../streams/buffer.h" +#include "../streams/stream.h" +#include "../streams/pipe.h" +#include "../test/test.h" +#include "../workerpool.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/ragel.cpp b/mordor/tests/ragel.cpp index 826cff74..6b64cd35 100644 --- a/mordor/tests/ragel.cpp +++ b/mordor/tests/ragel.cpp @@ -1,8 +1,8 @@ -#include "mordor/http/http.h" -#include "mordor/http/parser.h" -#include "mordor/streams/buffer.h" -#include "mordor/streams/memory.h" -#include "mordor/test/test.h" +#include "../http/http.h" +#include "../http/parser.h" +#include "../streams/buffer.h" +#include "../streams/memory.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/rate_limiter.cpp b/mordor/tests/rate_limiter.cpp index bbfbe035..36492562 100644 --- a/mordor/tests/rate_limiter.cpp +++ b/mordor/tests/rate_limiter.cpp @@ -1,10 +1,10 @@ // Copyright (c) 2013 - Cody Cutrer -#include "mordor/rate_limiter.h" -#include "mordor/iomanager.h" -#include "mordor/sleep.h" -#include "mordor/test/test.h" +#include "../rate_limiter.h" +#include "../iomanager.h" +#include "../sleep.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/scheduler.cpp b/mordor/tests/scheduler.cpp index c4bb74db..e8bed799 100644 --- a/mordor/tests/scheduler.cpp +++ b/mordor/tests/scheduler.cpp @@ -3,13 +3,13 @@ #include #include -#include "mordor/fiber.h" -#include "mordor/iomanager.h" -#include "mordor/parallel.h" -#include "mordor/sleep.h" -#include "mordor/test/test.h" -#include "mordor/workerpool.h" -#include "mordor/util.h" +#include "../fiber.h" +#include "../iomanager.h" +#include "../parallel.h" +#include "../sleep.h" +#include "../test/test.h" +#include "../workerpool.h" +#include "../util.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/socket.cpp b/mordor/tests/socket.cpp index 86c2557b..f3106da0 100644 --- a/mordor/tests/socket.cpp +++ b/mordor/tests/socket.cpp @@ -6,11 +6,11 @@ #include #include -#include "mordor/exception.h" -#include "mordor/fiber.h" -#include "mordor/iomanager.h" -#include "mordor/socket.h" -#include "mordor/test/test.h" +#include "../exception.h" +#include "../fiber.h" +#include "../iomanager.h" +#include "../socket.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/ssl_stream.cpp b/mordor/tests/ssl_stream.cpp index e67e7140..3703fd61 100644 --- a/mordor/tests/ssl_stream.cpp +++ b/mordor/tests/ssl_stream.cpp @@ -1,16 +1,16 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/iomanager.h" -#include "mordor/parallel.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/hash.h" -#include "mordor/streams/null.h" -#include "mordor/streams/pipe.h" -#include "mordor/streams/random.h" -#include "mordor/streams/ssl.h" -#include "mordor/streams/transfer.h" -#include "mordor/test/test.h" -#include "mordor/workerpool.h" +#include "../iomanager.h" +#include "../parallel.h" +#include "../streams/buffered.h" +#include "../streams/hash.h" +#include "../streams/null.h" +#include "../streams/pipe.h" +#include "../streams/random.h" +#include "../streams/ssl.h" +#include "../streams/transfer.h" +#include "../test/test.h" +#include "../workerpool.h" using namespace Mordor; diff --git a/mordor/tests/string.cpp b/mordor/tests/string.cpp index 1acbb08d..551350f8 100644 --- a/mordor/tests/string.cpp +++ b/mordor/tests/string.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/string.h" -#include "mordor/test/test.h" +#include "../string.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/temp_stream.cpp b/mordor/tests/temp_stream.cpp index 6d31e654..42d90f14 100644 --- a/mordor/tests/temp_stream.cpp +++ b/mordor/tests/temp_stream.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/streams/temp.h" -#include "mordor/test/test.h" +#include "../streams/temp.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/thread.cpp b/mordor/tests/thread.cpp index 8fe8427c..9441539f 100644 --- a/mordor/tests/thread.cpp +++ b/mordor/tests/thread.cpp @@ -1,9 +1,9 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/test/test.h" -#include "mordor/thread.h" -#include "mordor/workerpool.h" +#include "../test/test.h" +#include "../thread.h" +#include "../workerpool.h" using namespace Mordor; diff --git a/mordor/tests/timer.cpp b/mordor/tests/timer.cpp index a3d7fa0f..1f0d4f87 100644 --- a/mordor/tests/timer.cpp +++ b/mordor/tests/timer.cpp @@ -1,9 +1,9 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/timer.h" -#include "mordor/workerpool.h" -#include "mordor/test/test.h" +#include "../timer.h" +#include "../workerpool.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/transfer_stream.cpp b/mordor/tests/transfer_stream.cpp index 70035cc2..c2d4ca9d 100644 --- a/mordor/tests/transfer_stream.cpp +++ b/mordor/tests/transfer_stream.cpp @@ -1,9 +1,9 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/streams/memory.h" -#include "mordor/streams/test.h" -#include "mordor/streams/transfer.h" -#include "mordor/test/test.h" +#include "../streams/memory.h" +#include "../streams/test.h" +#include "../streams/transfer.h" +#include "../test/test.h" using namespace Mordor; diff --git a/mordor/tests/unicode.cpp b/mordor/tests/unicode.cpp index a83f23ba..bea58643 100644 --- a/mordor/tests/unicode.cpp +++ b/mordor/tests/unicode.cpp @@ -1,7 +1,7 @@ -#include "mordor/pch.h" +#include "../pch.h" -#include "mordor/string.h" -#include "mordor/test/test.h" +#include "../string.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/uri.cpp b/mordor/tests/uri.cpp index 75bd258e..e141785c 100644 --- a/mordor/tests/uri.cpp +++ b/mordor/tests/uri.cpp @@ -1,8 +1,8 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/uri.h" -#include "mordor/streams/buffer.h" -#include "mordor/test/test.h" +#include "../uri.h" +#include "../streams/buffer.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/util.cpp b/mordor/tests/util.cpp index d6254101..e0e39f2f 100755 --- a/mordor/tests/util.cpp +++ b/mordor/tests/util.cpp @@ -1,8 +1,8 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/util.h" -#include "mordor/test/test.h" +#include "../util.h" +#include "../test/test.h" using namespace Mordor; using namespace Mordor::Test; diff --git a/mordor/tests/xml.cpp b/mordor/tests/xml.cpp index b9fcff93..c7e0a9ee 100644 --- a/mordor/tests/xml.cpp +++ b/mordor/tests/xml.cpp @@ -1,9 +1,9 @@ // Copyright (c) 2010 - Mozy, Inc. -#include "mordor/xml/dom_parser.h" -#include "mordor/test/test.h" -#include "mordor/string.h" +#include "../xml/dom_parser.h" +#include "../test/test.h" +#include "../string.h" using namespace Mordor; diff --git a/mordor/uri.h b/mordor/uri.h index f23b9513..209859ba 100644 --- a/mordor/uri.h +++ b/mordor/uri.h @@ -7,7 +7,7 @@ #include "assert.h" -#include "mordor/string.h" +#include "string.h" namespace Mordor { diff --git a/mordor/xml/dom_parser.cpp b/mordor/xml/dom_parser.cpp index 143136cd..d71147e4 100644 --- a/mordor/xml/dom_parser.cpp +++ b/mordor/xml/dom_parser.cpp @@ -1,8 +1,8 @@ // Copyright (c) 2009 - Mozy, Inc. #include -#include "mordor/assert.h" -#include "mordor/xml/dom_parser.h" +#include "../assert.h" +#include "../xml/dom_parser.h" namespace Mordor { namespace DOM { diff --git a/mordor/xml/dom_parser.h b/mordor/xml/dom_parser.h index 924b5e2a..8c4f39b1 100644 --- a/mordor/xml/dom_parser.h +++ b/mordor/xml/dom_parser.h @@ -2,8 +2,8 @@ #define __MORDOR_DOM_DOM_PARSER_H__ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/exception.h" -#include "mordor/xml/parser.h" +#include "../exception.h" +#include "../xml/parser.h" namespace Mordor { class Stream; diff --git a/mordor/xml/parser.h b/mordor/xml/parser.h index e3da95d0..0832a12b 100644 --- a/mordor/xml/parser.h +++ b/mordor/xml/parser.h @@ -3,7 +3,7 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "mordor/ragel.h" +#include "../ragel.h" namespace Mordor { diff --git a/mordor/zip.cpp b/mordor/zip.cpp index a8cc3a29..e258030c 100644 --- a/mordor/zip.cpp +++ b/mordor/zip.cpp @@ -2,16 +2,16 @@ #include "zip.h" -#include "mordor/assert.h" -#include "mordor/log.h" -#include "mordor/streams/buffered.h" -#include "mordor/streams/deflate.h" -#include "mordor/streams/hash.h" -#include "mordor/streams/limited.h" -#include "mordor/streams/notify.h" -#include "mordor/streams/null.h" -#include "mordor/streams/singleplex.h" -#include "mordor/streams/transfer.h" +#include "assert.h" +#include "log.h" +#include "streams/buffered.h" +#include "streams/deflate.h" +#include "streams/hash.h" +#include "streams/limited.h" +#include "streams/notify.h" +#include "streams/null.h" +#include "streams/singleplex.h" +#include "streams/transfer.h" namespace { #pragma pack(push) From 0d2446ddafaacc4082f165113ee46b6eb7985294 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Tue, 30 Sep 2014 17:10:40 -0400 Subject: [PATCH 07/12] Changes. --- mordor/fiber.h | 14 + mordor/iomanager_epoll.cpp | 6 +- mordor/iomanager_epoll.h | 13 +- mordor/log.h | 1 + mordor/scheduler.cpp | 971 ++++++++++++++++++++++++++----------- mordor/scheduler.h | 150 +++--- mordor/thread.h | 4 + mordor/workerpool.cpp | 20 +- mordor/workerpool.h | 4 +- 9 files changed, 792 insertions(+), 391 deletions(-) diff --git a/mordor/fiber.h b/mordor/fiber.h index ef3c939d..06540546 100644 --- a/mordor/fiber.h +++ b/mordor/fiber.h @@ -83,6 +83,9 @@ class Fiber final : public std::enable_shared_from_this, private internal /// @pre state() == INIT || state() == HOLD void inject(boost::exception_ptr exception); + /// Cancel fiber via operation caclened exception + void cancel(); + /// Yield execution to a specific Fiber /// The Fiber is executed by replacing the currently executing Fiber. @@ -205,6 +208,17 @@ class FiberLocalStorage : public FiberLocalStorageBase T * operator->() { return FiberLocalStorageBase::get(); } }; +inline +void Fiber::cancel() +{ + try { + try { throw boost::enable_current_exception(OperationAbortedException()); } + catch(...) { inject(boost::current_exception()); } + } catch (OperationAbortedException) { + // Nothing + } +} + } #endif // __FIBER_H__ diff --git a/mordor/iomanager_epoll.cpp b/mordor/iomanager_epoll.cpp index 5e0dbebf..c3883c6d 100644 --- a/mordor/iomanager_epoll.cpp +++ b/mordor/iomanager_epoll.cpp @@ -374,7 +374,7 @@ IOManager::stopping(unsigned long long &nextTimeout) } void -IOManager::idle() +IOManager::idle(const std::atomic& ec) { epoll_event events[64]; while (true) { @@ -480,10 +480,6 @@ IOManager::idle() void IOManager::tickle() { - if (!hasIdleThreads()) { - MORDOR_LOG_VERBOSE(g_log) << this << " 0 idle thread, no tickle."; - return; - } int rc = write(m_tickleFds[1], "T", 1); MORDOR_LOG_VERBOSE(g_log) << this << " write(" << m_tickleFds[1] << ", 1): " << rc << " (" << lastError() << ")"; diff --git a/mordor/iomanager_epoll.h b/mordor/iomanager_epoll.h index 93bcdc71..b31093d2 100644 --- a/mordor/iomanager_epoll.h +++ b/mordor/iomanager_epoll.h @@ -16,7 +16,7 @@ namespace Mordor { class Fiber; -class IOManager : public Scheduler, public TimerManager +class IOManager final : public Scheduler, public TimerManager { public: enum Event { @@ -37,7 +37,7 @@ class IOManager : public Scheduler, public TimerManager { EventContext() : scheduler(NULL) {} Scheduler *scheduler; - std::shared_ptr fiber; + Fiber::ptr fiber; std::function dg; }; @@ -72,10 +72,15 @@ class IOManager : public Scheduler, public TimerManager bool cancelEvent(int fd, Event events); protected: + + void idle(const std::atomic& ec); + + virtual void tickle(const std::atomic& ec) + { tickle(); } + bool stopping(unsigned long long &nextTimeout); - void idle(); - void tickle(); + void tickle(); void onTimerInsertedAtFront() { tickle(); } private: diff --git a/mordor/log.h b/mordor/log.h index 45e8bb00..4f573c6b 100644 --- a/mordor/log.h +++ b/mordor/log.h @@ -3,6 +3,7 @@ // Copyright (c) 2009 - Mozy, Inc. #include +#include #include #include diff --git a/mordor/scheduler.cpp b/mordor/scheduler.cpp index f892a59b..66109fd7 100644 --- a/mordor/scheduler.cpp +++ b/mordor/scheduler.cpp @@ -1,165 +1,648 @@ // Copyright (c) 2009 - Mozy, Inc. +// C++ +#include +#include +#include +#include +using std::function; +using std::list; +using std::shared_ptr; +using std::vector; +using std::unique_ptr; + +// Boost +#include +#include + // Mordor #include "scheduler.h" #include "assert.h" #include "fiber.h" +#include "platform/eventcount_linux.hpp" namespace Mordor { +typedef boost::shared_lock ReadGuard; +typedef boost::unique_lock WriteGuard; +typedef std::lock_guard MutexGuard; + static Logger::ptr g_log = Log::lookup("mordor:scheduler"); -thread_local Scheduler* Scheduler::t_scheduler = nullptr; thread_local Fiber* Scheduler::t_fiber = nullptr; +thread_local struct Scheduler::Worker* Scheduler::t_worker = nullptr; + +enum WorkerStatus : uint32_t +{ + NOT_STARTED, + STARTING, + RUNNING, + DISPATCH, + KILL, + STOPPING, + STOPPED +}; + +struct FiberStack +{ + size_t len; + void* ptr; +}; + +struct Scheduler::Worker +{ + Worker(Scheduler* parent, int batch = 1); + virtual ~Worker(); + + Scheduler* get_parent() const; + + /** Start worker */ + virtual void start() = 0; + + /** Stop running worker */ + virtual void stop(); + + /** Unconditional wakeup. */ + void wakeup() const; + + /** Post a new task and wakeup if needed. */ + void enqueue(unique_ptr t); + + /** Get worker's thread id */ + virtual std::thread::id get_tid() const = 0; + +protected: + void change_status(WorkerStatus status); + void change_status(WorkerStatus status, WorkerStatus expected); + + void run(const std::function& idle_fun); + +private: + /** Check if we should commit suecide */ + bool check_done() const; + + /** Return all unused work to the parent scheduler */ + void return_work(); + + /** Get/setup fiber for this task */ + Fiber* work_fiber(Scheduler::Task& task); + + int get_next_task(vector>& out, int count = 1); + void steal_task(vector>& out); + + void run_task(unique_ptr task); + + void do_idle(const Fiber::ptr& idle_fiber, unsigned ec_prev) const; + + void cleanup(const Fiber::ptr& idle_fiber); + + /** Get a stack for fiber that doesn't have one yet. */ + void get_stack(); + +protected: + Scheduler* parent; + int batch; + +private: + std::atomic status; + std::atomic event_count; + + std::deque affinity_queue; + std::deque work_queue; + std::mutex lock; +}; + +struct Scheduler::ThreadWorker final: public Scheduler::Worker +{ + virtual ~ThreadWorker(); + + ThreadWorker(Scheduler* parent, std::function idle_func, int batch = 1) + : Worker(parent, batch), + idle_func(std::move(idle_func)) + { }; + + virtual void start(); + + virtual std::thread::id get_tid() const + { return runner.get_id(); } + +private: + std::function idle_func; + std::thread runner; +}; + +struct Scheduler::HijackWorker final : public Scheduler::Worker +{ + virtual ~HijackWorker(); + + HijackWorker(Scheduler* parent, std::function idle_func, int batch = 1) + : Worker(parent, batch), + tid(std::this_thread::get_id()), + runner(std::make_shared(std::bind(&HijackWorker::run, this, + std::move(idle_func)))) + { + t_worker = this; + t_fiber = runner.get(); + }; + + virtual void start(); + + virtual std::thread::id get_tid() const + { return tid; } + + void stop_when_done() + { + change_status(WorkerStatus::DISPATCH); + wakeup(); + } + +private: + std::thread::id tid; + Fiber::ptr runner; +}; + +static void cancelFiber(Fiber& fib) +{ + try { + try { throw boost::enable_current_exception(OperationAbortedException()); } + catch(...) { fib.inject(boost::current_exception()); } + } catch (OperationAbortedException) { + // Nothing + } +} + +struct Scheduler::WorkerList : public vector> +{ + WorkerList(WorkerList&& rhs) = default; + WorkerList(unsigned reserve = 0) + { if (reserve > 1) this->reserve(reserve); } +}; + +Scheduler::Worker::Worker(Scheduler* parent, int batch) + : parent(parent), + batch(batch), + status(WorkerStatus::NOT_STARTED), + event_count(0) +{ } + +Scheduler::Worker::~Worker() +{ + // TODO: Free all the stacks +} + +inline +Scheduler* Scheduler::Worker::get_parent() const +{ + return parent; +} + +inline +void Scheduler::Worker::stop() +{ + change_status(WorkerStatus::KILL); + // TODO: Wakeup workers + // Can't call it currently since it gets called from the destructor +} + +void Scheduler::Worker::wakeup() const +{ + parent->tickle(event_count); +} + +inline +void Scheduler::Worker::enqueue(unique_ptr task) +{ + { + MutexGuard _guard(lock); + work_queue.push_back(task.release()); + } + + if (internal::eventcount_post(event_count)) + wakeup(); +} + +inline +bool Scheduler::Worker::check_done() const +{ + return status.load(std::memory_order_relaxed) == KILL || + parent->stopping(); +} + +inline +void Scheduler::Worker::return_work() +{ + MutexGuard _guard(lock); + + for (; work_queue.size(); work_queue.pop_front()) { + parent->schedule(unique_ptr(work_queue.front())); + } +} + +inline +Fiber* Scheduler::Worker::work_fiber(Scheduler::Task& task) +{ + Fiber* f = task.fiber.get(); + + if (f && f->state() != Fiber::TERM) { + return f; + } else if (task.dg) { + // TODO: Get new stack from pool + task.fiber = std::make_shared(std::move(task.dg)); + return task.fiber.get(); + } + + MORDOR_LOG_ERROR(g_log) << this << " Unexpected dead fiber"; + return nullptr; +} + +inline +int Scheduler::Worker::get_next_task(vector>& out, int count) +{ + int i = 0; + MutexGuard _guard(lock); + + for (; i < count && !affinity_queue.empty(); i++) { + affinity_queue.emplace_back(work_queue.front()); + affinity_queue.pop_front(); + } + + for (; i < count && !work_queue.empty(); i++) { + out.emplace_back(work_queue.front()); + work_queue.pop_front(); + } + + return i; +} + +inline +void Scheduler::Worker::steal_task(vector>& out) +{ + ReadGuard _guard(parent->m_lock); + + for (const shared_ptr& w: *parent->worker_list) { + MutexGuard _guard(w->lock); + + if (!w->work_queue.empty()) { + unique_ptr task(work_queue.back()); + + if (task->thread != std::thread::id()) + w->affinity_queue.emplace_back(std::move(task)); + else { + out->push_back(std::move(task)); + return; + } + } + } +} + +inline +void Scheduler::Worker::change_status(WorkerStatus new_status) +{ + status.store(new_status, std::memory_order_relaxed); +} + +inline +void Scheduler::Worker::change_status(WorkerStatus new_status, WorkerStatus expected) +{ + status.compare_exchange_strong(expected, new_status, std::memory_order_relaxed, + std::memory_order_relaxed); +} + +inline +void Scheduler::Worker::run_task(unique_ptr task) +{ + Fiber* f = work_fiber(*task); + + if (f) { + if (f->state() == Fiber::State::EXEC) { + // Fiber rescheduled itself hasn't fallen asleep yet + enqueue(std::move(task)); + return; + } + + MORDOR_LOG_DEBUG(g_log) << this << " running " << task.get(); + f->yieldTo(); + parent->done_count.fetch_add(1, std::memory_order_relaxed); + } + + if (f && f->state() == Fiber::TERM) { + // TODO: Return stack to stack pool + } +} + +inline +void Scheduler::Worker::do_idle(const Fiber::ptr& idle_fiber, unsigned ec_prev) const +{ + if (!idle_fiber) { + // No idle fiber (spin) + return; + } else if (idle_fiber->state() == Fiber::State::TERM) { + // Idle fiber exited (or died) + return false; + } + + if (internal::eventcount_shouldsleep(event_count, ec_prev)) + idle_fiber->call(); +} + +static inline +void log_run_error() +{ + // Swallow any exceptions that might occur while trying to log the current fiber state #98680 + try { + MORDOR_LOG_FATAL(Log::root()) + << boost::current_exception_diagnostic_information(); + } catch (...) { + } +} + +void Scheduler::Worker::run(const std::function& idle_func) +{ + vector> tasks; + unsigned empty_runs = 0; + Fiber::ptr idle_fiber; + + if (dynamic_cast(this)) { + t_fiber = Fiber::getThis().get(); + } else { + MORDOR_ASSERT(t_fiber == Fiber::getThis().get()); + } + + if (idle_func) + idle_fiber = std::make_shared(std::bind(idle_func, std::ref(event_count))); + + // Current scheduler worker + t_worker = this; + + // Keep enough space + tasks.reserve(batch); + + // Make this thread as running (unless it's already switched to KILL or DISPATCH mode) + change_status(WorkerStatus::RUNNING, WorkerStatus::STARTING); + + while (!check_done()) { + unsigned ec_prev = internal::eventcount_current(event_count); + + // Get task, if we fail try to steal a task + get_next_task(tasks, batch); + if (tasks.empty()) + steal_task(tasks); + + try { + for (unsigned i = 0; i < tasks.size(); i++) { + run_task(std::move(tasks[i])); + } + } catch (...) { + log_run_error(); + cleanup(idle_fiber); + throw; + } + + // There was work for us to do + if (tasks.size()) { + tasks.clear(); + empty_runs = 0; + continue; + } + + // If this thread is running in dispatch mode, return when there's no more work + // left to do. + if (status.load(std::memory_order_relaxed) == WorkerStatus::DISPATCH) { + parent->context->yieldTo(); + continue; + } + + // Try adaptive spinning to see if we can get some data before we go to sleep + empty_runs++; + if (empty_runs < 100) { + continue; + } else if (empty_runs < 1000) { + std::this_thread::yield(); + } + + // Run idle loop + do_idle(idle_fiber, ec_prev); + } + + cleanup(idle_fiber); +} + +void Mordor::Scheduler::Worker::cleanup(const Fiber::ptr& idle_fiber) +{ + // Shutdown sequence: + // - Mark the worker as shutting down + // - Cleanup idle fiber + // - Return the work (to other fibers) + if ((bool) idle_fiber && idle_fiber->state() == Fiber::State::HOLD) { + cancelFiber(*idle_fiber); + } + + return_work(); + + // We're dead + change_status(WorkerStatus::STOPPED); +} + +Scheduler::ThreadWorker::~ThreadWorker() +{ + stop(); + + if (runner.joinable()) { + runner.join(); + } +} + +void Scheduler::ThreadWorker::start() +{ + change_status(WorkerStatus::STARTING); + + // Create the fiber containing the run loop + runner = std::thread(std::bind(&ThreadWorker::run, this, std::move(idle_func))); +} + +Scheduler::HijackWorker::~HijackWorker() +{ + if (runner->state() == Fiber::State::HOLD) { + cancelFiber(*runner); + } + + t_worker = nullptr; + t_fiber = nullptr; +} + +void Scheduler::HijackWorker::start() +{ + parent->context = Fiber::getThis(); + change_status(WorkerStatus::STARTING, WorkerStatus::NOT_STARTED); + + // Save our calling fiber, so we can return + parent->yieldTo(true); +} Scheduler::Scheduler(size_t threads, bool useCaller, size_t batchSize) - : m_activeThreadCount(0), - m_idleThreadCount(0), - m_stopping(true), - m_autoStop(false), - m_batchSize(batchSize) + : m_hijack(useCaller), + m_batchSize(batchSize), + m_threadCount(threads), + m_state(State::STOPPED), + work_count(0), + done_count(0) { MORDOR_ASSERT(threads >= 1); if (useCaller) { - --threads; - MORDOR_ASSERT(getThis() == NULL); - t_scheduler = this; - m_rootFiber.reset(new Fiber(std::bind(&Scheduler::run, this))); - t_scheduler = this; - t_fiber = m_rootFiber.get(); - m_rootThread = std::this_thread::get_id(); + // Not allowed to create a new scheduler if already running in a scheduler + MORDOR_ASSERT(!getThis()); } - - m_threadCount = threads; } Scheduler::~Scheduler() { - MORDOR_ASSERT(m_stopping); - if (getThis() == this) { - t_scheduler = NULL; - } + // Derived shedulers should make sure we're stopped... + // virtual calls might be needed to shutdown + MORDOR_ASSERT(m_state == State::STOPPED); } -Scheduler * +Scheduler* Scheduler::getThis() { - return t_scheduler; + return (t_worker) + ? t_worker->get_parent() + : nullptr; } void Scheduler::start() { + std::function idle_func = std::bind(&Mordor::Scheduler::idle, this); + unique_ptr new_list(new WorkerList); + MORDOR_LOG_VERBOSE(g_log) << this << " starting " << m_threadCount << " threads"; - boost::mutex::scoped_lock lock(m_mutex); - if (!m_stopping) + + WriteGuard lock(m_lock); + + // Only start if we're in a already fully stopped mode + if (m_state != STOPPED) return; - // TODO: There may be a race condition here if one thread calls stop(), - // and another thread calls start() before the worker threads for this - // scheduler actually exit; they may resurrect themselves, and the stopping - // thread would block waiting for the thread to exit - - m_stopping = false; - MORDOR_ASSERT(m_threads.empty()); - m_threads.resize(m_threadCount); - for (size_t i = 0; i < m_threadCount; ++i) { - m_threads[i] = std::shared_ptr(new Thread( - std::bind(&Scheduler::run, this))); + + MORDOR_ASSERT(!worker_list); + + // Create the "thread-less" worker + if (m_hijack) { + auto worker = std::make_shared(this, idle_func, m_batchSize); + new_list->emplace_back(std::move(worker)); } -} -bool -Scheduler::hasWorkToDo() -{ - boost::mutex::scoped_lock lock(m_mutex); - return !m_fibers.empty(); + // Create the threaded worker + for (unsigned i = (m_hijack) ? 1 : 0; i < m_threadCount; ++i) { + auto worker = std::make_shared(this, idle_func, m_batchSize); + new_list->emplace_back(std::move(worker)); + new_list->back()->start(); + } + + worker_list = std::move(new_list); + m_state = State::RUNNING; } void Scheduler::stop() { - // Already stopped - if (m_rootFiber && - m_threadCount == 0 && - (m_rootFiber->state() == Fiber::TERM || m_rootFiber->state() == Fiber::INIT)) { - MORDOR_LOG_VERBOSE(g_log) << this << " stopped"; - m_stopping = true; - // A derived class may inhibit stopping while it has things to do in - // its idle loop, so we can't break early - if (stopping()) + unsigned count = (m_hijack) ? m_threadCount -1 : m_threadCount; + WorkerList stop_list(count); + + { + WriteGuard _guard(m_lock); + + if (!m_state == RUNNING) { + _guard.unlock(); + MORDOR_LOG_VERBOSE(g_log) << this << " already stopping / stopped"; return; + } else if (!worker_list) { + _guard.unlock(); + MORDOR_LOG_VERBOSE(g_log) << this << " already stopped"; + return; + } + + for (unsigned i = (m_hijack) ? 1 : 0; i < worker_list->size(); i++) + stop_list.push_back(worker_list->at(i)); + + // Leave the "hijacked" worker running + if (m_hijack) + worker_list->resize(1); + + m_state.store(State::STOPPING, std::memory_order_relaxed); } - bool exitOnThisFiber = false; - if (m_rootThread != std::thread::id()) { - // A thread-hijacking scheduler must be stopped - // from within itself to return control to the - // original thread + MORDOR_LOG_INFO(g_log) << this << " stopping scheduler"; + tickle(); + + if (m_hijack) { + // A thread-hijacking scheduler must be stopped from within itself to return control to the + // original thread. MORDOR_ASSERT(Scheduler::getThis() == this); - if (Fiber::getThis() == m_callingFiber) { - exitOnThisFiber = true; - // First switch to the correct thread - MORDOR_LOG_DEBUG(g_log) << this - << " switching to root thread to stop"; - switchTo(m_rootThread); + + // Switch to the hijacked thread + if (!dynamic_cast(t_worker)) { + std::thread::id tid; + + { + ReadGuard _guard(m_lock); + tid = worker_list->at(0)->get_tid(); + } + + MORDOR_LOG_DEBUG(g_log) << this << " switching to root thread to stop"; + switchTo(tid); } - if (!m_callingFiber) - exitOnThisFiber = true; } else { - // A spawned-threads only scheduler cannot be stopped from within - // itself... who would get control? + // A spawned-threads only scheduler cannot be stopped from within itself... + // who would get control? MORDOR_ASSERT(Scheduler::getThis() != this); } - m_stopping = true; - for (size_t i = 0; i < m_threadCount; ++i) - tickle(); - if (m_rootFiber && (m_threadCount != 0u || Scheduler::getThis() != this)) - tickle(); - // Wait for all work to stop on this thread - if (exitOnThisFiber) { - while (!stopping()) { - // Give this thread's run fiber a chance to kill itself off - MORDOR_LOG_DEBUG(g_log) << this - << " yielding to this thread to stop"; - yieldTo(true); - } + + // Notify all of worker to stop + stop_list.clear(); + + while (!stopping()) { + MORDOR_LOG_DEBUG(g_log) << this << " yielding to this thread to stop"; + yieldTo(true); } - // Wait for other threads to stop - if (exitOnThisFiber || - Scheduler::getThis() != this) { - MORDOR_LOG_DEBUG(g_log) << this - << " waiting for other threads to stop"; - std::vector > threads; - { - boost::mutex::scoped_lock lock(m_mutex); - threads.swap(m_threads); - } - for (std::vector >::const_iterator it - (threads.begin()); - it != threads.end(); - ++it) { - (*it)->join(); + + { + WriteGuard lock(m_lock); + m_state = State::STOPPED; + + if (m_hijack) { + worker_list.reset(); + MORDOR_ASSERT(!t_fiber); } } + MORDOR_LOG_VERBOSE(g_log) << this << " stopped"; + // Return back to our callin context } bool Scheduler::stopping() { - boost::mutex::scoped_lock lock(m_mutex); - return m_stopping && m_fibers.empty() && m_activeThreadCount == 0; + unsigned done, work; + ReadGuard lock(m_lock); + + if (m_state.load(std::memory_order_relaxed) != STOPPING) + return false; + + // Only fully stop once there's no more work + done = done_count.load(std::memory_order_relaxed); + work = work_count.load(std::memory_order_relaxed); + return done == work; } void Scheduler::switchTo(std::thread::id thread) { MORDOR_ASSERT(Scheduler::getThis() != NULL); - if (Scheduler::getThis() == this) { - if (thread == std::thread::id() || thread == std::this_thread::get_id()) - return; - } + + if (Scheduler::getThis() == this && thread == std::this_thread::get_id()) + return; + MORDOR_LOG_DEBUG(g_log) << this << " switching to thread " << thread; schedule(Fiber::getThis(), thread); Scheduler::yieldTo(); @@ -168,14 +651,17 @@ Scheduler::switchTo(std::thread::id thread) void Scheduler::yieldTo() { - Scheduler *self = Scheduler::getThis(); + Scheduler* self = Scheduler::getThis(); + HijackWorker* hworker = dynamic_cast(t_worker); + MORDOR_ASSERT(self); MORDOR_LOG_DEBUG(g_log) << self << " yielding to scheduler"; MORDOR_ASSERT(t_fiber); - if (self->m_rootThread == std::this_thread::get_id() && - (t_fiber->state() == Fiber::INIT || t_fiber->state() == Fiber::TERM)) { - self->m_callingFiber = Fiber::getThis(); - self->yieldTo(true); + + if (hworker && + (t_fiber->state() == Fiber::State::INIT || t_fiber->state() == Fiber::State::TERM)) + { + hworker->start(); } else { self->yieldTo(false); } @@ -185,6 +671,8 @@ void Scheduler::yield() { MORDOR_ASSERT(Scheduler::getThis()); + + // Make sure we schedule ourselves first Scheduler::getThis()->schedule(Fiber::getThis()); yieldTo(); } @@ -192,30 +680,77 @@ Scheduler::yield() void Scheduler::dispatch() { + HijackWorker* worker; + MORDOR_LOG_DEBUG(g_log) << this << " dispatching"; - MORDOR_ASSERT(m_rootThread == std::this_thread::get_id() && m_threadCount == 0); - m_stopping = true; - m_autoStop = true; + MORDOR_ASSERT(worker = dynamic_cast(t_worker)); + MORDOR_ASSERT(worker->get_tid() == std::this_thread::get_id()); + + worker->stop_when_done(); yieldTo(); - m_autoStop = false; } void -Scheduler::threadCount(size_t threads) +Scheduler::threadCount(unsigned threads) { + unique_ptr old_list; + unique_ptr new_list(new WorkerList(threads)); + unsigned prev; + MORDOR_ASSERT(threads >= 1); - if (m_rootFiber) - --threads; - boost::mutex::scoped_lock lock(m_mutex); - if (threads == m_threadCount) { + + // This is done infreqently + WriteGuard lock(m_lock); + + m_threadCount = threads; + + // We're not running so no ned to manually kick things off + if (m_state.load(std::memory_order_relaxed) != Scheduler::State::RUNNING) return; - } else if (threads > m_threadCount) { - m_threads.resize(threads); - for (size_t i = m_threadCount; i < threads; ++i) - m_threads[i] = std::shared_ptr(new Thread( - std::bind(&Scheduler::run, this))); + + old_list = std::move(worker_list); + prev = old_list->size(); + + // Notify old threads to shutdown + for (unsigned i = threads; i < prev; i++) { + Worker* w = worker_list->at(i).get(); + w->stop(); } - m_threadCount = threads; + + // Copy the list of alive ones + size_t copy = (prev < threads) ? prev : threads; + for (size_t i = 0; i < copy; i++) { + new_list->emplace_back(worker_list->at(i)); + } + + // Create new ones if needed + for (unsigned i = prev; i < threads; i++) { + auto worker = std::make_shared(this, nullptr, m_batchSize); + new_list->emplace_back(std::move(worker)); + } + + worker_list = std::move(new_list); +} + +unsigned +Scheduler::threadCount() const +{ + Scheduler* self = const_cast(this); + ReadGuard guard(self->m_lock); + + return self->m_threadCount; +} + +const list Scheduler::threads() const +{ + list result; + Scheduler* self = const_cast(this); + ReadGuard guard(self->m_lock); + + for (const shared_ptr& ptr: *(self->worker_list)) + result.push_back(ptr->get_tid()); + + return result; } void @@ -223,187 +758,51 @@ Scheduler::yieldTo(bool yieldToCallerOnTerminate) { MORDOR_ASSERT(t_fiber); MORDOR_ASSERT(Scheduler::getThis() == this); + + // Ensure we're running inside the hihack worker (if we're transfering out) if (yieldToCallerOnTerminate) - MORDOR_ASSERT(m_rootThread == std::this_thread::get_id()); - if (t_fiber->state() != Fiber::HOLD) { - m_stopping = m_autoStop || m_stopping; - // XXX: is t_fiber the hijacked thread ? - t_fiber->reset(std::bind(&Scheduler::run, this)); - } + MORDOR_ASSERT(dynamic_cast(t_worker)); + t_fiber->yieldTo(yieldToCallerOnTerminate); } void -Scheduler::run() +Scheduler::schedule(unique_ptr task) { - setThis(); - if (std::this_thread::get_id() != m_rootThread) { - // Running in own thread - t_fiber = Fiber::getThis().get(); - } else { - // Hijacked a thread - MORDOR_ASSERT(t_fiber == Fiber::getThis().get()); - } - Fiber::ptr idleFiber(new Fiber(std::bind(&Scheduler::idle, this))); - MORDOR_LOG_VERBOSE(g_log) << this << " starting thread with idle fiber " << idleFiber; - Fiber::ptr dgFiber; - // use a vector for O(1) .size() - std::vector batch; - batch.reserve(m_batchSize); - bool isActive = false; - while (true) { - MORDOR_ASSERT(batch.empty()); - bool dontIdle = false; - bool tickleMe = false; - { - boost::mutex::scoped_lock lock(m_mutex); - // Kill ourselves off if needed - if (m_threads.size() > m_threadCount && std::this_thread::get_id() != m_rootThread) { - // Accounting - if (isActive) - --m_activeThreadCount; - // Kill off the idle fiber - try { - throw boost::enable_current_exception( - OperationAbortedException()); - } catch(...) { - idleFiber->inject(boost::current_exception()); - } - // Detach our thread - for (std::vector > - ::iterator it = m_threads.begin(); - it != m_threads.end(); - ++it) - if ((*it)->tid() == std::this_thread::get_id()) { - m_threads.erase(it); - if (m_threads.size() > m_threadCount) - tickle(); - return; - } - MORDOR_NOTREACHED(); - } + unsigned prev = work_count.fetch_add(1, std::memory_order_relaxed); + MORDOR_LOG_DEBUG(g_log) << this << " Adding work " << task.get(); - std::list::iterator it(m_fibers.begin()); - while (it != m_fibers.end()) { - // If we've met our batch size, and we're not checking to see - // if we need to tickle another thread, then break - if ( (tickleMe || m_activeThreadCount == threadCount()) && - batch.size() == m_batchSize) - break; - if (it->thread != std::thread::id() && it->thread != std::this_thread::get_id()) { - MORDOR_LOG_DEBUG(g_log) << this - << " skipping item scheduled for thread " - << it->thread; - - // Wake up another thread to hopefully service this - tickleMe = true; - dontIdle = true; - ++it; - continue; - } - MORDOR_ASSERT(it->fiber || it->dg); - // This fiber is still executing; probably just some race - // race condition that it needs to yield on one thread - // before running on another thread - if (it->fiber && it->fiber->state() == Fiber::EXEC) { - MORDOR_LOG_DEBUG(g_log) << this - << " skipping executing fiber " << it->fiber; - ++it; - dontIdle = true; - continue; - } - // We were just checking if there is more work; there is, so - // set the flag and don't actually take this piece of work - if (batch.size() == m_batchSize) { - tickleMe = true; - break; - } - batch.push_back(*it); - it = m_fibers.erase(it); - if (!isActive) { - ++m_activeThreadCount; - isActive = true; - } - } - if (batch.empty() && isActive) { - --m_activeThreadCount; - isActive = false; - } - } - if (tickleMe) - tickle(); - MORDOR_LOG_DEBUG(g_log) << this - << " got " << batch.size() << " fiber/dgs to process (max: " - << m_batchSize << ", active: " << isActive << ")"; - MORDOR_ASSERT(isActive == !batch.empty()); - - if (batch.empty()) { - if (dontIdle) - continue; - - if (idleFiber->state() == Fiber::TERM) { - MORDOR_LOG_DEBUG(g_log) << this << " idle fiber terminated"; - if (std::this_thread::get_id() == m_rootThread) - m_callingFiber.reset(); - // Unblock the next thread - if (threadCount() > 1) - tickle(); - return; - } - MORDOR_LOG_DEBUG(g_log) << this << " idling"; - m_idleThreadCount++; - idleFiber->call(); - m_idleThreadCount--; - continue; - } + ReadGuard lock(m_lock); - while (!batch.empty()) { - FiberAndThread& ft = batch.back(); - Fiber::ptr f = ft.fiber; - std::function dg = ft.dg; - batch.pop_back(); - - try { - if (f && f->state() != Fiber::TERM) { - MORDOR_LOG_DEBUG(g_log) << this << " running " << f; - f->yieldTo(); - } else if (dg) { - if (dgFiber) - dgFiber->reset(dg); - else - dgFiber.reset(new Fiber(dg)); - MORDOR_LOG_DEBUG(g_log) << this << " running "; - dg = NULL; - dgFiber->yieldTo(); - if (dgFiber->state() != Fiber::TERM) - dgFiber.reset(); - else - dgFiber->reset(NULL); - } - } catch (...) { - try { - MORDOR_LOG_FATAL(Log::root()) - << boost::current_exception_diagnostic_information(); - } - catch(...) { - // Swallow any exceptions that might occur while trying to log the current fiber state #98680 - } - - { - boost::mutex::scoped_lock lock(m_mutex); - // push all un-executed fibers back to m_fibers - copy(batch.begin(), batch.end(), back_inserter(m_fibers)); - batch.clear(); - // decrease the activeCount as this thread is in exception - isActive = false; - --m_activeThreadCount; - } - throw; + unsigned count = worker_list->size(); + shared_ptr* workers = worker_list->data(); + + if (task->thread != std::thread::id()) { + // Try to find the worker in the list + for (unsigned i = 0; i < count ; i++) { + if (workers[i]->get_tid() == task->thread) { + workers[i]->enqueue(std::move(task)); + return; } } } + + // Round robin which worker we're going to use + unsigned which = prev % count; + workers[which]->enqueue(std::move(task)); + + m_lock.unlock(); + work_count.load(); } +void Scheduler::tickle() +{ + ReadGuard lock(m_lock); + + for (const shared_ptr& w: *worker_list) { + w->wakeup(); + } +} SchedulerSwitcher::SchedulerSwitcher(Scheduler *target) { diff --git a/mordor/scheduler.h b/mordor/scheduler.h index e125f3fb..5a83182c 100644 --- a/mordor/scheduler.h +++ b/mordor/scheduler.h @@ -2,12 +2,17 @@ #define __MORDOR_SCHEDULER_H__ // Copyright (c) 2009 - Mozy, Inc. +// C++ #include +#include #include #include +#include -#include +// Boost +#include +#include "fiber.h" #include "thread.h" namespace Mordor { @@ -28,6 +33,13 @@ class Fiber; /// stop(). stop() will return only after there are no more Fibers scheduled. class Scheduler { +public: + enum State { + RUNNING, + STOPPING, + STOPPED, + }; + public: /// Default constructor @@ -76,7 +88,7 @@ class Scheduler /// @param thread Optionally provide a specific thread for the Fiber to run /// on template - void schedule(FiberOrDg fd, std::thread::id thread = {}); + void schedule(FiberOrDg&& fd, std::thread::id thread = {}); /// Schedule multiple items to be executed at once @@ -118,16 +130,16 @@ class Scheduler /// @pre this is a hijacking Scheduler void dispatch(); - size_t threadCount() const; + unsigned threadCount() const; /// Change the number of threads in this scheduler - void threadCount(size_t threads); + void threadCount(unsigned threads); - const std::vector >& threads() const; - - std::thread::id rootThreadId() const { return m_rootThread; } + // Get the list of thread ids in the current scheduler + const std::list threads() const; protected: + /// Derived classes can query stopping() to see if the Scheduler is trying /// to stop, and should return from the idle Fiber as soon as possible. /// @@ -142,64 +154,68 @@ class Scheduler /// /// Implementors should Fiber::yield() when it believes there is work /// scheduled on the Scheduler. - virtual void idle() = 0; + virtual void idle(const std::atomic& ec) = 0; /// The Scheduler wants to force the idle fiber to Fiber::yield(), because /// new work has been scheduled. - virtual void tickle() = 0; - bool hasWorkToDo(); - virtual bool hasIdleThreads() const; - /// determine whether tickle() is needed, to be invoked in schedule() - /// @param empty whether m_fibers is empty before the new task is scheduled - virtual bool shouldTickle(bool empty) const; - - /// set `this' to TLS so that getThis() can get correct Scheduler - void setThis(); - -private: - void yieldTo(bool yieldToCallerOnTerminate); - void run(); - - /// @pre @c fd should be valid - /// @pre the task to be scheduled is not thread-targeted, or this scheduler - /// owns the targeted thread. - template - bool scheduleNoLock(FiberOrDg fd, std::thread::id thread = {}); + virtual void tickle(const std::atomic& ec) = 0; private: Scheduler(const Scheduler& rhs) = delete; +// Lockless queue (and queue entry) private: - struct FiberAndThread { - std::shared_ptr fiber; + + struct Task + { + Fiber::ptr fiber; std::function dg; std::thread::id thread; - FiberAndThread(std::shared_ptr f, std::thread::id th) + Task(const Fiber::ptr& f, std::thread::id th) : fiber(f), thread(th) { } - FiberAndThread(std::shared_ptr* f, std::thread::id th) + + Task(Fiber::ptr* f, std::thread::id th) : thread(th) { fiber.swap(*f); } - FiberAndThread(std::function d, std::thread::id th) + + Task(std::function d, std::thread::id th) : dg(d), thread(th) { } - FiberAndThread(std::function *d, std::thread::id th) + + Task(std::function *d, std::thread::id th) : thread(th) { dg.swap(*d); } }; - static thread_local Scheduler* t_scheduler; + + // Worker classes (hidden from user) + struct Worker; + struct ThreadWorker; + struct HijackWorker; + friend struct Worker; + // + struct WorkerList; + +private: + void yieldTo(bool yieldToCallerOnTerminate); + void schedule(std::unique_ptr task); + +private: static thread_local Fiber* t_fiber; - boost::mutex m_mutex; - std::list m_fibers; - std::thread::id m_rootThread; - std::shared_ptr m_rootFiber; - std::shared_ptr m_callingFiber; - std::vector > m_threads; - size_t m_threadCount, m_activeThreadCount; - std::atomic m_idleThreadCount; - bool m_stopping; - bool m_autoStop; + static thread_local Worker* t_worker; + + bool m_hijack; size_t m_batchSize; + unsigned m_threadCount; + + boost::shared_mutex m_lock; + + std::atomic m_state; + std::unique_ptr worker_list; + Fiber::ptr context; + + std::atomic work_count; + std::atomic done_count; }; /// Automatic Scheduler switcher @@ -224,53 +240,17 @@ struct SchedulerSwitcher // Implementation template -inline void Scheduler::schedule(FiberOrDg fd, std::thread::id thread) +inline void Scheduler::schedule(FiberOrDg&& fd, std::thread::id tid) { - bool tickleMe; - { - boost::mutex::scoped_lock lock(m_mutex); - tickleMe = scheduleNoLock(fd, thread); - } - if (shouldTickle(tickleMe)) - tickle(); + std::unique_ptr task(new Task(std::forward(fd), tid)); + schedule(std::move(task)); } template inline void Scheduler::schedule(InputIterator begin, InputIterator end) { - bool tickleMe = false; - { - boost::mutex::scoped_lock lock(m_mutex); - while (begin != end) { - tickleMe = scheduleNoLock(&*begin) || tickleMe; - ++begin; - } - } - if (shouldTickle(tickleMe)) - tickle(); -} - -inline size_t Scheduler::threadCount() const -{ return m_threadCount + (m_rootFiber ? 1 : 0); } - -inline const std::vector >& Scheduler::threads() const -{ return m_threads; } - -inline void Scheduler::setThis() -{ t_scheduler = this; } - -inline bool Scheduler::hasIdleThreads() const -{ return m_idleThreadCount != 0; } - -inline bool Scheduler::shouldTickle(bool empty) const -{ return empty && Scheduler::getThis() != this; } - -template -inline bool Scheduler::scheduleNoLock(FiberOrDg fd, std::thread::id thread) -{ - bool tickleMe = m_fibers.empty(); - m_fibers.push_back(FiberAndThread(fd, thread)); - return tickleMe; + for (; begin != end; ++begin) + schedule(&*begin); } } // namespace: Mordor diff --git a/mordor/thread.h b/mordor/thread.h index ba67939e..9fe7bfbb 100644 --- a/mordor/thread.h +++ b/mordor/thread.h @@ -2,7 +2,9 @@ #define __MORDOR_THREAD_H__ // Copyright (c) 2010 - Mozy, Inc. +// C++ #include +#include #include #include "version.h" @@ -19,8 +21,10 @@ class Thread /// /// bookmark current thread id and scheduler, allow to switch back to /// the same thread id later. + /// /// @pre The process must be running with available scheduler, otherwise /// it is not possible to switch execution between threads with bookmark. + /// /// @note Bookmark was designed to address the issue where we failed to /// rethrow an exception in catch block, because GCC C++ runtime saves the /// exception stack in a pthread TLS variable. and swapcontext(3) does not diff --git a/mordor/workerpool.cpp b/mordor/workerpool.cpp index df1e21e4..b915f05b 100644 --- a/mordor/workerpool.cpp +++ b/mordor/workerpool.cpp @@ -1,7 +1,8 @@ // Copyright (c) 2009 - Mozy, Inc. -#include "workerpool.h" +#include +#include "workerpool.h" #include "fiber.h" #include "log.h" @@ -16,13 +17,12 @@ WorkerPool::WorkerPool(size_t threads, bool useCaller, size_t batchSize) } void -WorkerPool::idle() +WorkerPool::idle(const std::atomic& ec) { - while (true) { - if (stopping()) { - return; - } - m_semaphore.wait(); + while (stopping()) { + int* uaddr = reinterpret_cast(&ec); + sys_futex(uaddr, FUTEX_WAIT, 1, nullptr, nullptr, 0); + try { Fiber::yield(); } catch (OperationAbortedException &) { @@ -32,10 +32,12 @@ WorkerPool::idle() } void -WorkerPool::tickle() +WorkerPool::tickle(const std::atomic& ec) { + int* uaddr = reinterpret_cast(&ec); + MORDOR_LOG_DEBUG(g_log) << this << " tickling"; - m_semaphore.notify(); + sys_futex(uaddr, FUTEX_WAKE, 1, nullptr, nullptr, 0); } } diff --git a/mordor/workerpool.h b/mordor/workerpool.h index fb24e21b..557ffa57 100644 --- a/mordor/workerpool.h +++ b/mordor/workerpool.h @@ -21,9 +21,9 @@ class WorkerPool : public Scheduler /// The idle Fiber for a WorkerPool simply loops waiting on a Semaphore, /// and yields whenever that Semaphore is signalled, returning if /// stopping() is true. - void idle(); + void idle(const std::atomic& ec); /// Signals the semaphore so that the idle Fiber will yield. - void tickle(); + void tickle(const std::atomic& ec); private: Semaphore m_semaphore; From ab0e384c91153721e7a7239e0df9058c6f0979d5 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Wed, 11 Nov 2015 16:13:55 -0500 Subject: [PATCH 08/12] Make it work with GCC5. --- m4/ax_boost_base.m4 | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/m4/ax_boost_base.m4 b/m4/ax_boost_base.m4 index ec23a0ab..f3279f2b 100644 --- a/m4/ax_boost_base.m4 +++ b/m4/ax_boost_base.m4 @@ -33,7 +33,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 18 +#serial 26 AC_DEFUN([AX_BOOST_BASE], [ @@ -59,7 +59,7 @@ AC_ARG_WITH([boost], AC_ARG_WITH([boost-libdir], AS_HELP_STRING([--with-boost-libdir=LIB_DIR], - [Force given directory for boost libraries. Note that this will overwrite library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), + [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), [ if test -d "$withval" then @@ -84,15 +84,33 @@ if test "x$want_boost" = "xyes"; then AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) succeeded=no - dnl On x86_64 systems check for system libraries in both lib64 and lib. + dnl On 64-bit systems check for system libraries in both lib64 and lib. dnl The former is specified by FHS, but e.g. Debian does not adhere to dnl this (as it rises problems for generic multi-arch support). dnl The last entry in the list is chosen by default when no libraries dnl are found, e.g. when only header-only libraries are installed! libsubdirs="lib" - if test `uname -m` = x86_64; then - libsubdirs="lib64 lib lib64" - fi + ax_arch=`uname -m` + case $ax_arch in + x86_64) + libsubdirs="lib64 libx32 lib lib64" + ;; + ppc64|s390x|sparc64|aarch64|ppc64le) + libsubdirs="lib64 lib lib64 ppc64le" + ;; + esac + + dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give + dnl them priority over the other paths since, if libs are found there, they + dnl are almost assuredly the ones desired. + AC_REQUIRE([AC_CANONICAL_HOST]) + libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" + + case ${host_cpu} in + i?86) + libsubdirs="lib/i386-${host_os} $libsubdirs" + ;; + esac dnl first we check the system location for boost libraries dnl this location ist chosen if boost libraries are installed with the --layout=system option @@ -155,6 +173,10 @@ if test "x$want_boost" = "xyes"; then dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version if test "x$succeeded" != "xyes"; then + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + BOOST_CPPFLAGS= + BOOST_LDFLAGS= _version=0 if test "$ac_boost_path" != ""; then if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then @@ -167,6 +189,12 @@ if test "x$want_boost" = "xyes"; then VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" done + dnl if nothing found search for layout used in Windows distributions + if test -z "$BOOST_CPPFLAGS"; then + if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then + BOOST_CPPFLAGS="-I$ac_boost_path" + fi + fi fi else if test "$cross_compiling" != yes; then From dd9785246859a628af2dbf666d02c9950aae92be Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Wed, 11 Nov 2015 16:41:52 -0500 Subject: [PATCH 09/12] Make this build, Werror. --- mordor/fiber.cpp | 6 ------ mordor/tests/uri.cpp | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/mordor/fiber.cpp b/mordor/fiber.cpp index 0839e29e..ab3b760c 100644 --- a/mordor/fiber.cpp +++ b/mordor/fiber.cpp @@ -29,12 +29,6 @@ namespace Mordor { -static AverageMinMaxStatistic &g_statAlloc = - Statistics::registerStatistic("fiber.allocstack", - AverageMinMaxStatistic("us")); -static AverageMinMaxStatistic &g_statFree= - Statistics::registerStatistic("fiber.freestack", - AverageMinMaxStatistic("us")); static std::atomic g_cntFibers(0); // Active fibers static MaxStatistic &g_statMaxFibers=Statistics::registerStatistic("fiber.max", MaxStatistic()); diff --git a/mordor/tests/uri.cpp b/mordor/tests/uri.cpp index 75bd258e..a59b398c 100644 --- a/mordor/tests/uri.cpp +++ b/mordor/tests/uri.cpp @@ -500,7 +500,7 @@ MORDOR_UNITTEST(URI, userinfoWithColon) MORDOR_TEST_ASSERT(uri.authority.hostDefined()); MORDOR_TEST_ASSERT(uri.authority.host().empty()); MORDOR_TEST_ASSERT(uri.authority.portDefined()); - MORDOR_TEST_ASSERT_EQUAL(uri.authority.port(), 15432u); + MORDOR_TEST_ASSERT_EQUAL(uri.authority.port(), 15432); uri = "postgres://:password@/"; MORDOR_TEST_ASSERT(uri.authority.userinfoDefined()); From 91bc56b1be6e10f7f3a857b5eb806f98d9f90f2f Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Wed, 11 Nov 2015 18:15:46 -0500 Subject: [PATCH 10/12] Revert "Changes." This reverts commit 0d2446ddafaacc4082f165113ee46b6eb7985294. --- mordor/fiber.h | 14 - mordor/iomanager_epoll.cpp | 6 +- mordor/iomanager_epoll.h | 13 +- mordor/log.h | 1 - mordor/scheduler.cpp | 971 +++++++++++-------------------------- mordor/scheduler.h | 150 +++--- mordor/thread.h | 4 - mordor/workerpool.cpp | 20 +- mordor/workerpool.h | 4 +- 9 files changed, 391 insertions(+), 792 deletions(-) diff --git a/mordor/fiber.h b/mordor/fiber.h index 06540546..ef3c939d 100644 --- a/mordor/fiber.h +++ b/mordor/fiber.h @@ -83,9 +83,6 @@ class Fiber final : public std::enable_shared_from_this, private internal /// @pre state() == INIT || state() == HOLD void inject(boost::exception_ptr exception); - /// Cancel fiber via operation caclened exception - void cancel(); - /// Yield execution to a specific Fiber /// The Fiber is executed by replacing the currently executing Fiber. @@ -208,17 +205,6 @@ class FiberLocalStorage : public FiberLocalStorageBase T * operator->() { return FiberLocalStorageBase::get(); } }; -inline -void Fiber::cancel() -{ - try { - try { throw boost::enable_current_exception(OperationAbortedException()); } - catch(...) { inject(boost::current_exception()); } - } catch (OperationAbortedException) { - // Nothing - } -} - } #endif // __FIBER_H__ diff --git a/mordor/iomanager_epoll.cpp b/mordor/iomanager_epoll.cpp index c3883c6d..5e0dbebf 100644 --- a/mordor/iomanager_epoll.cpp +++ b/mordor/iomanager_epoll.cpp @@ -374,7 +374,7 @@ IOManager::stopping(unsigned long long &nextTimeout) } void -IOManager::idle(const std::atomic& ec) +IOManager::idle() { epoll_event events[64]; while (true) { @@ -480,6 +480,10 @@ IOManager::idle(const std::atomic& ec) void IOManager::tickle() { + if (!hasIdleThreads()) { + MORDOR_LOG_VERBOSE(g_log) << this << " 0 idle thread, no tickle."; + return; + } int rc = write(m_tickleFds[1], "T", 1); MORDOR_LOG_VERBOSE(g_log) << this << " write(" << m_tickleFds[1] << ", 1): " << rc << " (" << lastError() << ")"; diff --git a/mordor/iomanager_epoll.h b/mordor/iomanager_epoll.h index b31093d2..93bcdc71 100644 --- a/mordor/iomanager_epoll.h +++ b/mordor/iomanager_epoll.h @@ -16,7 +16,7 @@ namespace Mordor { class Fiber; -class IOManager final : public Scheduler, public TimerManager +class IOManager : public Scheduler, public TimerManager { public: enum Event { @@ -37,7 +37,7 @@ class IOManager final : public Scheduler, public TimerManager { EventContext() : scheduler(NULL) {} Scheduler *scheduler; - Fiber::ptr fiber; + std::shared_ptr fiber; std::function dg; }; @@ -72,15 +72,10 @@ class IOManager final : public Scheduler, public TimerManager bool cancelEvent(int fd, Event events); protected: - - void idle(const std::atomic& ec); - - virtual void tickle(const std::atomic& ec) - { tickle(); } - bool stopping(unsigned long long &nextTimeout); - + void idle(); void tickle(); + void onTimerInsertedAtFront() { tickle(); } private: diff --git a/mordor/log.h b/mordor/log.h index 4f573c6b..45e8bb00 100644 --- a/mordor/log.h +++ b/mordor/log.h @@ -3,7 +3,6 @@ // Copyright (c) 2009 - Mozy, Inc. #include -#include #include #include diff --git a/mordor/scheduler.cpp b/mordor/scheduler.cpp index 66109fd7..f892a59b 100644 --- a/mordor/scheduler.cpp +++ b/mordor/scheduler.cpp @@ -1,648 +1,165 @@ // Copyright (c) 2009 - Mozy, Inc. -// C++ -#include -#include -#include -#include -using std::function; -using std::list; -using std::shared_ptr; -using std::vector; -using std::unique_ptr; - -// Boost -#include -#include - // Mordor #include "scheduler.h" #include "assert.h" #include "fiber.h" -#include "platform/eventcount_linux.hpp" namespace Mordor { -typedef boost::shared_lock ReadGuard; -typedef boost::unique_lock WriteGuard; -typedef std::lock_guard MutexGuard; - static Logger::ptr g_log = Log::lookup("mordor:scheduler"); +thread_local Scheduler* Scheduler::t_scheduler = nullptr; thread_local Fiber* Scheduler::t_fiber = nullptr; -thread_local struct Scheduler::Worker* Scheduler::t_worker = nullptr; - -enum WorkerStatus : uint32_t -{ - NOT_STARTED, - STARTING, - RUNNING, - DISPATCH, - KILL, - STOPPING, - STOPPED -}; - -struct FiberStack -{ - size_t len; - void* ptr; -}; - -struct Scheduler::Worker -{ - Worker(Scheduler* parent, int batch = 1); - virtual ~Worker(); - - Scheduler* get_parent() const; - - /** Start worker */ - virtual void start() = 0; - - /** Stop running worker */ - virtual void stop(); - - /** Unconditional wakeup. */ - void wakeup() const; - - /** Post a new task and wakeup if needed. */ - void enqueue(unique_ptr t); - - /** Get worker's thread id */ - virtual std::thread::id get_tid() const = 0; - -protected: - void change_status(WorkerStatus status); - void change_status(WorkerStatus status, WorkerStatus expected); - - void run(const std::function& idle_fun); - -private: - /** Check if we should commit suecide */ - bool check_done() const; - - /** Return all unused work to the parent scheduler */ - void return_work(); - - /** Get/setup fiber for this task */ - Fiber* work_fiber(Scheduler::Task& task); - - int get_next_task(vector>& out, int count = 1); - void steal_task(vector>& out); - - void run_task(unique_ptr task); - - void do_idle(const Fiber::ptr& idle_fiber, unsigned ec_prev) const; - - void cleanup(const Fiber::ptr& idle_fiber); - - /** Get a stack for fiber that doesn't have one yet. */ - void get_stack(); - -protected: - Scheduler* parent; - int batch; - -private: - std::atomic status; - std::atomic event_count; - - std::deque affinity_queue; - std::deque work_queue; - std::mutex lock; -}; - -struct Scheduler::ThreadWorker final: public Scheduler::Worker -{ - virtual ~ThreadWorker(); - - ThreadWorker(Scheduler* parent, std::function idle_func, int batch = 1) - : Worker(parent, batch), - idle_func(std::move(idle_func)) - { }; - - virtual void start(); - - virtual std::thread::id get_tid() const - { return runner.get_id(); } - -private: - std::function idle_func; - std::thread runner; -}; - -struct Scheduler::HijackWorker final : public Scheduler::Worker -{ - virtual ~HijackWorker(); - - HijackWorker(Scheduler* parent, std::function idle_func, int batch = 1) - : Worker(parent, batch), - tid(std::this_thread::get_id()), - runner(std::make_shared(std::bind(&HijackWorker::run, this, - std::move(idle_func)))) - { - t_worker = this; - t_fiber = runner.get(); - }; - - virtual void start(); - - virtual std::thread::id get_tid() const - { return tid; } - - void stop_when_done() - { - change_status(WorkerStatus::DISPATCH); - wakeup(); - } - -private: - std::thread::id tid; - Fiber::ptr runner; -}; - -static void cancelFiber(Fiber& fib) -{ - try { - try { throw boost::enable_current_exception(OperationAbortedException()); } - catch(...) { fib.inject(boost::current_exception()); } - } catch (OperationAbortedException) { - // Nothing - } -} - -struct Scheduler::WorkerList : public vector> -{ - WorkerList(WorkerList&& rhs) = default; - WorkerList(unsigned reserve = 0) - { if (reserve > 1) this->reserve(reserve); } -}; - -Scheduler::Worker::Worker(Scheduler* parent, int batch) - : parent(parent), - batch(batch), - status(WorkerStatus::NOT_STARTED), - event_count(0) -{ } - -Scheduler::Worker::~Worker() -{ - // TODO: Free all the stacks -} - -inline -Scheduler* Scheduler::Worker::get_parent() const -{ - return parent; -} - -inline -void Scheduler::Worker::stop() -{ - change_status(WorkerStatus::KILL); - // TODO: Wakeup workers - // Can't call it currently since it gets called from the destructor -} - -void Scheduler::Worker::wakeup() const -{ - parent->tickle(event_count); -} - -inline -void Scheduler::Worker::enqueue(unique_ptr task) -{ - { - MutexGuard _guard(lock); - work_queue.push_back(task.release()); - } - - if (internal::eventcount_post(event_count)) - wakeup(); -} - -inline -bool Scheduler::Worker::check_done() const -{ - return status.load(std::memory_order_relaxed) == KILL || - parent->stopping(); -} - -inline -void Scheduler::Worker::return_work() -{ - MutexGuard _guard(lock); - - for (; work_queue.size(); work_queue.pop_front()) { - parent->schedule(unique_ptr(work_queue.front())); - } -} - -inline -Fiber* Scheduler::Worker::work_fiber(Scheduler::Task& task) -{ - Fiber* f = task.fiber.get(); - - if (f && f->state() != Fiber::TERM) { - return f; - } else if (task.dg) { - // TODO: Get new stack from pool - task.fiber = std::make_shared(std::move(task.dg)); - return task.fiber.get(); - } - - MORDOR_LOG_ERROR(g_log) << this << " Unexpected dead fiber"; - return nullptr; -} - -inline -int Scheduler::Worker::get_next_task(vector>& out, int count) -{ - int i = 0; - MutexGuard _guard(lock); - - for (; i < count && !affinity_queue.empty(); i++) { - affinity_queue.emplace_back(work_queue.front()); - affinity_queue.pop_front(); - } - - for (; i < count && !work_queue.empty(); i++) { - out.emplace_back(work_queue.front()); - work_queue.pop_front(); - } - - return i; -} - -inline -void Scheduler::Worker::steal_task(vector>& out) -{ - ReadGuard _guard(parent->m_lock); - - for (const shared_ptr& w: *parent->worker_list) { - MutexGuard _guard(w->lock); - - if (!w->work_queue.empty()) { - unique_ptr task(work_queue.back()); - - if (task->thread != std::thread::id()) - w->affinity_queue.emplace_back(std::move(task)); - else { - out->push_back(std::move(task)); - return; - } - } - } -} - -inline -void Scheduler::Worker::change_status(WorkerStatus new_status) -{ - status.store(new_status, std::memory_order_relaxed); -} - -inline -void Scheduler::Worker::change_status(WorkerStatus new_status, WorkerStatus expected) -{ - status.compare_exchange_strong(expected, new_status, std::memory_order_relaxed, - std::memory_order_relaxed); -} - -inline -void Scheduler::Worker::run_task(unique_ptr task) -{ - Fiber* f = work_fiber(*task); - - if (f) { - if (f->state() == Fiber::State::EXEC) { - // Fiber rescheduled itself hasn't fallen asleep yet - enqueue(std::move(task)); - return; - } - - MORDOR_LOG_DEBUG(g_log) << this << " running " << task.get(); - f->yieldTo(); - parent->done_count.fetch_add(1, std::memory_order_relaxed); - } - - if (f && f->state() == Fiber::TERM) { - // TODO: Return stack to stack pool - } -} - -inline -void Scheduler::Worker::do_idle(const Fiber::ptr& idle_fiber, unsigned ec_prev) const -{ - if (!idle_fiber) { - // No idle fiber (spin) - return; - } else if (idle_fiber->state() == Fiber::State::TERM) { - // Idle fiber exited (or died) - return false; - } - - if (internal::eventcount_shouldsleep(event_count, ec_prev)) - idle_fiber->call(); -} - -static inline -void log_run_error() -{ - // Swallow any exceptions that might occur while trying to log the current fiber state #98680 - try { - MORDOR_LOG_FATAL(Log::root()) - << boost::current_exception_diagnostic_information(); - } catch (...) { - } -} - -void Scheduler::Worker::run(const std::function& idle_func) -{ - vector> tasks; - unsigned empty_runs = 0; - Fiber::ptr idle_fiber; - - if (dynamic_cast(this)) { - t_fiber = Fiber::getThis().get(); - } else { - MORDOR_ASSERT(t_fiber == Fiber::getThis().get()); - } - - if (idle_func) - idle_fiber = std::make_shared(std::bind(idle_func, std::ref(event_count))); - - // Current scheduler worker - t_worker = this; - - // Keep enough space - tasks.reserve(batch); - - // Make this thread as running (unless it's already switched to KILL or DISPATCH mode) - change_status(WorkerStatus::RUNNING, WorkerStatus::STARTING); - - while (!check_done()) { - unsigned ec_prev = internal::eventcount_current(event_count); - - // Get task, if we fail try to steal a task - get_next_task(tasks, batch); - if (tasks.empty()) - steal_task(tasks); - - try { - for (unsigned i = 0; i < tasks.size(); i++) { - run_task(std::move(tasks[i])); - } - } catch (...) { - log_run_error(); - cleanup(idle_fiber); - throw; - } - - // There was work for us to do - if (tasks.size()) { - tasks.clear(); - empty_runs = 0; - continue; - } - - // If this thread is running in dispatch mode, return when there's no more work - // left to do. - if (status.load(std::memory_order_relaxed) == WorkerStatus::DISPATCH) { - parent->context->yieldTo(); - continue; - } - - // Try adaptive spinning to see if we can get some data before we go to sleep - empty_runs++; - if (empty_runs < 100) { - continue; - } else if (empty_runs < 1000) { - std::this_thread::yield(); - } - - // Run idle loop - do_idle(idle_fiber, ec_prev); - } - - cleanup(idle_fiber); -} - -void Mordor::Scheduler::Worker::cleanup(const Fiber::ptr& idle_fiber) -{ - // Shutdown sequence: - // - Mark the worker as shutting down - // - Cleanup idle fiber - // - Return the work (to other fibers) - if ((bool) idle_fiber && idle_fiber->state() == Fiber::State::HOLD) { - cancelFiber(*idle_fiber); - } - - return_work(); - - // We're dead - change_status(WorkerStatus::STOPPED); -} - -Scheduler::ThreadWorker::~ThreadWorker() -{ - stop(); - - if (runner.joinable()) { - runner.join(); - } -} - -void Scheduler::ThreadWorker::start() -{ - change_status(WorkerStatus::STARTING); - - // Create the fiber containing the run loop - runner = std::thread(std::bind(&ThreadWorker::run, this, std::move(idle_func))); -} - -Scheduler::HijackWorker::~HijackWorker() -{ - if (runner->state() == Fiber::State::HOLD) { - cancelFiber(*runner); - } - - t_worker = nullptr; - t_fiber = nullptr; -} - -void Scheduler::HijackWorker::start() -{ - parent->context = Fiber::getThis(); - change_status(WorkerStatus::STARTING, WorkerStatus::NOT_STARTED); - - // Save our calling fiber, so we can return - parent->yieldTo(true); -} Scheduler::Scheduler(size_t threads, bool useCaller, size_t batchSize) - : m_hijack(useCaller), - m_batchSize(batchSize), - m_threadCount(threads), - m_state(State::STOPPED), - work_count(0), - done_count(0) + : m_activeThreadCount(0), + m_idleThreadCount(0), + m_stopping(true), + m_autoStop(false), + m_batchSize(batchSize) { MORDOR_ASSERT(threads >= 1); if (useCaller) { - // Not allowed to create a new scheduler if already running in a scheduler - MORDOR_ASSERT(!getThis()); + --threads; + MORDOR_ASSERT(getThis() == NULL); + t_scheduler = this; + m_rootFiber.reset(new Fiber(std::bind(&Scheduler::run, this))); + t_scheduler = this; + t_fiber = m_rootFiber.get(); + m_rootThread = std::this_thread::get_id(); } + + m_threadCount = threads; } Scheduler::~Scheduler() { - // Derived shedulers should make sure we're stopped... - // virtual calls might be needed to shutdown - MORDOR_ASSERT(m_state == State::STOPPED); + MORDOR_ASSERT(m_stopping); + if (getThis() == this) { + t_scheduler = NULL; + } } -Scheduler* +Scheduler * Scheduler::getThis() { - return (t_worker) - ? t_worker->get_parent() - : nullptr; + return t_scheduler; } void Scheduler::start() { - std::function idle_func = std::bind(&Mordor::Scheduler::idle, this); - unique_ptr new_list(new WorkerList); - MORDOR_LOG_VERBOSE(g_log) << this << " starting " << m_threadCount << " threads"; - - WriteGuard lock(m_lock); - - // Only start if we're in a already fully stopped mode - if (m_state != STOPPED) + boost::mutex::scoped_lock lock(m_mutex); + if (!m_stopping) return; - - MORDOR_ASSERT(!worker_list); - - // Create the "thread-less" worker - if (m_hijack) { - auto worker = std::make_shared(this, idle_func, m_batchSize); - new_list->emplace_back(std::move(worker)); - } - - // Create the threaded worker - for (unsigned i = (m_hijack) ? 1 : 0; i < m_threadCount; ++i) { - auto worker = std::make_shared(this, idle_func, m_batchSize); - new_list->emplace_back(std::move(worker)); - new_list->back()->start(); + // TODO: There may be a race condition here if one thread calls stop(), + // and another thread calls start() before the worker threads for this + // scheduler actually exit; they may resurrect themselves, and the stopping + // thread would block waiting for the thread to exit + + m_stopping = false; + MORDOR_ASSERT(m_threads.empty()); + m_threads.resize(m_threadCount); + for (size_t i = 0; i < m_threadCount; ++i) { + m_threads[i] = std::shared_ptr(new Thread( + std::bind(&Scheduler::run, this))); } +} - worker_list = std::move(new_list); - m_state = State::RUNNING; +bool +Scheduler::hasWorkToDo() +{ + boost::mutex::scoped_lock lock(m_mutex); + return !m_fibers.empty(); } void Scheduler::stop() { - unsigned count = (m_hijack) ? m_threadCount -1 : m_threadCount; - WorkerList stop_list(count); - - { - WriteGuard _guard(m_lock); - - if (!m_state == RUNNING) { - _guard.unlock(); - MORDOR_LOG_VERBOSE(g_log) << this << " already stopping / stopped"; + // Already stopped + if (m_rootFiber && + m_threadCount == 0 && + (m_rootFiber->state() == Fiber::TERM || m_rootFiber->state() == Fiber::INIT)) { + MORDOR_LOG_VERBOSE(g_log) << this << " stopped"; + m_stopping = true; + // A derived class may inhibit stopping while it has things to do in + // its idle loop, so we can't break early + if (stopping()) return; - } else if (!worker_list) { - _guard.unlock(); - MORDOR_LOG_VERBOSE(g_log) << this << " already stopped"; - return; - } - - for (unsigned i = (m_hijack) ? 1 : 0; i < worker_list->size(); i++) - stop_list.push_back(worker_list->at(i)); - - // Leave the "hijacked" worker running - if (m_hijack) - worker_list->resize(1); - - m_state.store(State::STOPPING, std::memory_order_relaxed); } - MORDOR_LOG_INFO(g_log) << this << " stopping scheduler"; - tickle(); - - if (m_hijack) { - // A thread-hijacking scheduler must be stopped from within itself to return control to the - // original thread. + bool exitOnThisFiber = false; + if (m_rootThread != std::thread::id()) { + // A thread-hijacking scheduler must be stopped + // from within itself to return control to the + // original thread MORDOR_ASSERT(Scheduler::getThis() == this); - - // Switch to the hijacked thread - if (!dynamic_cast(t_worker)) { - std::thread::id tid; - - { - ReadGuard _guard(m_lock); - tid = worker_list->at(0)->get_tid(); - } - - MORDOR_LOG_DEBUG(g_log) << this << " switching to root thread to stop"; - switchTo(tid); + if (Fiber::getThis() == m_callingFiber) { + exitOnThisFiber = true; + // First switch to the correct thread + MORDOR_LOG_DEBUG(g_log) << this + << " switching to root thread to stop"; + switchTo(m_rootThread); } + if (!m_callingFiber) + exitOnThisFiber = true; } else { - // A spawned-threads only scheduler cannot be stopped from within itself... - // who would get control? + // A spawned-threads only scheduler cannot be stopped from within + // itself... who would get control? MORDOR_ASSERT(Scheduler::getThis() != this); } - - // Notify all of worker to stop - stop_list.clear(); - - while (!stopping()) { - MORDOR_LOG_DEBUG(g_log) << this << " yielding to this thread to stop"; - yieldTo(true); + m_stopping = true; + for (size_t i = 0; i < m_threadCount; ++i) + tickle(); + if (m_rootFiber && (m_threadCount != 0u || Scheduler::getThis() != this)) + tickle(); + // Wait for all work to stop on this thread + if (exitOnThisFiber) { + while (!stopping()) { + // Give this thread's run fiber a chance to kill itself off + MORDOR_LOG_DEBUG(g_log) << this + << " yielding to this thread to stop"; + yieldTo(true); + } } - - { - WriteGuard lock(m_lock); - m_state = State::STOPPED; - - if (m_hijack) { - worker_list.reset(); - MORDOR_ASSERT(!t_fiber); + // Wait for other threads to stop + if (exitOnThisFiber || + Scheduler::getThis() != this) { + MORDOR_LOG_DEBUG(g_log) << this + << " waiting for other threads to stop"; + std::vector > threads; + { + boost::mutex::scoped_lock lock(m_mutex); + threads.swap(m_threads); + } + for (std::vector >::const_iterator it + (threads.begin()); + it != threads.end(); + ++it) { + (*it)->join(); } } - MORDOR_LOG_VERBOSE(g_log) << this << " stopped"; - // Return back to our callin context } bool Scheduler::stopping() { - unsigned done, work; - ReadGuard lock(m_lock); - - if (m_state.load(std::memory_order_relaxed) != STOPPING) - return false; - - // Only fully stop once there's no more work - done = done_count.load(std::memory_order_relaxed); - work = work_count.load(std::memory_order_relaxed); - return done == work; + boost::mutex::scoped_lock lock(m_mutex); + return m_stopping && m_fibers.empty() && m_activeThreadCount == 0; } void Scheduler::switchTo(std::thread::id thread) { MORDOR_ASSERT(Scheduler::getThis() != NULL); - - if (Scheduler::getThis() == this && thread == std::this_thread::get_id()) - return; - + if (Scheduler::getThis() == this) { + if (thread == std::thread::id() || thread == std::this_thread::get_id()) + return; + } MORDOR_LOG_DEBUG(g_log) << this << " switching to thread " << thread; schedule(Fiber::getThis(), thread); Scheduler::yieldTo(); @@ -651,17 +168,14 @@ Scheduler::switchTo(std::thread::id thread) void Scheduler::yieldTo() { - Scheduler* self = Scheduler::getThis(); - HijackWorker* hworker = dynamic_cast(t_worker); - + Scheduler *self = Scheduler::getThis(); MORDOR_ASSERT(self); MORDOR_LOG_DEBUG(g_log) << self << " yielding to scheduler"; MORDOR_ASSERT(t_fiber); - - if (hworker && - (t_fiber->state() == Fiber::State::INIT || t_fiber->state() == Fiber::State::TERM)) - { - hworker->start(); + if (self->m_rootThread == std::this_thread::get_id() && + (t_fiber->state() == Fiber::INIT || t_fiber->state() == Fiber::TERM)) { + self->m_callingFiber = Fiber::getThis(); + self->yieldTo(true); } else { self->yieldTo(false); } @@ -671,8 +185,6 @@ void Scheduler::yield() { MORDOR_ASSERT(Scheduler::getThis()); - - // Make sure we schedule ourselves first Scheduler::getThis()->schedule(Fiber::getThis()); yieldTo(); } @@ -680,77 +192,30 @@ Scheduler::yield() void Scheduler::dispatch() { - HijackWorker* worker; - MORDOR_LOG_DEBUG(g_log) << this << " dispatching"; - MORDOR_ASSERT(worker = dynamic_cast(t_worker)); - MORDOR_ASSERT(worker->get_tid() == std::this_thread::get_id()); - - worker->stop_when_done(); + MORDOR_ASSERT(m_rootThread == std::this_thread::get_id() && m_threadCount == 0); + m_stopping = true; + m_autoStop = true; yieldTo(); + m_autoStop = false; } void -Scheduler::threadCount(unsigned threads) +Scheduler::threadCount(size_t threads) { - unique_ptr old_list; - unique_ptr new_list(new WorkerList(threads)); - unsigned prev; - MORDOR_ASSERT(threads >= 1); - - // This is done infreqently - WriteGuard lock(m_lock); - - m_threadCount = threads; - - // We're not running so no ned to manually kick things off - if (m_state.load(std::memory_order_relaxed) != Scheduler::State::RUNNING) + if (m_rootFiber) + --threads; + boost::mutex::scoped_lock lock(m_mutex); + if (threads == m_threadCount) { return; - - old_list = std::move(worker_list); - prev = old_list->size(); - - // Notify old threads to shutdown - for (unsigned i = threads; i < prev; i++) { - Worker* w = worker_list->at(i).get(); - w->stop(); - } - - // Copy the list of alive ones - size_t copy = (prev < threads) ? prev : threads; - for (size_t i = 0; i < copy; i++) { - new_list->emplace_back(worker_list->at(i)); + } else if (threads > m_threadCount) { + m_threads.resize(threads); + for (size_t i = m_threadCount; i < threads; ++i) + m_threads[i] = std::shared_ptr(new Thread( + std::bind(&Scheduler::run, this))); } - - // Create new ones if needed - for (unsigned i = prev; i < threads; i++) { - auto worker = std::make_shared(this, nullptr, m_batchSize); - new_list->emplace_back(std::move(worker)); - } - - worker_list = std::move(new_list); -} - -unsigned -Scheduler::threadCount() const -{ - Scheduler* self = const_cast(this); - ReadGuard guard(self->m_lock); - - return self->m_threadCount; -} - -const list Scheduler::threads() const -{ - list result; - Scheduler* self = const_cast(this); - ReadGuard guard(self->m_lock); - - for (const shared_ptr& ptr: *(self->worker_list)) - result.push_back(ptr->get_tid()); - - return result; + m_threadCount = threads; } void @@ -758,52 +223,188 @@ Scheduler::yieldTo(bool yieldToCallerOnTerminate) { MORDOR_ASSERT(t_fiber); MORDOR_ASSERT(Scheduler::getThis() == this); - - // Ensure we're running inside the hihack worker (if we're transfering out) if (yieldToCallerOnTerminate) - MORDOR_ASSERT(dynamic_cast(t_worker)); - + MORDOR_ASSERT(m_rootThread == std::this_thread::get_id()); + if (t_fiber->state() != Fiber::HOLD) { + m_stopping = m_autoStop || m_stopping; + // XXX: is t_fiber the hijacked thread ? + t_fiber->reset(std::bind(&Scheduler::run, this)); + } t_fiber->yieldTo(yieldToCallerOnTerminate); } void -Scheduler::schedule(unique_ptr task) +Scheduler::run() { - unsigned prev = work_count.fetch_add(1, std::memory_order_relaxed); - MORDOR_LOG_DEBUG(g_log) << this << " Adding work " << task.get(); - - ReadGuard lock(m_lock); - - unsigned count = worker_list->size(); - shared_ptr* workers = worker_list->data(); + setThis(); + if (std::this_thread::get_id() != m_rootThread) { + // Running in own thread + t_fiber = Fiber::getThis().get(); + } else { + // Hijacked a thread + MORDOR_ASSERT(t_fiber == Fiber::getThis().get()); + } + Fiber::ptr idleFiber(new Fiber(std::bind(&Scheduler::idle, this))); + MORDOR_LOG_VERBOSE(g_log) << this << " starting thread with idle fiber " << idleFiber; + Fiber::ptr dgFiber; + // use a vector for O(1) .size() + std::vector batch; + batch.reserve(m_batchSize); + bool isActive = false; + while (true) { + MORDOR_ASSERT(batch.empty()); + bool dontIdle = false; + bool tickleMe = false; + { + boost::mutex::scoped_lock lock(m_mutex); + // Kill ourselves off if needed + if (m_threads.size() > m_threadCount && std::this_thread::get_id() != m_rootThread) { + // Accounting + if (isActive) + --m_activeThreadCount; + // Kill off the idle fiber + try { + throw boost::enable_current_exception( + OperationAbortedException()); + } catch(...) { + idleFiber->inject(boost::current_exception()); + } + // Detach our thread + for (std::vector > + ::iterator it = m_threads.begin(); + it != m_threads.end(); + ++it) + if ((*it)->tid() == std::this_thread::get_id()) { + m_threads.erase(it); + if (m_threads.size() > m_threadCount) + tickle(); + return; + } + MORDOR_NOTREACHED(); + } - if (task->thread != std::thread::id()) { - // Try to find the worker in the list - for (unsigned i = 0; i < count ; i++) { - if (workers[i]->get_tid() == task->thread) { - workers[i]->enqueue(std::move(task)); + std::list::iterator it(m_fibers.begin()); + while (it != m_fibers.end()) { + // If we've met our batch size, and we're not checking to see + // if we need to tickle another thread, then break + if ( (tickleMe || m_activeThreadCount == threadCount()) && + batch.size() == m_batchSize) + break; + if (it->thread != std::thread::id() && it->thread != std::this_thread::get_id()) { + MORDOR_LOG_DEBUG(g_log) << this + << " skipping item scheduled for thread " + << it->thread; + + // Wake up another thread to hopefully service this + tickleMe = true; + dontIdle = true; + ++it; + continue; + } + MORDOR_ASSERT(it->fiber || it->dg); + // This fiber is still executing; probably just some race + // race condition that it needs to yield on one thread + // before running on another thread + if (it->fiber && it->fiber->state() == Fiber::EXEC) { + MORDOR_LOG_DEBUG(g_log) << this + << " skipping executing fiber " << it->fiber; + ++it; + dontIdle = true; + continue; + } + // We were just checking if there is more work; there is, so + // set the flag and don't actually take this piece of work + if (batch.size() == m_batchSize) { + tickleMe = true; + break; + } + batch.push_back(*it); + it = m_fibers.erase(it); + if (!isActive) { + ++m_activeThreadCount; + isActive = true; + } + } + if (batch.empty() && isActive) { + --m_activeThreadCount; + isActive = false; + } + } + if (tickleMe) + tickle(); + MORDOR_LOG_DEBUG(g_log) << this + << " got " << batch.size() << " fiber/dgs to process (max: " + << m_batchSize << ", active: " << isActive << ")"; + MORDOR_ASSERT(isActive == !batch.empty()); + + if (batch.empty()) { + if (dontIdle) + continue; + + if (idleFiber->state() == Fiber::TERM) { + MORDOR_LOG_DEBUG(g_log) << this << " idle fiber terminated"; + if (std::this_thread::get_id() == m_rootThread) + m_callingFiber.reset(); + // Unblock the next thread + if (threadCount() > 1) + tickle(); return; } + MORDOR_LOG_DEBUG(g_log) << this << " idling"; + m_idleThreadCount++; + idleFiber->call(); + m_idleThreadCount--; + continue; } - } - // Round robin which worker we're going to use - unsigned which = prev % count; - workers[which]->enqueue(std::move(task)); - - m_lock.unlock(); - work_count.load(); -} - -void Scheduler::tickle() -{ - ReadGuard lock(m_lock); - - for (const shared_ptr& w: *worker_list) { - w->wakeup(); + while (!batch.empty()) { + FiberAndThread& ft = batch.back(); + Fiber::ptr f = ft.fiber; + std::function dg = ft.dg; + batch.pop_back(); + + try { + if (f && f->state() != Fiber::TERM) { + MORDOR_LOG_DEBUG(g_log) << this << " running " << f; + f->yieldTo(); + } else if (dg) { + if (dgFiber) + dgFiber->reset(dg); + else + dgFiber.reset(new Fiber(dg)); + MORDOR_LOG_DEBUG(g_log) << this << " running "; + dg = NULL; + dgFiber->yieldTo(); + if (dgFiber->state() != Fiber::TERM) + dgFiber.reset(); + else + dgFiber->reset(NULL); + } + } catch (...) { + try { + MORDOR_LOG_FATAL(Log::root()) + << boost::current_exception_diagnostic_information(); + } + catch(...) { + // Swallow any exceptions that might occur while trying to log the current fiber state #98680 + } + + { + boost::mutex::scoped_lock lock(m_mutex); + // push all un-executed fibers back to m_fibers + copy(batch.begin(), batch.end(), back_inserter(m_fibers)); + batch.clear(); + // decrease the activeCount as this thread is in exception + isActive = false; + --m_activeThreadCount; + } + throw; + } + } } } + SchedulerSwitcher::SchedulerSwitcher(Scheduler *target) { m_caller = Scheduler::getThis(); diff --git a/mordor/scheduler.h b/mordor/scheduler.h index 5a83182c..e125f3fb 100644 --- a/mordor/scheduler.h +++ b/mordor/scheduler.h @@ -2,17 +2,12 @@ #define __MORDOR_SCHEDULER_H__ // Copyright (c) 2009 - Mozy, Inc. -// C++ #include -#include #include #include -#include -// Boost -#include +#include -#include "fiber.h" #include "thread.h" namespace Mordor { @@ -33,13 +28,6 @@ class Fiber; /// stop(). stop() will return only after there are no more Fibers scheduled. class Scheduler { -public: - enum State { - RUNNING, - STOPPING, - STOPPED, - }; - public: /// Default constructor @@ -88,7 +76,7 @@ class Scheduler /// @param thread Optionally provide a specific thread for the Fiber to run /// on template - void schedule(FiberOrDg&& fd, std::thread::id thread = {}); + void schedule(FiberOrDg fd, std::thread::id thread = {}); /// Schedule multiple items to be executed at once @@ -130,16 +118,16 @@ class Scheduler /// @pre this is a hijacking Scheduler void dispatch(); - unsigned threadCount() const; + size_t threadCount() const; /// Change the number of threads in this scheduler - void threadCount(unsigned threads); + void threadCount(size_t threads); - // Get the list of thread ids in the current scheduler - const std::list threads() const; + const std::vector >& threads() const; -protected: + std::thread::id rootThreadId() const { return m_rootThread; } +protected: /// Derived classes can query stopping() to see if the Scheduler is trying /// to stop, and should return from the idle Fiber as soon as possible. /// @@ -154,68 +142,64 @@ class Scheduler /// /// Implementors should Fiber::yield() when it believes there is work /// scheduled on the Scheduler. - virtual void idle(const std::atomic& ec) = 0; + virtual void idle() = 0; /// The Scheduler wants to force the idle fiber to Fiber::yield(), because /// new work has been scheduled. + virtual void tickle() = 0; - virtual void tickle(const std::atomic& ec) = 0; + bool hasWorkToDo(); + virtual bool hasIdleThreads() const; + /// determine whether tickle() is needed, to be invoked in schedule() + /// @param empty whether m_fibers is empty before the new task is scheduled + virtual bool shouldTickle(bool empty) const; + + /// set `this' to TLS so that getThis() can get correct Scheduler + void setThis(); private: - Scheduler(const Scheduler& rhs) = delete; + void yieldTo(bool yieldToCallerOnTerminate); + void run(); + + /// @pre @c fd should be valid + /// @pre the task to be scheduled is not thread-targeted, or this scheduler + /// owns the targeted thread. + template + bool scheduleNoLock(FiberOrDg fd, std::thread::id thread = {}); -// Lockless queue (and queue entry) private: + Scheduler(const Scheduler& rhs) = delete; - struct Task - { - Fiber::ptr fiber; +private: + struct FiberAndThread { + std::shared_ptr fiber; std::function dg; std::thread::id thread; - Task(const Fiber::ptr& f, std::thread::id th) + FiberAndThread(std::shared_ptr f, std::thread::id th) : fiber(f), thread(th) { } - - Task(Fiber::ptr* f, std::thread::id th) + FiberAndThread(std::shared_ptr* f, std::thread::id th) : thread(th) { fiber.swap(*f); } - - Task(std::function d, std::thread::id th) + FiberAndThread(std::function d, std::thread::id th) : dg(d), thread(th) { } - - Task(std::function *d, std::thread::id th) + FiberAndThread(std::function *d, std::thread::id th) : thread(th) { dg.swap(*d); } }; - - // Worker classes (hidden from user) - struct Worker; - struct ThreadWorker; - struct HijackWorker; - friend struct Worker; - // - struct WorkerList; - -private: - void yieldTo(bool yieldToCallerOnTerminate); - void schedule(std::unique_ptr task); - -private: + static thread_local Scheduler* t_scheduler; static thread_local Fiber* t_fiber; - static thread_local Worker* t_worker; - - bool m_hijack; + boost::mutex m_mutex; + std::list m_fibers; + std::thread::id m_rootThread; + std::shared_ptr m_rootFiber; + std::shared_ptr m_callingFiber; + std::vector > m_threads; + size_t m_threadCount, m_activeThreadCount; + std::atomic m_idleThreadCount; + bool m_stopping; + bool m_autoStop; size_t m_batchSize; - unsigned m_threadCount; - - boost::shared_mutex m_lock; - - std::atomic m_state; - std::unique_ptr worker_list; - Fiber::ptr context; - - std::atomic work_count; - std::atomic done_count; }; /// Automatic Scheduler switcher @@ -240,17 +224,53 @@ struct SchedulerSwitcher // Implementation template -inline void Scheduler::schedule(FiberOrDg&& fd, std::thread::id tid) +inline void Scheduler::schedule(FiberOrDg fd, std::thread::id thread) { - std::unique_ptr task(new Task(std::forward(fd), tid)); - schedule(std::move(task)); + bool tickleMe; + { + boost::mutex::scoped_lock lock(m_mutex); + tickleMe = scheduleNoLock(fd, thread); + } + if (shouldTickle(tickleMe)) + tickle(); } template inline void Scheduler::schedule(InputIterator begin, InputIterator end) { - for (; begin != end; ++begin) - schedule(&*begin); + bool tickleMe = false; + { + boost::mutex::scoped_lock lock(m_mutex); + while (begin != end) { + tickleMe = scheduleNoLock(&*begin) || tickleMe; + ++begin; + } + } + if (shouldTickle(tickleMe)) + tickle(); +} + +inline size_t Scheduler::threadCount() const +{ return m_threadCount + (m_rootFiber ? 1 : 0); } + +inline const std::vector >& Scheduler::threads() const +{ return m_threads; } + +inline void Scheduler::setThis() +{ t_scheduler = this; } + +inline bool Scheduler::hasIdleThreads() const +{ return m_idleThreadCount != 0; } + +inline bool Scheduler::shouldTickle(bool empty) const +{ return empty && Scheduler::getThis() != this; } + +template +inline bool Scheduler::scheduleNoLock(FiberOrDg fd, std::thread::id thread) +{ + bool tickleMe = m_fibers.empty(); + m_fibers.push_back(FiberAndThread(fd, thread)); + return tickleMe; } } // namespace: Mordor diff --git a/mordor/thread.h b/mordor/thread.h index 9fe7bfbb..ba67939e 100644 --- a/mordor/thread.h +++ b/mordor/thread.h @@ -2,9 +2,7 @@ #define __MORDOR_THREAD_H__ // Copyright (c) 2010 - Mozy, Inc. -// C++ #include -#include #include #include "version.h" @@ -21,10 +19,8 @@ class Thread /// /// bookmark current thread id and scheduler, allow to switch back to /// the same thread id later. - /// /// @pre The process must be running with available scheduler, otherwise /// it is not possible to switch execution between threads with bookmark. - /// /// @note Bookmark was designed to address the issue where we failed to /// rethrow an exception in catch block, because GCC C++ runtime saves the /// exception stack in a pthread TLS variable. and swapcontext(3) does not diff --git a/mordor/workerpool.cpp b/mordor/workerpool.cpp index b915f05b..df1e21e4 100644 --- a/mordor/workerpool.cpp +++ b/mordor/workerpool.cpp @@ -1,8 +1,7 @@ // Copyright (c) 2009 - Mozy, Inc. -#include - #include "workerpool.h" + #include "fiber.h" #include "log.h" @@ -17,12 +16,13 @@ WorkerPool::WorkerPool(size_t threads, bool useCaller, size_t batchSize) } void -WorkerPool::idle(const std::atomic& ec) +WorkerPool::idle() { - while (stopping()) { - int* uaddr = reinterpret_cast(&ec); - sys_futex(uaddr, FUTEX_WAIT, 1, nullptr, nullptr, 0); - + while (true) { + if (stopping()) { + return; + } + m_semaphore.wait(); try { Fiber::yield(); } catch (OperationAbortedException &) { @@ -32,12 +32,10 @@ WorkerPool::idle(const std::atomic& ec) } void -WorkerPool::tickle(const std::atomic& ec) +WorkerPool::tickle() { - int* uaddr = reinterpret_cast(&ec); - MORDOR_LOG_DEBUG(g_log) << this << " tickling"; - sys_futex(uaddr, FUTEX_WAKE, 1, nullptr, nullptr, 0); + m_semaphore.notify(); } } diff --git a/mordor/workerpool.h b/mordor/workerpool.h index 557ffa57..fb24e21b 100644 --- a/mordor/workerpool.h +++ b/mordor/workerpool.h @@ -21,9 +21,9 @@ class WorkerPool : public Scheduler /// The idle Fiber for a WorkerPool simply loops waiting on a Semaphore, /// and yields whenever that Semaphore is signalled, returning if /// stopping() is true. - void idle(const std::atomic& ec); + void idle(); /// Signals the semaphore so that the idle Fiber will yield. - void tickle(const std::atomic& ec); + void tickle(); private: Semaphore m_semaphore; From 4a4f14f4bbe59c3c696305ed881527c7b7073a1f Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Thu, 16 Feb 2017 13:29:10 -0500 Subject: [PATCH 11/12] FIX: Non-issue Warning turned to error (Werror) GCC warning about bad if statement formating leading to confusing code (bugs). Doesn't impact this case, so reformat to make GCC happy. --- mordor/http/http.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mordor/http/http.h b/mordor/http/http.h index e0bfbe3a..5292bbb7 100644 --- a/mordor/http/http.h +++ b/mordor/http/http.h @@ -160,21 +160,25 @@ struct Version } bool operator<(const Version& rhs) const { - if (major < rhs.major) return true; return minor < rhs.minor; + if (major < rhs.major) return true; + return minor < rhs.minor; } bool operator<=(const Version& rhs) const { if (major > rhs.major) return false; - if (major < rhs.major) return true; return minor <= rhs.minor; + if (major < rhs.major) return true; + return minor <= rhs.minor; } bool operator>(const Version& rhs) const { - if (major > rhs.major) return true; return minor > rhs.minor; + if (major > rhs.major) return true; + return minor > rhs.minor; } bool operator>=(const Version& rhs) const { if (major < rhs.major) return false; - if (major > rhs.major) return true; return minor >= rhs.minor; + if (major > rhs.major) return true; + return minor >= rhs.minor; } }; From cdd7cecf23013436ba01ec2b07829a26ccaca3b7 Mon Sep 17 00:00:00 2001 From: Milosz Tanski Date: Fri, 17 Feb 2017 13:19:27 -0500 Subject: [PATCH 12/12] FIX BUILD: noexpect(false) on a lot of destructors C++11 makes them noexcept by default and mordor sprinkles a lot of ASSERTS. --- mordor/examples/netbench.h | 4 ++-- mordor/fiber.cpp | 2 +- mordor/fiber.h | 2 +- mordor/fibersynchronization.cpp | 8 ++++---- mordor/fibersynchronization.h | 8 ++++---- mordor/http/broker.h | 2 +- mordor/http/client.cpp | 2 +- mordor/http/client.h | 2 +- mordor/iomanager_epoll.cpp | 4 ++-- mordor/iomanager_epoll.h | 4 ++-- mordor/scheduler.cpp | 2 +- mordor/scheduler.h | 2 +- mordor/semaphore.cpp | 2 +- mordor/semaphore.h | 2 +- mordor/streams/stream.h | 2 +- mordor/timer.cpp | 2 +- mordor/timer.h | 2 +- 17 files changed, 26 insertions(+), 26 deletions(-) diff --git a/mordor/examples/netbench.h b/mordor/examples/netbench.h index e183093a..9a79d520 100644 --- a/mordor/examples/netbench.h +++ b/mordor/examples/netbench.h @@ -6,7 +6,7 @@ class NetBenchServer { public: - virtual ~NetBenchServer() {} + virtual ~NetBenchServer() noexcept(false) {} // start the implementation of the server to be benchmarked virtual void run(std::string& host, @@ -21,7 +21,7 @@ class NetBenchServer class NetBenchClient { public: - virtual ~NetBenchClient () {} + virtual ~NetBenchClient () noexcept(false) {} // initialize the client to be benchmarked virtual void init(std::string& host, diff --git a/mordor/fiber.cpp b/mordor/fiber.cpp index beccb827..f453c409 100644 --- a/mordor/fiber.cpp +++ b/mordor/fiber.cpp @@ -103,7 +103,7 @@ Fiber::Fiber(std::function dg, size_t stacksize) g_statMaxFibers.update(++g_cntFibers); } -Fiber::~Fiber() +Fiber::~Fiber() noexcept(false) { --g_cntFibers; if (!stack_ptr() ) { diff --git a/mordor/fiber.h b/mordor/fiber.h index ef3c939d..9eb757b2 100644 --- a/mordor/fiber.h +++ b/mordor/fiber.h @@ -52,7 +52,7 @@ class Fiber final : public std::enable_shared_from_this, private internal /// are touched by the Fiber executing /// @post state() == INIT Fiber(std::function dg, size_t stacksize = 0); - ~Fiber(); + ~Fiber() noexcept(false); /// @brief Reset a Fiber to be used again, with a different initial function /// @param dg The new initial function diff --git a/mordor/fibersynchronization.cpp b/mordor/fibersynchronization.cpp index 2314ca05..bfd14764 100644 --- a/mordor/fibersynchronization.cpp +++ b/mordor/fibersynchronization.cpp @@ -8,7 +8,7 @@ namespace Mordor { -FiberMutex::~FiberMutex() +FiberMutex::~FiberMutex() noexcept(false) { #ifndef NDEBUG boost::mutex::scoped_lock scopeLock(m_mutex); @@ -80,7 +80,7 @@ FiberSemaphore::FiberSemaphore(size_t initialConcurrency) : m_concurrency(initialConcurrency) {} -FiberSemaphore::~FiberSemaphore() +FiberSemaphore::~FiberSemaphore() noexcept(false) { #ifndef NDEBUG boost::mutex::scoped_lock scopeLock(m_mutex); @@ -126,7 +126,7 @@ FiberSemaphore::notify() } } -FiberCondition::~FiberCondition() +FiberCondition::~FiberCondition() noexcept(false) { #ifndef NDEBUG boost::mutex::scoped_lock lock(m_mutex); @@ -205,7 +205,7 @@ FiberCondition::broadcast() } -FiberEvent::~FiberEvent() +FiberEvent::~FiberEvent() noexcept(false) { #ifndef NDEBUG boost::mutex::scoped_lock lock(m_mutex); diff --git a/mordor/fibersynchronization.h b/mordor/fibersynchronization.h index eccda6b8..d520aac6 100644 --- a/mordor/fibersynchronization.h +++ b/mordor/fibersynchronization.h @@ -87,7 +87,7 @@ struct FiberMutex public: FiberMutex() = default; - ~FiberMutex(); + ~FiberMutex() noexcept(false); /// @brief Locks the mutex /// Note that it is possible for this Fiber to switch threads after this @@ -128,7 +128,7 @@ struct FiberSemaphore { public: FiberSemaphore(size_t initialConcurrency = 0); - ~FiberSemaphore(); + ~FiberSemaphore() noexcept(false); /// @brief Waits for the semaphore /// Decreases the amount of concurrency. If concurrency is already at @@ -162,7 +162,7 @@ struct FiberCondition FiberCondition(FiberMutex &mutex) : m_fiberMutex(mutex) {} - ~FiberCondition(); + ~FiberCondition() noexcept(false); /// @brief Wait for the Condition to be signalled /// @details @@ -201,7 +201,7 @@ struct FiberEvent : m_signalled(false), m_autoReset(autoReset) {} - ~FiberEvent(); + ~FiberEvent() noexcept(false); /// @brief Wait for the Event to become set /// @pre Scheduler::getThis() != NULL diff --git a/mordor/http/broker.h b/mordor/http/broker.h index 65559631..6bfd71f6 100644 --- a/mordor/http/broker.h +++ b/mordor/http/broker.h @@ -115,7 +115,7 @@ class ConnectionBroker m_sslCtx(NULL), m_timerManager(NULL) {} - virtual ~ConnectionBroker() {} + virtual ~ConnectionBroker() noexcept(false) {} virtual std::pair, bool> getConnection(const URI &uri, bool forceNewConnection = false) = 0; diff --git a/mordor/http/client.cpp b/mordor/http/client.cpp index 22135128..429586d6 100644 --- a/mordor/http/client.cpp +++ b/mordor/http/client.cpp @@ -499,7 +499,7 @@ ClientRequest::ClientRequest(ClientConnection::ptr conn, const Request &request) MORDOR_ASSERT(m_conn); } -ClientRequest::~ClientRequest() +ClientRequest::~ClientRequest() noexcept(false) { cancel(true); #ifndef NDEBUG diff --git a/mordor/http/client.h b/mordor/http/client.h index da447d9e..586234ed 100644 --- a/mordor/http/client.h +++ b/mordor/http/client.h @@ -58,7 +58,7 @@ class ClientRequest : public std::enable_shared_from_this ClientRequest(const ClientRequest& rhs) = delete; public: - ~ClientRequest(); + ~ClientRequest() noexcept(false); std::shared_ptr connection() { return m_conn; } State requestState() const { return m_requestState; } diff --git a/mordor/iomanager_epoll.cpp b/mordor/iomanager_epoll.cpp index 5e0dbebf..948e97fa 100644 --- a/mordor/iomanager_epoll.cpp +++ b/mordor/iomanager_epoll.cpp @@ -99,7 +99,7 @@ IOManager::AsyncState::AsyncState() m_events(NONE) {} -IOManager::AsyncState::~AsyncState() +IOManager::AsyncState::~AsyncState() noexcept(false) { boost::mutex::scoped_lock lock(m_mutex); MORDOR_ASSERT(!m_events); @@ -218,7 +218,7 @@ IOManager::IOManager(size_t threads, bool useCaller, bool autoStart) } } -IOManager::~IOManager() +IOManager::~IOManager() noexcept(false) { stop(); close(m_epfd); diff --git a/mordor/iomanager_epoll.h b/mordor/iomanager_epoll.h index 93bcdc71..a616346c 100644 --- a/mordor/iomanager_epoll.h +++ b/mordor/iomanager_epoll.h @@ -30,7 +30,7 @@ class IOManager : public Scheduler, public TimerManager struct AsyncState { AsyncState(); - ~AsyncState(); + ~AsyncState() noexcept(false); AsyncState(const AsyncState& rhs) = delete; struct EventContext @@ -59,7 +59,7 @@ class IOManager : public Scheduler, public TimerManager /// @note @p autoStart provides a more friendly behavior for derived class /// that inherits from IOManager IOManager(size_t threads = 1, bool useCaller = true, bool autoStart = true); - ~IOManager(); + ~IOManager() noexcept(false); bool stopping(); diff --git a/mordor/scheduler.cpp b/mordor/scheduler.cpp index f892a59b..81d3bb56 100644 --- a/mordor/scheduler.cpp +++ b/mordor/scheduler.cpp @@ -34,7 +34,7 @@ Scheduler::Scheduler(size_t threads, bool useCaller, size_t batchSize) m_threadCount = threads; } -Scheduler::~Scheduler() +Scheduler::~Scheduler() noexcept(false) { MORDOR_ASSERT(m_stopping); if (getThis() == this) { diff --git a/mordor/scheduler.h b/mordor/scheduler.h index e125f3fb..2532edf4 100644 --- a/mordor/scheduler.h +++ b/mordor/scheduler.h @@ -43,7 +43,7 @@ class Scheduler /// @pre if (useCaller == true) Scheduler::getThis() == NULL Scheduler(size_t threads = 1, bool useCaller = true, size_t batchSize = 1); /// Destroys the scheduler, implicitly calling stop() - virtual ~Scheduler(); + virtual ~Scheduler() noexcept(false); /// @return The Scheduler controlling the currently executing thread static Scheduler* getThis(); diff --git a/mordor/semaphore.cpp b/mordor/semaphore.cpp index cfbeb49c..51c702cc 100644 --- a/mordor/semaphore.cpp +++ b/mordor/semaphore.cpp @@ -50,7 +50,7 @@ Semaphore::Semaphore(unsigned int count) #endif } -Semaphore::~Semaphore() +Semaphore::~Semaphore() noexcept(false) { #ifdef WINDOWS MORDOR_VERIFY(CloseHandle(m_semaphore)); diff --git a/mordor/semaphore.h b/mordor/semaphore.h index 5d525e45..e3057733 100644 --- a/mordor/semaphore.h +++ b/mordor/semaphore.h @@ -21,7 +21,7 @@ class Semaphore public: Semaphore(unsigned int count = 0); Semaphore(const Semaphore& rhs) = delete; - ~Semaphore(); + ~Semaphore() noexcept(false); void wait(); diff --git a/mordor/streams/stream.h b/mordor/streams/stream.h index c95179f5..ef47c194 100644 --- a/mordor/streams/stream.h +++ b/mordor/streams/stream.h @@ -59,7 +59,7 @@ class Stream /// Cleans up the underlying implementation, possibly by ungracefully /// closing it. - virtual ~Stream() {} + virtual ~Stream() noexcept(false) {} /// @return If it is valid to call close() with READ or WRITE virtual bool supportsHalfClose() { return false; } diff --git a/mordor/timer.cpp b/mordor/timer.cpp index b4608a00..20f77e02 100644 --- a/mordor/timer.cpp +++ b/mordor/timer.cpp @@ -169,7 +169,7 @@ TimerManager::TimerManager() m_previousTime(0ull) {} -TimerManager::~TimerManager() +TimerManager::~TimerManager() noexcept(false) { #ifndef NDEBUG boost::mutex::scoped_lock lock(m_mutex); diff --git a/mordor/timer.h b/mordor/timer.h index 3a671f1d..debb0c01 100644 --- a/mordor/timer.h +++ b/mordor/timer.h @@ -62,7 +62,7 @@ class TimerManager public: TimerManager(); TimerManager(const TimerManager& rhs) = delete; - virtual ~TimerManager(); + virtual ~TimerManager() noexcept(false); virtual Timer::ptr registerTimer(unsigned long long us, std::function dg, bool recurring = false);