diff --git a/.gitignore b/.gitignore
index 1a834f299e..5e162614aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ Docs
*.manifest
*.manifest.res
*.o
+*.opensdf
*.d
*.sdf
xcuserdata
@@ -24,5 +25,5 @@ contents.xcworkspacedata
profile
Builds/VisualStudio2012/Debug
Builds/VisualStudio2012/Release
-
+project.xcworkspace
modules/beast_cryptopp
diff --git a/demos/unittests/.gitignore b/demos/unittests/.gitignore
new file mode 100644
index 0000000000..cf321b73d0
--- /dev/null
+++ b/demos/unittests/.gitignore
@@ -0,0 +1,2 @@
+builds/vs2012/Debug
+builds/vs2012/Release
diff --git a/demos/unittests/builds/vs2012/unittests.filters b/demos/unittests/builds/vs2012/unittests.filters
new file mode 100644
index 0000000000..6ff4acf0ba
--- /dev/null
+++ b/demos/unittests/builds/vs2012/unittests.filters
@@ -0,0 +1,19 @@
+
+
+
+
+
+ shared
+
+
+
+
+ {986861c7-f1e7-4a41-bea0-eede68819634}
+
+
+
+
+ shared
+
+
+
\ No newline at end of file
diff --git a/demos/unittests/builds/vs2012/unittests.vcxproj b/demos/unittests/builds/vs2012/unittests.vcxproj
new file mode 100644
index 0000000000..2164c4aac7
--- /dev/null
+++ b/demos/unittests/builds/vs2012/unittests.vcxproj
@@ -0,0 +1,93 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {36E40B92-F578-4599-9909-70952176D18A}
+ Win32Proj
+
+
+
+
+
+ Application
+ true
+ v110
+ Unicode
+
+
+ Application
+ false
+ v110
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ $(ProjectDir)..\..\..\..\config;$(ProjectDir)..\..\..\..;$(ProjectDir)..\..\..\beast;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ $(ProjectDir)..\..\..\..\config;$(ProjectDir)..\..\..\..;$(ProjectDir)..\..\..\beast
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/unittests/builds/xcode/unittests.xcodeproj/project.pbxproj b/demos/unittests/builds/xcode/unittests.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..8a75f50998
--- /dev/null
+++ b/demos/unittests/builds/xcode/unittests.xcodeproj/project.pbxproj
@@ -0,0 +1,269 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ CD0A5B3F181707F700DA0342 /* mac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD0A5B3E181707F700DA0342 /* mac.cpp */; };
+ CD0A5B421817097800DA0342 /* BeastUnitTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD0A5B401817097800DA0342 /* BeastUnitTests.cpp */; };
+ CD0A5B4918170DC300DA0342 /* beast.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD0A5B4818170DC300DA0342 /* beast.mm */; };
+ CD0A5B4B18170EBC00DA0342 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD0A5B4A18170EBC00DA0342 /* CoreServices.framework */; };
+ CD0A5B4E18170F0D00DA0342 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD0A5B4D18170F0D00DA0342 /* AppKit.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ CD0A5B301817074500DA0342 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ CD0A5B321817074500DA0342 /* unittests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unittests; sourceTree = BUILT_PRODUCTS_DIR; };
+ CD0A5B3E181707F700DA0342 /* mac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mac.cpp; path = ../../src/mac.cpp; sourceTree = ""; };
+ CD0A5B401817097800DA0342 /* BeastUnitTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BeastUnitTests.cpp; path = ../../src/BeastUnitTests.cpp; sourceTree = ""; };
+ CD0A5B411817097800DA0342 /* BeastUnitTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BeastUnitTests.h; path = ../../src/BeastUnitTests.h; sourceTree = ""; };
+ CD0A5B4318170A5100DA0342 /* beast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = beast.cpp; path = ../../src/beast.cpp; sourceTree = ""; };
+ CD0A5B4418170A5100DA0342 /* beast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = beast.h; path = ../../src/beast.h; sourceTree = ""; };
+ CD0A5B4818170DC300DA0342 /* beast.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = beast.mm; path = ../../src/beast.mm; sourceTree = ""; };
+ CD0A5B4A18170EBC00DA0342 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
+ CD0A5B4D18170F0D00DA0342 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+ CD0A5B4F181714A000DA0342 /* beast */ = {isa = PBXFileReference; lastKnownFileType = folder; name = beast; path = ../../../../beast; sourceTree = ""; };
+ CD0A5B50181714B800DA0342 /* modules */ = {isa = PBXFileReference; lastKnownFileType = folder; name = modules; path = ../../../../modules; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ CD0A5B2F1817074500DA0342 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CD0A5B4E18170F0D00DA0342 /* AppKit.framework in Frameworks */,
+ CD0A5B4B18170EBC00DA0342 /* CoreServices.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ CD0A5B291817074500DA0342 = {
+ isa = PBXGroup;
+ children = (
+ CD0A5B50181714B800DA0342 /* modules */,
+ CD0A5B4F181714A000DA0342 /* beast */,
+ CD0A5B4818170DC300DA0342 /* beast.mm */,
+ CD0A5B4318170A5100DA0342 /* beast.cpp */,
+ CD0A5B4418170A5100DA0342 /* beast.h */,
+ CD0A5B401817097800DA0342 /* BeastUnitTests.cpp */,
+ CD0A5B411817097800DA0342 /* BeastUnitTests.h */,
+ CD0A5B3E181707F700DA0342 /* mac.cpp */,
+ CD0A5B4C18170EC600DA0342 /* Frameworks */,
+ CD0A5B331817074500DA0342 /* Products */,
+ );
+ sourceTree = "";
+ };
+ CD0A5B331817074500DA0342 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CD0A5B321817074500DA0342 /* unittests */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ CD0A5B4C18170EC600DA0342 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ CD0A5B4D18170F0D00DA0342 /* AppKit.framework */,
+ CD0A5B4A18170EBC00DA0342 /* CoreServices.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ CD0A5B311817074500DA0342 /* unittests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CD0A5B3B1817074500DA0342 /* Build configuration list for PBXNativeTarget "unittests" */;
+ buildPhases = (
+ CD0A5B2E1817074500DA0342 /* Sources */,
+ CD0A5B2F1817074500DA0342 /* Frameworks */,
+ CD0A5B301817074500DA0342 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = unittests;
+ productName = unittests;
+ productReference = CD0A5B321817074500DA0342 /* unittests */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ CD0A5B2A1817074500DA0342 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0500;
+ ORGANIZATIONNAME = "Patrick Dehne";
+ };
+ buildConfigurationList = CD0A5B2D1817074500DA0342 /* Build configuration list for PBXProject "unittests" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = CD0A5B291817074500DA0342;
+ productRefGroup = CD0A5B331817074500DA0342 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ CD0A5B311817074500DA0342 /* unittests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ CD0A5B2E1817074500DA0342 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CD0A5B3F181707F700DA0342 /* mac.cpp in Sources */,
+ CD0A5B421817097800DA0342 /* BeastUnitTests.cpp in Sources */,
+ CD0A5B4918170DC300DA0342 /* beast.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ CD0A5B391817074500DA0342 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = NO;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../../config",
+ "$(SRCROOT)/../../../..",
+ "$(SRCROOT)/../../../../beast",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.8;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ CD0A5B3A1817074500DA0342 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = NO;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../../config",
+ "$(SRCROOT)/../../../..",
+ "$(SRCROOT)/../../../../beast",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.8;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ CD0A5B3C1817074500DA0342 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ CD0A5B3D1817074500DA0342 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ CD0A5B2D1817074500DA0342 /* Build configuration list for PBXProject "unittests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CD0A5B391817074500DA0342 /* Debug */,
+ CD0A5B3A1817074500DA0342 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CD0A5B3B1817074500DA0342 /* Build configuration list for PBXNativeTarget "unittests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CD0A5B3C1817074500DA0342 /* Debug */,
+ CD0A5B3D1817074500DA0342 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = CD0A5B2A1817074500DA0342 /* Project object */;
+}
diff --git a/demos/unittests/src/BeastUnitTests.cpp b/demos/unittests/src/BeastUnitTests.cpp
new file mode 100644
index 0000000000..25c90f975e
--- /dev/null
+++ b/demos/unittests/src/BeastUnitTests.cpp
@@ -0,0 +1,79 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "BeastUnitTests.h"
+
+class BeastUnitTests : public beast::UnitTests
+{
+public:
+ explicit BeastUnitTests (bool shouldLog)
+ : m_shouldLog (shouldLog)
+ {
+ }
+
+ void logMessage (beast::String const& message)
+ {
+ if (m_shouldLog)
+ std::cout << message.toStdString () << std::endl;
+ }
+
+private:
+ bool const m_shouldLog;
+};
+
+int runUnitTests (beast::String const& match, beast::String const& format)
+{
+ bool const shouldLog = format != "junit";
+
+ if (format != "junit" && format != "text" && format != "")
+ {
+ beast::String s;
+ s << "Warning, unknown unittest-format='" << format << "'";
+ // Log::out () << s.toStdString ();
+ }
+
+ BeastUnitTests tr (shouldLog);
+
+ tr.runSelectedTests (match);
+
+ if (format == "junit")
+ {
+ beast::UnitTestUtilities::JUnitXMLFormatter f (tr);
+
+ beast::String const s = f.createDocumentString ();
+
+ std::cout << s.toStdString ();
+ }
+ else
+ {
+ beast::UnitTests::Results const& r (tr.getResults ());
+
+ beast::String s;
+
+ s << "Summary: " <<
+ beast::String (r.suites.size ()) << " suites, " <<
+ beast::String (r.cases) << " cases, " <<
+ beast::String (r.tests) << " tests, " <<
+ beast::String (r.failures) << " failure" << ((r.failures != 1) ? "s" : "") << ".";
+
+ tr.logMessage (s);
+ }
+
+ return tr.anyTestsFailed () ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/demos/unittests/src/BeastUnitTests.h b/demos/unittests/src/BeastUnitTests.h
new file mode 100644
index 0000000000..e3b20b0843
--- /dev/null
+++ b/demos/unittests/src/BeastUnitTests.h
@@ -0,0 +1,27 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+//==============================================================================
+
+#ifndef UNITTESTS_BEASTUNITTESTS_H_INCLUDED
+#define UNITTESTS_BEASTUNITTESTS_H_INCLUDED
+
+#include "beast.h"
+
+int runUnitTests (beast::String const& match, beast::String const& format);
+
+#endif
diff --git a/demos/unittests/src/beast.cpp b/demos/unittests/src/beast.cpp
new file mode 100644
index 0000000000..e424d93efc
--- /dev/null
+++ b/demos/unittests/src/beast.cpp
@@ -0,0 +1,31 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "beast.h"
+
+#include "modules/beast_core/beast_core.cpp"
+#include "modules/beast_vflib/beast_vflib.cpp"
+
+#include "beast/chrono/Chrono.cpp"
+#include "beast/crypto/Crypto.cpp"
+#include "beast/strings/Strings.cpp"
+#include "beast/threads/Threads.cpp"
+// #include "beast/http/HTTP.cpp"
+#include "beast/net/Net.cpp"
+#include "beast/utility/Utility.cpp"
diff --git a/demos/unittests/src/beast.h b/demos/unittests/src/beast.h
new file mode 100644
index 0000000000..351fb0a2a4
--- /dev/null
+++ b/demos/unittests/src/beast.h
@@ -0,0 +1,33 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef UNITTESTS_BEAST_H_INCLUDED
+#define UNITTESTS_BEAST_H_INCLUDED
+
+#include "BeastConfig.h"
+
+#include "modules/beast_core/beast_core.h"
+#include "modules/beast_vflib/beast_vflib.h"
+
+#include "beast/Strings.h"
+#include "beast/Threads.h"
+#include "beast/SmartPtr.h"
+#include "beast/Chrono.h"
+
+#endif
diff --git a/demos/unittests/src/beast.mm b/demos/unittests/src/beast.mm
new file mode 100644
index 0000000000..566db5b523
--- /dev/null
+++ b/demos/unittests/src/beast.mm
@@ -0,0 +1,20 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "beast.cpp"
diff --git a/demos/unittests/src/mac.cpp b/demos/unittests/src/mac.cpp
new file mode 100644
index 0000000000..2e13ce4792
--- /dev/null
+++ b/demos/unittests/src/mac.cpp
@@ -0,0 +1,25 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "BeastUnitTests.h"
+
+int main(int argc, const char * argv[])
+{
+ return runUnitTests("", "text");
+}
diff --git a/demos/unittests/src/win32.cpp b/demos/unittests/src/win32.cpp
new file mode 100644
index 0000000000..7fe103a845
--- /dev/null
+++ b/demos/unittests/src/win32.cpp
@@ -0,0 +1,11 @@
+#include
+#include
+
+#include "BeastUnitTests.h"
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ runUnitTests("", "text");
+
+ return 0;
+}
diff --git a/modules/beast_core/native/mac_Network.mm b/modules/beast_core/native/mac_Network.mm
index 4002e97ab0..b8e2d74ae5 100644
--- a/modules/beast_core/native/mac_Network.mm
+++ b/modules/beast_core/native/mac_Network.mm
@@ -21,8 +21,6 @@
*/
//==============================================================================
-#include "../network/URL.h"
-
void MACAddress::findAllAddresses (Array& result)
{
ifaddrs* addrs = nullptr;
@@ -97,202 +95,3 @@ bool Process::openEmailWithAttachments (const String& targetEmailAddress,
}
#endif
}
-
-//==============================================================================
-class URLConnectionState
- : public Thread
- , LeakChecked
- , public Uncopyable
-{
-public:
- URLConnectionState (NSURLRequest* req)
- : Thread ("http connection"),
- contentLength (-1),
- delegate (nil),
- request ([req retain]),
- connection (nil),
- data ([[NSMutableData data] retain]),
- headers (nil),
- initialised (false),
- hasFailed (false),
- hasFinished (false)
- {
- static DelegateClass cls;
- delegate = [cls.createInstance() init];
- DelegateClass::setState (delegate, this);
- }
-
- ~URLConnectionState()
- {
- stop();
- [connection release];
- [data release];
- [request release];
- [headers release];
- [delegate release];
- }
-
- bool start (URL::OpenStreamProgressCallback* callback, void* context)
- {
- startThread();
-
- while (isThreadRunning() && ! initialised)
- {
- if (callback != nullptr)
- callback (context, -1, (int) [[request HTTPBody] length]);
-
- Thread::sleep (1);
- }
-
- return connection != nil && ! hasFailed;
- }
-
- void stop()
- {
- [connection cancel];
- stopThread (10000);
- }
-
- int read (char* dest, int numBytes)
- {
- int numDone = 0;
-
- while (numBytes > 0)
- {
- const int available = bmin (numBytes, (int) [data length]);
-
- if (available > 0)
- {
- const ScopedLock sl (dataLock);
- [data getBytes: dest length: (NSUInteger) available];
- [data replaceBytesInRange: NSMakeRange (0, (NSUInteger) available) withBytes: nil length: 0];
-
- numDone += available;
- numBytes -= available;
- dest += available;
- }
- else
- {
- if (hasFailed || hasFinished)
- break;
-
- Thread::sleep (1);
- }
- }
-
- return numDone;
- }
-
- void didReceiveResponse (NSURLResponse* response)
- {
- {
- const ScopedLock sl (dataLock);
- [data setLength: 0];
- }
-
- initialised = true;
- contentLength = [response expectedContentLength];
-
- [headers release];
- headers = nil;
-
- if ([response isKindOfClass: [NSHTTPURLResponse class]])
- headers = [[((NSHTTPURLResponse*) response) allHeaderFields] retain];
- }
-
- void didFailWithError (NSError* error)
- {
- DBG (nsStringToBeast ([error description])); (void) error;
- hasFailed = true;
- initialised = true;
- signalThreadShouldExit();
- }
-
- void didReceiveData (NSData* newData)
- {
- const ScopedLock sl (dataLock);
- [data appendData: newData];
- initialised = true;
- }
-
- void didSendBodyData (int /*totalBytesWritten*/, int /*totalBytesExpected*/)
- {
- }
-
- void finishedLoading()
- {
- hasFinished = true;
- initialised = true;
- signalThreadShouldExit();
- }
-
- void run() override
- {
- connection = [[NSURLConnection alloc] initWithRequest: request
- delegate: delegate];
- while (! threadShouldExit())
- {
- BEAST_AUTORELEASEPOOL
- {
- [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
- }
- }
- }
-
- int64 contentLength;
- CriticalSection dataLock;
- NSObject* delegate;
- NSURLRequest* request;
- NSURLConnection* connection;
- NSMutableData* data;
- NSDictionary* headers;
- bool initialised, hasFailed, hasFinished;
-
-private:
- //==============================================================================
- struct DelegateClass : public ObjCClass
- {
- DelegateClass() : ObjCClass ("BEASTAppDelegate_")
- {
- addIvar ("state");
-
- addMethod (@selector (connection:didReceiveResponse:), didReceiveResponse, "v@:@@");
- addMethod (@selector (connection:didFailWithError:), didFailWithError, "v@:@@");
- addMethod (@selector (connection:didReceiveData:), didReceiveData, "v@:@@");
- addMethod (@selector (connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:totalBytesExpectedToWrite:),
- connectionDidSendBodyData, "v@:@iii");
- addMethod (@selector (connectionDidFinishLoading:), connectionDidFinishLoading, "v@:@");
-
- registerClass();
- }
-
- static void setState (id self, URLConnectionState* state) { object_setInstanceVariable (self, "state", state); }
- static URLConnectionState* getState (id self) { return getIvar (self, "state"); }
-
- private:
- static void didReceiveResponse (id self, SEL, NSURLConnection*, NSURLResponse* response)
- {
- getState (self)->didReceiveResponse (response);
- }
-
- static void didFailWithError (id self, SEL, NSURLConnection*, NSError* error)
- {
- getState (self)->didFailWithError (error);
- }
-
- static void didReceiveData (id self, SEL, NSURLConnection*, NSData* newData)
- {
- getState (self)->didReceiveData (newData);
- }
-
- static void connectionDidSendBodyData (id self, SEL, NSURLConnection*, NSInteger, NSInteger totalBytesWritten, NSInteger totalBytesExpected)
- {
- getState (self)->didSendBodyData (totalBytesWritten, totalBytesExpected);
- }
-
- static void connectionDidFinishLoading (id self, SEL, NSURLConnection*)
- {
- getState (self)->finishedLoading();
- }
- };
-};
diff --git a/modules/beast_vflib/beast_vflib.cpp b/modules/beast_vflib/beast_vflib.cpp
new file mode 100644
index 0000000000..94e2c88a0f
--- /dev/null
+++ b/modules/beast_vflib/beast_vflib.cpp
@@ -0,0 +1,22 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "beast_vflib.h"
+
+#include "threads/ThreadWithServiceQueue.cpp"
diff --git a/modules/beast_vflib/beast_vflib.h b/modules/beast_vflib/beast_vflib.h
new file mode 100644
index 0000000000..6582169d41
--- /dev/null
+++ b/modules/beast_vflib/beast_vflib.h
@@ -0,0 +1,27 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of BeastUtils: https://github.com/pdehne/BeastUtils
+ Copyright 2013, Patrick Dehne
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+//==============================================================================
+
+#ifndef BEAST_VFLIB_H_INCLUDED
+#define BEAST_VFLIB_H_INCLUDED
+
+#include "functor/BindHelper.h"
+#include "threads/BindableServiceQueue.h"
+#include "threads/ThreadWithServiceQueue.h"
+
+#endif
diff --git a/modules/beast_vflib/functor/BindHelper.h b/modules/beast_vflib/functor/BindHelper.h
new file mode 100644
index 0000000000..0247592f64
--- /dev/null
+++ b/modules/beast_vflib/functor/BindHelper.h
@@ -0,0 +1,78 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+//==============================================================================
+
+#ifndef BEAST_VFLIB_BINDHELPER_H_INCLUDED
+#define BEAST_VFLIB_BINDHELPER_H_INCLUDED
+
+namespace beast {
+
+/** Calls bind() for you.
+ The UnaryFunction will be called with this signature:
+ @code
+ template
+ void operator() (Functor const& f);
+ @endcode
+ Where Functor is the result of the bind.
+ */
+template
+class BindHelper
+{
+private:
+ // Gets called with the bind
+ UnaryFunction m_f;
+
+public:
+ template
+ explicit BindHelper (Arg& arg)
+ : m_f (arg)
+ { }
+
+ template
+ explicit BindHelper (Arg const& arg)
+ : m_f (arg)
+ { }
+
+ template
+ void operator() (F const& f) const
+ { m_f (f); }
+
+ template
+ void operator() (F const& f, P1 const& p1) const
+ { m_f (bind (f, p1)); }
+
+ template
+ void operator() (F const& f, P1 const& p1, P2 const& p2) const
+ { m_f (bind (f, p1, p2)); }
+
+ template
+ void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3) const
+ { m_f (bind (f, p1, p2, p3)); }
+
+ template
+ void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const
+ { m_f (bind (f, p1, p2, p3, p4)); }
+
+ template
+ void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5) const
+ { m_f (bind (f, p1, p2, p3, p4, p5)); }
+};
+
+}
+
+#endif
diff --git a/modules/beast_vflib/threads/BindableServiceQueue.h b/modules/beast_vflib/threads/BindableServiceQueue.h
new file mode 100644
index 0000000000..42872f2447
--- /dev/null
+++ b/modules/beast_vflib/threads/BindableServiceQueue.h
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_VFLIB_BINDABLESERVICEQUEUETYPE_H_INCLUDED
+#define BEAST_VFLIB_BINDABLESERVICEQUEUETYPE_H_INCLUDED
+
+#include "beast/Threads.h"
+#include "../functor/BindHelper.h"
+
+namespace beast {
+
+ template >
+ class BindableServiceQueueType
+ : public ServiceQueueType
+ {
+ public:
+ explicit BindableServiceQueueType (int expectedConcurrency = 1,
+ Allocator alloc = Allocator())
+ : ServiceQueueType(expectedConcurrency, alloc)
+ , queue(*this)
+ , call(*this)
+ {
+ }
+
+ struct BindHelperPost
+ {
+ BindableServiceQueueType& m_queue;
+ explicit BindHelperPost (BindableServiceQueueType& queue)
+ : m_queue (queue)
+ { }
+ template
+ void operator() (F const& f) const
+ { m_queue.post ( F (f) ); }
+ };
+
+ struct BindHelperDispatch
+ {
+ BindableServiceQueueType& m_queue;
+ explicit BindHelperDispatch (BindableServiceQueueType& queue)
+ : m_queue (queue)
+ { }
+ template
+ void operator() (F const& f) const
+ { m_queue.dispatch ( F (f) ); }
+ };
+
+ BindHelper const queue;
+ BindHelper const call;
+ };
+
+ typedef BindableServiceQueueType > BindableServiceQueue;
+
+}
+
+#endif
diff --git a/modules/beast_vflib/threads/ThreadWithServiceQueue.cpp b/modules/beast_vflib/threads/ThreadWithServiceQueue.cpp
new file mode 100644
index 0000000000..73f0979aa9
--- /dev/null
+++ b/modules/beast_vflib/threads/ThreadWithServiceQueue.cpp
@@ -0,0 +1,246 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+//==============================================================================
+
+#include "ThreadWithServiceQueue.h"
+
+namespace beast {
+
+ThreadWithServiceQueue::ThreadWithServiceQueue (const String& name)
+: Thread (name)
+, m_entryPoints(nullptr)
+, m_calledStart(false)
+, m_calledStop(false)
+, m_interrupted(false)
+{
+}
+
+ThreadWithServiceQueue::~ThreadWithServiceQueue()
+{
+ stop(true);
+}
+
+void ThreadWithServiceQueue::start (EntryPoints* const entryPoints)
+{
+ {
+ CriticalSection::ScopedLockType lock (m_mutex);
+
+ // start() MUST be called.
+ bassert (!m_calledStart);
+ m_calledStart = true;
+ }
+
+ m_entryPoints = entryPoints;
+
+ startThread();
+}
+
+void ThreadWithServiceQueue::stop (bool const wait)
+{
+ {
+ CriticalSection::ScopedLockType lock (m_mutex);
+
+ // start() MUST be called.
+ bassert (m_calledStart);
+
+ if (!m_calledStop)
+ {
+ m_calledStop = true;
+
+ {
+ CriticalSection::ScopedUnlockType unlock (m_mutex);
+
+ call (&Thread::signalThreadShouldExit, this);
+
+ // something could slip in here
+
+ // m_queue.close();
+ }
+ }
+ }
+
+ if (wait)
+ waitForThreadToExit();
+}
+
+void ThreadWithServiceQueue::interrupt ()
+{
+ call (&ThreadWithServiceQueue::doInterrupt, this);
+}
+
+bool ThreadWithServiceQueue::interruptionPoint ()
+{
+ return m_interrupted;
+}
+
+void ThreadWithServiceQueue::run ()
+{
+ m_entryPoints->threadInit();
+
+ while (! this->threadShouldExit())
+ {
+ run_one();
+
+ bool isInterrupted = m_entryPoints->threadIdle();
+
+ isInterrupted |= interruptionPoint();
+
+ if(isInterrupted)
+ {
+ // We put this call into the service queue to make
+ // sure we get through to threadIdle without
+ // waiting
+ call (&ThreadWithServiceQueue::doWakeUp, this);
+ }
+ }
+
+ m_entryPoints->threadExit();
+}
+
+void ThreadWithServiceQueue::doInterrupt ()
+{
+ m_interrupted = true;
+}
+
+void ThreadWithServiceQueue::doWakeUp ()
+{
+ m_interrupted = false;
+}
+
+//------------------------------------------------------------------------------
+
+namespace detail
+{
+
+//------------------------------------------------------------------------------
+
+class BindableServiceQueueTests
+: public UnitTest
+{
+public:
+
+ struct BindableServiceQueueRunner
+ : public ThreadWithServiceQueue::EntryPoints
+ {
+ ThreadWithServiceQueue m_worker;
+ int cCallCount, c1CallCount, idleInterruptedCount;
+
+ BindableServiceQueueRunner()
+ : m_worker("BindableServiceQueueRunner")
+ , cCallCount(0)
+ , c1CallCount(0)
+ , idleInterruptedCount(0)
+ {
+ }
+
+ void start()
+ {
+ m_worker.start(this);
+ }
+
+ void stop()
+ {
+ m_worker.stop(true);
+ }
+
+ void interrupt()
+ {
+ m_worker.interrupt();
+ }
+
+ void c()
+ {
+ m_worker.queue(&BindableServiceQueueRunner::cImpl, this);
+ }
+
+ void cImpl()
+ {
+ cCallCount++;
+ }
+
+ void c1(int p1)
+ {
+ m_worker.queue(&BindableServiceQueueRunner::c1Impl, this, p1);
+ }
+
+ void c1Impl(int p1)
+ {
+ c1CallCount++;
+ }
+
+ bool threadIdle ()
+ {
+ bool interrupted = m_worker.interruptionPoint ();
+
+ if(interrupted)
+ idleInterruptedCount++;
+
+ return interrupted;
+ }
+ };
+
+ static int const calls = 10000;
+
+ void performCalls()
+ {
+ Random r;
+ r.setSeedRandomly();
+
+ BindableServiceQueueRunner runner;
+
+ beginTestCase("Calls and interruptions");
+
+ runner.start();
+
+ for(std::size_t i=0; i 0);
+ }
+
+ void runTest()
+ {
+ performCalls ();
+ }
+
+ BindableServiceQueueTests () : UnitTest ("BindableServiceQueue", "beast")
+ {
+ }
+};
+
+static BindableServiceQueueTests bindableServiceQueueTests;
+
+}
+
+
+}
diff --git a/modules/beast_vflib/threads/ThreadWithServiceQueue.h b/modules/beast_vflib/threads/ThreadWithServiceQueue.h
new file mode 100644
index 0000000000..2e93d5bacf
--- /dev/null
+++ b/modules/beast_vflib/threads/ThreadWithServiceQueue.h
@@ -0,0 +1,91 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+//==============================================================================
+
+#ifndef BEAST_VFLIB_THREADWITHSERVICEQUEUE_H_INCLUDED
+#define BEAST_VFLIB_THREADWITHSERVICEQUEUE_H_INCLUDED
+
+#include "BindableServiceQueue.h"
+
+namespace beast {
+
+ /** TODO: Queued calls no longer interrupt the idle method at the moment
+ use an explicit call to interrupt() if you want to also interrupt the
+ idle method when queuing calls
+ */
+
+ class ThreadWithServiceQueue
+ : public BindableServiceQueue
+ , public Thread
+ {
+ public:
+ /** Entry points for a ThreadWithCallQueue.
+ */
+ class EntryPoints
+ {
+ public:
+ virtual ~EntryPoints () { }
+
+ virtual void threadInit () { }
+
+ virtual void threadExit () { }
+
+ virtual bool threadIdle ()
+ {
+ bool interrupted = false;
+
+ return interrupted;
+ }
+ };
+
+ explicit ThreadWithServiceQueue (const String& name);
+
+ ~ThreadWithServiceQueue();
+
+ void start (EntryPoints* const entryPoints);
+
+ void stop (bool const wait);
+
+ // Should be called periodically by the idle function.
+ // There are two possible results:
+ //
+ // #1 Returns false. The idle function may continue or return.
+ // #2 Returns true. The idle function should return as soon as possible.
+ //
+ // May only be called on the service queue thead
+ bool interruptionPoint ();
+
+ /* Interrupts the idle function.
+ */
+ void interrupt ();
+
+ private:
+ void run ();
+ void doInterrupt ();
+ void doWakeUp ();
+
+ private:
+ EntryPoints* m_entryPoints;
+ bool m_calledStart;
+ bool m_calledStop;
+ bool m_interrupted;
+ CriticalSection m_mutex;
+ };
+}
+
+#endif