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