mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Beast improvements and vflib compatibility module work
* Add CallQueue vflib compatibility class * Use run instead of run_one * Merge BindableServiceQueue into CallQueue * Take BEAST_VARIADIC_MAX into account * Fix license headers as suggested by Vinnie * Remove obsolete comment * Add ManualServiceQueue * Add ManualServiceQueue to beast_vflib include * Move static unit test variables of header only classes to module cpp * Remove no longer used mutex member * _VARIADIC_MAX maxes out at 10 * Correctly apply BEAST_VARIADIC_MAX * Merge BindableServiceQueue into CallQueue * New GuiServiceQueue and its JUCE dependency * Fix leftover merge errors * Fix CallQueue unit test * Don't use bassert for better CI support
This commit is contained in:
committed by
Vinnie Falco
parent
bf87614fa6
commit
08aa415c66
@@ -107,7 +107,7 @@ extern void beast_reportFatalError (char const* message, char const* fileName, i
|
||||
This is only compiled in a debug build.
|
||||
@see Logger::outputDebugString
|
||||
*/
|
||||
#define DBG(dbgtext) { beast::String tempDbgBuf; tempDbgBuf << dbgtext; beast::Logger::outputDebugString (tempDbgBuf); }
|
||||
#define BDBG(dbgtext) { beast::String tempDbgBuf; tempDbgBuf << dbgtext; beast::Logger::outputDebugString (tempDbgBuf); }
|
||||
|
||||
/** This will always cause an assertion failure.
|
||||
It is only compiled in a debug build, (unless BEAST_LOG_ASSERTIONS is enabled for your build).
|
||||
@@ -127,7 +127,7 @@ extern void beast_reportFatalError (char const* message, char const* fileName, i
|
||||
|
||||
// If debugging is disabled, these dummy debug and assertion macros are used..
|
||||
|
||||
#define DBG(dbgtext)
|
||||
#define BDBG(dbgtext)
|
||||
#define bassertfalse { beast_LogCurrentAssertion }
|
||||
|
||||
# if BEAST_LOG_ASSERTIONS
|
||||
|
||||
@@ -354,6 +354,7 @@ protected:
|
||||
|
||||
void wait();
|
||||
virtual void enqueue (Item* item);
|
||||
bool empty();
|
||||
|
||||
virtual std::size_t dequeue() = 0;
|
||||
virtual Waiter* new_waiter() = 0;
|
||||
|
||||
@@ -179,6 +179,12 @@ void ServiceQueueBase::enqueue (Item* item)
|
||||
waiter->signal();
|
||||
}
|
||||
|
||||
bool ServiceQueueBase::empty()
|
||||
{
|
||||
SharedState::Access state (m_state);
|
||||
return state->handlers.empty();
|
||||
}
|
||||
|
||||
// A thread can only be blocked on one ServiceQueue so we store the pointer
|
||||
// to which ServiceQueue it is blocked on to determine if the thread belongs
|
||||
// to that queue.
|
||||
|
||||
@@ -456,8 +456,8 @@ void BEAST_CALLTYPE Thread::sleep (int millisecs)
|
||||
|
||||
void BEAST_API beast_threadEntryPoint (void*);
|
||||
|
||||
extern "C" void* threadEntryProc (void*);
|
||||
extern "C" void* threadEntryProc (void* userData)
|
||||
extern "C" void* threadEntryProcBeast (void*);
|
||||
extern "C" void* threadEntryProcBeast (void* userData)
|
||||
{
|
||||
BEAST_AUTORELEASEPOOL
|
||||
{
|
||||
@@ -482,7 +482,7 @@ void Thread::launchThread()
|
||||
threadHandle = 0;
|
||||
pthread_t handle = 0;
|
||||
|
||||
if (pthread_create (&handle, 0, threadEntryProc, this) == 0)
|
||||
if (pthread_create (&handle, 0, threadEntryProcBeast, this) == 0)
|
||||
{
|
||||
pthread_detach (handle);
|
||||
threadHandle = (void*) handle;
|
||||
|
||||
@@ -85,7 +85,7 @@ void LeakCheckedBase::LeakCounterBase::checkForLeaks ()
|
||||
always use ScopedPointers, OwnedArrays, SharedObjects,
|
||||
etc, and avoid the 'delete' operator at all costs!
|
||||
*/
|
||||
DBG ("Leaked objects: " << count << " of " << getClassName ());
|
||||
BDBG ("Leaked objects: " << count << " of " << getClassName ());
|
||||
|
||||
//bassertfalse;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ void LeakCheckedBase::reportDanglingPointer (char const*)
|
||||
SharedObjects, etc, and avoid the 'delete' operator
|
||||
at all costs!
|
||||
*/
|
||||
DBG ("Dangling pointer deletion: " << objectName);
|
||||
BDBG ("Dangling pointer deletion: " << objectName);
|
||||
|
||||
bassertfalse;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
/* 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 */; };
|
||||
CD0A5B4918170DC300DA0342 /* beast_modules.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD0A5B4818170DC300DA0342 /* beast_modules.mm */; };
|
||||
CD0A5B4B18170EBC00DA0342 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD0A5B4A18170EBC00DA0342 /* CoreServices.framework */; };
|
||||
CD0A5B4E18170F0D00DA0342 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD0A5B4D18170F0D00DA0342 /* AppKit.framework */; };
|
||||
CD1CBE68181B2D99002CCC0C /* juce_modules.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD1CBE64181B2689002CCC0C /* juce_modules.mm */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -31,13 +32,16 @@
|
||||
CD0A5B3E181707F700DA0342 /* mac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mac.cpp; path = ../../src/mac.cpp; sourceTree = "<group>"; };
|
||||
CD0A5B401817097800DA0342 /* BeastUnitTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BeastUnitTests.cpp; path = ../../src/BeastUnitTests.cpp; sourceTree = "<group>"; };
|
||||
CD0A5B411817097800DA0342 /* BeastUnitTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BeastUnitTests.h; path = ../../src/BeastUnitTests.h; sourceTree = "<group>"; };
|
||||
CD0A5B4318170A5100DA0342 /* beast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = beast.cpp; path = ../../src/beast.cpp; sourceTree = "<group>"; };
|
||||
CD0A5B4418170A5100DA0342 /* beast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = beast.h; path = ../../src/beast.h; sourceTree = "<group>"; };
|
||||
CD0A5B4818170DC300DA0342 /* beast.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = beast.mm; path = ../../src/beast.mm; sourceTree = "<group>"; };
|
||||
CD0A5B4318170A5100DA0342 /* beast_modules.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = beast_modules.cpp; path = ../../src/beast_modules.cpp; sourceTree = "<group>"; };
|
||||
CD0A5B4418170A5100DA0342 /* beast_modules.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = beast_modules.h; path = ../../src/beast_modules.h; sourceTree = "<group>"; };
|
||||
CD0A5B4818170DC300DA0342 /* beast_modules.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = beast_modules.mm; path = ../../src/beast_modules.mm; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
CD0A5B50181714B800DA0342 /* modules */ = {isa = PBXFileReference; lastKnownFileType = folder; name = modules; path = ../../../../modules; sourceTree = "<group>"; };
|
||||
CD1CBE62181B2689002CCC0C /* juce_modules.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = juce_modules.cpp; path = ../../src/juce_modules.cpp; sourceTree = "<group>"; };
|
||||
CD1CBE63181B2689002CCC0C /* juce_modules.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = juce_modules.h; path = ../../src/juce_modules.h; sourceTree = "<group>"; };
|
||||
CD1CBE64181B2689002CCC0C /* juce_modules.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = juce_modules.mm; path = ../../src/juce_modules.mm; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -58,11 +62,14 @@
|
||||
children = (
|
||||
CD0A5B50181714B800DA0342 /* modules */,
|
||||
CD0A5B4F181714A000DA0342 /* beast */,
|
||||
CD0A5B4818170DC300DA0342 /* beast.mm */,
|
||||
CD0A5B4318170A5100DA0342 /* beast.cpp */,
|
||||
CD0A5B4418170A5100DA0342 /* beast.h */,
|
||||
CD0A5B4318170A5100DA0342 /* beast_modules.cpp */,
|
||||
CD0A5B4418170A5100DA0342 /* beast_modules.h */,
|
||||
CD0A5B4818170DC300DA0342 /* beast_modules.mm */,
|
||||
CD0A5B401817097800DA0342 /* BeastUnitTests.cpp */,
|
||||
CD0A5B411817097800DA0342 /* BeastUnitTests.h */,
|
||||
CD1CBE62181B2689002CCC0C /* juce_modules.cpp */,
|
||||
CD1CBE63181B2689002CCC0C /* juce_modules.h */,
|
||||
CD1CBE64181B2689002CCC0C /* juce_modules.mm */,
|
||||
CD0A5B3E181707F700DA0342 /* mac.cpp */,
|
||||
CD0A5B4C18170EC600DA0342 /* Frameworks */,
|
||||
CD0A5B331817074500DA0342 /* Products */,
|
||||
@@ -139,7 +146,8 @@
|
||||
files = (
|
||||
CD0A5B3F181707F700DA0342 /* mac.cpp in Sources */,
|
||||
CD0A5B421817097800DA0342 /* BeastUnitTests.cpp in Sources */,
|
||||
CD0A5B4918170DC300DA0342 /* beast.mm in Sources */,
|
||||
CD1CBE68181B2D99002CCC0C /* juce_modules.mm in Sources */,
|
||||
CD0A5B4918170DC300DA0342 /* beast_modules.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -180,9 +188,10 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../src",
|
||||
"$(SRCROOT)/../../../../../../../JUCE",
|
||||
"$(SRCROOT)/../../../../config",
|
||||
"$(SRCROOT)/../../../..",
|
||||
"$(SRCROOT)/../../../../beast",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -219,9 +228,10 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../src",
|
||||
"$(SRCROOT)/../../../../../../../JUCE",
|
||||
"$(SRCROOT)/../../../../config",
|
||||
"$(SRCROOT)/../../../..",
|
||||
"$(SRCROOT)/../../../../beast",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
SDKROOT = macosx;
|
||||
|
||||
94
demos/unittests/src/AppConfig.h
Normal file
94
demos/unittests/src/AppConfig.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
IMPORTANT! This file is auto-generated each time you save your
|
||||
project - if you alter its contents, your changes may be overwritten!
|
||||
|
||||
There's a section below where you can add your own custom code safely, and the
|
||||
Introjucer will preserve the contents of that block, but the best way to change
|
||||
any of these definitions is by using the Introjucer's project settings.
|
||||
|
||||
Any commented-out settings will assume their default values.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_APPCONFIG_M70QFTRRK__
|
||||
#define __JUCE_APPCONFIG_M70QFTRRK__
|
||||
|
||||
//==============================================================================
|
||||
// [BEGIN_USER_CODE_SECTION]
|
||||
|
||||
// (You can add your own code in this section, and the Introjucer will not overwrite it)
|
||||
|
||||
// [END_USER_CODE_SECTION]
|
||||
|
||||
//==============================================================================
|
||||
#define JUCE_MODULE_AVAILABLE_juce_core 1
|
||||
//#define JUCE_MODULE_AVAILABLE_juce_cryptography 1
|
||||
//#define JUCE_MODULE_AVAILABLE_juce_data_structures 1
|
||||
#define JUCE_MODULE_AVAILABLE_juce_events 1
|
||||
//#define JUCE_MODULE_AVAILABLE_juce_graphics 1
|
||||
//#define JUCE_MODULE_AVAILABLE_juce_gui_basics 1
|
||||
//#define JUCE_MODULE_AVAILABLE_juce_gui_extra 1
|
||||
|
||||
//==============================================================================
|
||||
// juce_core flags:
|
||||
|
||||
#ifndef JUCE_FORCE_DEBUG
|
||||
//#define JUCE_FORCE_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_LOG_ASSERTIONS
|
||||
#define JUCE_LOG_ASSERTIONS 1
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_CHECK_MEMORY_LEAKS
|
||||
//#define JUCE_CHECK_MEMORY_LEAKS
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
//#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_INCLUDE_ZLIB_CODE
|
||||
//#define JUCE_INCLUDE_ZLIB_CODE
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// juce_graphics flags:
|
||||
|
||||
#ifndef JUCE_USE_COREIMAGE_LOADER
|
||||
#define JUCE_USE_COREIMAGE_LOADER 0
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_USE_DIRECTWRITE
|
||||
//#define JUCE_USE_DIRECTWRITE
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// juce_gui_basics flags:
|
||||
|
||||
#ifndef JUCE_ENABLE_REPAINT_DEBUGGING
|
||||
//#define JUCE_ENABLE_REPAINT_DEBUGGING
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_USE_XSHM
|
||||
//#define JUCE_USE_XSHM
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_USE_XRENDER
|
||||
//#define JUCE_USE_XRENDER
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_USE_XCURSOR
|
||||
//#define JUCE_USE_XCURSOR
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// juce_gui_extra flags:
|
||||
|
||||
#ifndef JUCE_WEB_BROWSER
|
||||
//#define JUCE_WEB_BROWSER
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __JUCE_APPCONFIG_M70QFTRRK__
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef UNITTESTS_BEASTUNITTESTS_H_INCLUDED
|
||||
#define UNITTESTS_BEASTUNITTESTS_H_INCLUDED
|
||||
|
||||
#include "beast.h"
|
||||
#include "beast_modules.h"
|
||||
|
||||
int runUnitTests (beast::String const& match, beast::String const& format);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "beast.h"
|
||||
#include "beast_modules.h"
|
||||
|
||||
#include "modules/beast_core/beast_core.cpp"
|
||||
#include "modules/beast_vflib/beast_vflib.cpp"
|
||||
@@ -26,6 +26,6 @@
|
||||
#include "beast/crypto/Crypto.cpp"
|
||||
#include "beast/strings/Strings.cpp"
|
||||
#include "beast/threads/Threads.cpp"
|
||||
// #include "beast/http/HTTP.cpp"
|
||||
//#include "beast/http/HTTP.cpp"
|
||||
#include "beast/net/Net.cpp"
|
||||
#include "beast/utility/Utility.cpp"
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef UNITTESTS_BEAST_H_INCLUDED
|
||||
#define UNITTESTS_BEAST_H_INCLUDED
|
||||
#ifndef UNITTESTS_BEASTMODULES_H_INCLUDED
|
||||
#define UNITTESTS_BEASTMODULES_H_INCLUDED
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
20
demos/unittests/src/beast_modules.mm
Normal file
20
demos/unittests/src/beast_modules.mm
Normal file
@@ -0,0 +1,20 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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_modules.cpp"
|
||||
21
demos/unittests/src/juce_modules.cpp
Normal file
21
demos/unittests/src/juce_modules.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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 "modules/juce_core/juce_core.cpp"
|
||||
#include "modules/juce_events/juce_events.cpp"
|
||||
28
demos/unittests/src/juce_modules.h
Normal file
28
demos/unittests/src/juce_modules.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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_JUCEMODULES_H_INCLUDED
|
||||
#define UNITTESTS_JUCEMODULES_H_INCLUDED
|
||||
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "modules/juce_core/juce_core.h"
|
||||
#include "modules/juce_events/juce_events.h"
|
||||
|
||||
#endif
|
||||
@@ -17,4 +17,4 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "beast.cpp"
|
||||
#include "juce_modules.cpp"
|
||||
@@ -1,25 +1,29 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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.
|
||||
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.
|
||||
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 "juce_modules.h"
|
||||
#include "beast_modules.h"
|
||||
|
||||
#include "BeastUnitTests.h"
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
return runUnitTests("", "text");
|
||||
juce::ScopedJuceInitialiser_GUI juce;
|
||||
return runUnitTests("", "text");
|
||||
}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
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 <stdio.h>
|
||||
#include <tchar.h>
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ void PropertySet::restoreFromXml (const XmlElement& xml)
|
||||
const ScopedLock sl (lock);
|
||||
clear();
|
||||
|
||||
forEachXmlChildElementWithTagName (xml, e, "VALUE")
|
||||
beast_forEachXmlChildElementWithTagName (xml, e, "VALUE")
|
||||
{
|
||||
if (e->hasAttribute ("name")
|
||||
&& e->hasAttribute ("val"))
|
||||
|
||||
@@ -47,7 +47,7 @@ FileLogger::~FileLogger() {}
|
||||
void FileLogger::logMessage (const String& message)
|
||||
{
|
||||
const ScopedLock sl (logLock);
|
||||
DBG (message);
|
||||
BDBG (message);
|
||||
FileOutputStream out (logFile, 256);
|
||||
out << message << newLine;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ void logAssertion (const char* const filename, const int lineNum) noexcept
|
||||
#if BEAST_LOG_ASSERTIONS
|
||||
Logger::writeToLog (m);
|
||||
#else
|
||||
DBG (m);
|
||||
BDBG (m);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -93,7 +93,7 @@ struct Expression::Helpers
|
||||
public:
|
||||
EvaluationError (const String& desc) : description (desc)
|
||||
{
|
||||
DBG ("Expression::EvaluationError: " + description);
|
||||
BDBG ("Expression::EvaluationError: " + description);
|
||||
}
|
||||
|
||||
String description;
|
||||
@@ -1086,7 +1086,7 @@ SharedPtr<Expression::Term> Expression::Term::negated()
|
||||
Expression::ParseError::ParseError (const String& message)
|
||||
: description (message)
|
||||
{
|
||||
DBG ("Expression::ParseError: " + message);
|
||||
BDBG ("Expression::ParseError: " + message);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
@@ -47,10 +47,10 @@
|
||||
# ifdef _VARIADIC_MAX
|
||||
# define BEAST_VARIADIC_MAX _VARIADIC_MAX
|
||||
# else
|
||||
# define BEAST_VARIADIC_MAX 9
|
||||
# define BEAST_VARIADIC_MAX 10
|
||||
# endif
|
||||
#else
|
||||
# define BEAST_VARIADIC_MAX 9
|
||||
# define BEAST_VARIADIC_MAX 10
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
@see forEachXmlChildElementWithTagName
|
||||
*/
|
||||
#define forEachXmlChildElement(parentXmlElement, childElementVariableName) \
|
||||
#define beast_forEachXmlChildElement(parentXmlElement, childElementVariableName) \
|
||||
\
|
||||
for (beast::XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \
|
||||
childElementVariableName != nullptr; \
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
@see forEachXmlChildElement
|
||||
*/
|
||||
#define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \
|
||||
#define beast_forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \
|
||||
\
|
||||
for (beast::XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \
|
||||
childElementVariableName != nullptr; \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -20,3 +20,9 @@
|
||||
#include "beast_vflib.h"
|
||||
|
||||
#include "threads/ThreadWithServiceQueue.cpp"
|
||||
|
||||
/** Unit tests for header only classes
|
||||
*/
|
||||
|
||||
static beast::detail::CallQueueTests callQueueTests;
|
||||
static beast::detail::ManualServiceQueueTests manualServiceQueueTests;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of BeastUtils: https://github.com/pdehne/BeastUtils
|
||||
Copyright 2013, Patrick Dehne <patrick@sonicweb.de>
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -21,7 +21,9 @@
|
||||
#define BEAST_VFLIB_H_INCLUDED
|
||||
|
||||
#include "functor/BindHelper.h"
|
||||
#include "threads/BindableServiceQueue.h"
|
||||
#include "threads/CallQueue.h"
|
||||
#include "threads/ThreadWithServiceQueue.h"
|
||||
#include "threads/ManualServiceQueue.h"
|
||||
#include "threads/GuiServiceQueue.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -38,6 +39,7 @@ private:
|
||||
UnaryFunction m_f;
|
||||
|
||||
public:
|
||||
#if BEAST_VARIADIC_MAX >= 1
|
||||
template <typename Arg>
|
||||
explicit BindHelper (Arg& arg)
|
||||
: m_f (arg)
|
||||
@@ -51,26 +53,61 @@ public:
|
||||
template <typename F>
|
||||
void operator() (F const& f) const
|
||||
{ m_f (f); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 2
|
||||
template <typename F, class P1>
|
||||
void operator() (F const& f, P1 const& p1) const
|
||||
{ m_f (bind (f, p1)); }
|
||||
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 3
|
||||
template <typename F, class P1, class P2>
|
||||
void operator() (F const& f, P1 const& p1, P2 const& p2) const
|
||||
{ m_f (bind (f, p1, p2)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 4
|
||||
template <typename F, class P1, class P2, class P3>
|
||||
void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3) const
|
||||
{ m_f (bind (f, p1, p2, p3)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 5
|
||||
template <typename F, class P1, class P2, class P3, class P4>
|
||||
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)); }
|
||||
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 6
|
||||
template <typename F, class P1, class P2, class P3, class P4, class P5>
|
||||
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
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 7
|
||||
template <typename F, class P1, class P2, class P3, class P4, class P5, class P6>
|
||||
void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6) const
|
||||
{ m_f (bind (f, p1, p2, p3, p4, p5, p6)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 8
|
||||
template <typename F, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
|
||||
void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6, P7 const& p7) const
|
||||
{ m_f (bind (f, p1, p2, p3, p4, p5, p6, p7)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 9
|
||||
template <typename F, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
|
||||
void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6, P7 const& p7, P8 const& p8) const
|
||||
{ m_f (bind (f, p1, p2, p3, p4, p5, p6, p7, p8)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 10
|
||||
template <typename F, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
|
||||
void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6, P7 const& p7, P8 const& p8, P9 const& p9) const
|
||||
{ m_f (bind (f, p1, p2, p3, p4, p5, p6, p7, p8, p9)); }
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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 Allocator = std::allocator <char> >
|
||||
class BindableServiceQueueType
|
||||
: public ServiceQueueType <Allocator>
|
||||
{
|
||||
public:
|
||||
explicit BindableServiceQueueType (int expectedConcurrency = 1,
|
||||
Allocator alloc = Allocator())
|
||||
: ServiceQueueType<Allocator>(expectedConcurrency, alloc)
|
||||
, queue(*this)
|
||||
, call(*this)
|
||||
{
|
||||
}
|
||||
|
||||
struct BindHelperPost
|
||||
{
|
||||
BindableServiceQueueType<Allocator>& m_queue;
|
||||
explicit BindHelperPost (BindableServiceQueueType<Allocator>& queue)
|
||||
: m_queue (queue)
|
||||
{ }
|
||||
template <typename F>
|
||||
void operator() (F const& f) const
|
||||
{ m_queue.post ( F (f) ); }
|
||||
};
|
||||
|
||||
struct BindHelperDispatch
|
||||
{
|
||||
BindableServiceQueueType<Allocator>& m_queue;
|
||||
explicit BindHelperDispatch (BindableServiceQueueType<Allocator>& queue)
|
||||
: m_queue (queue)
|
||||
{ }
|
||||
template <typename F>
|
||||
void operator() (F const& f) const
|
||||
{ m_queue.dispatch ( F (f) ); }
|
||||
};
|
||||
|
||||
BindHelper <BindHelperPost> const queue;
|
||||
BindHelper <BindHelperDispatch> const call;
|
||||
};
|
||||
|
||||
typedef BindableServiceQueueType <std::allocator <char> > BindableServiceQueue;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
382
modules/beast_vflib/threads/CallQueue.h
Normal file
382
modules/beast_vflib/threads/CallQueue.h
Normal file
@@ -0,0 +1,382 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
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_CALLQUEUE_H_INCLUDED
|
||||
#define BEAST_VFLIB_CALLQUEUE_H_INCLUDED
|
||||
|
||||
#include "beast/Threads.h"
|
||||
#include "../functor/BindHelper.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
template <class Allocator = std::allocator <char> >
|
||||
class CallQueueType
|
||||
: public ServiceQueueType <Allocator>
|
||||
{
|
||||
public:
|
||||
explicit CallQueueType (const String& name,
|
||||
int expectedConcurrency = 1,
|
||||
Allocator alloc = Allocator())
|
||||
: ServiceQueueType<Allocator>(expectedConcurrency, alloc)
|
||||
, m_name (name)
|
||||
, queue(*this)
|
||||
, call(*this)
|
||||
{
|
||||
}
|
||||
|
||||
~CallQueueType ()
|
||||
{
|
||||
// Someone forget to close the queue.
|
||||
bassert (m_closed.isSignaled ());
|
||||
|
||||
// Can't destroy queue with unprocessed calls.
|
||||
bassert (ServiceQueueBase::empty ());
|
||||
}
|
||||
|
||||
void enqueue (ServiceQueueBase::Item* item)
|
||||
{
|
||||
// If this goes off someone added calls
|
||||
// after the queue has been closed.
|
||||
bassert (!m_closed.isSignaled ());
|
||||
|
||||
ServiceQueueType <Allocator>::enqueue (item);
|
||||
}
|
||||
|
||||
/** Close the queue.
|
||||
|
||||
Functors may not be added after this routine is called. This is used for
|
||||
diagnostics, to track down spurious calls during application shutdown
|
||||
or exit. Derived classes may call this if the appropriate time is known.
|
||||
|
||||
The queue is synchronized after it is closed.
|
||||
Can still have pending calls, just can't put new ones in.
|
||||
*/
|
||||
virtual void close ()
|
||||
{
|
||||
m_closed.signal ();
|
||||
|
||||
ServiceQueueType <Allocator>::stop ();
|
||||
}
|
||||
|
||||
struct BindHelperPost
|
||||
{
|
||||
CallQueueType<Allocator>& m_queue;
|
||||
explicit BindHelperPost (CallQueueType<Allocator>& queue)
|
||||
: m_queue (queue)
|
||||
{ }
|
||||
template <typename F>
|
||||
void operator() (F const& f) const
|
||||
{ m_queue.post ( F (f) ); }
|
||||
};
|
||||
|
||||
struct BindHelperDispatch
|
||||
{
|
||||
CallQueueType<Allocator>& m_queue;
|
||||
explicit BindHelperDispatch (CallQueueType<Allocator>& queue)
|
||||
: m_queue (queue)
|
||||
{ }
|
||||
template <typename F>
|
||||
void operator() (F const& f) const
|
||||
{ m_queue.dispatch ( F (f) ); }
|
||||
};
|
||||
|
||||
BindHelper <BindHelperPost> const queue;
|
||||
BindHelper <BindHelperDispatch> const call;
|
||||
|
||||
private:
|
||||
String m_name;
|
||||
AtomicFlag m_closed;
|
||||
};
|
||||
|
||||
typedef CallQueueType <std::allocator <char> > CallQueue;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CallQueueTests
|
||||
: public UnitTest
|
||||
{
|
||||
public:
|
||||
struct CallTracker
|
||||
{
|
||||
CallQueueTests *unitTest;
|
||||
int c0, c1, c2, c3, c4, c5, c6, c7, c8;
|
||||
int q0, q1, q2, q3, q4, q5, q6, q7, q8;
|
||||
|
||||
CallTracker(CallQueueTests *parent)
|
||||
: unitTest(parent)
|
||||
, c0(0), c1(0), c2(0), c3(0), c4(0), c5(0), c6(0), c7(0), c8(0)
|
||||
, q0(0), q1(0), q2(0), q3(0), q4(0), q5(0), q6(0), q7(0), q8(0)
|
||||
{
|
||||
}
|
||||
|
||||
void doQ0() { q0++; }
|
||||
|
||||
void doQ1(const String& p1)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
q1++;
|
||||
}
|
||||
|
||||
void doQ2(const String& p1, const String& p2)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
q2++;
|
||||
}
|
||||
|
||||
void doQ3(const String& p1, const String& p2, const String& p3)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
q3++;
|
||||
}
|
||||
|
||||
void doQ4(const String& p1, const String& p2, const String& p3, const String& p4)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
q4++;
|
||||
}
|
||||
|
||||
void doQ5(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
q5++;
|
||||
}
|
||||
|
||||
void doQ6(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
unitTest->expect(p6 == "p6");
|
||||
q6++;
|
||||
}
|
||||
|
||||
void doQ7(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
unitTest->expect(p6 == "p6");
|
||||
unitTest->expect(p7 == "p7");
|
||||
q7++;
|
||||
}
|
||||
|
||||
void doQ8(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7, const String& p8)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
unitTest->expect(p6 == "p6");
|
||||
unitTest->expect(p7 == "p7");
|
||||
unitTest->expect(p8 == "p8");
|
||||
q8++;
|
||||
}
|
||||
|
||||
void doC0() { c0++; }
|
||||
|
||||
void doC1(const String& p1)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
c1++;
|
||||
}
|
||||
|
||||
void doC2(const String& p1, const String& p2)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
c2++;
|
||||
}
|
||||
|
||||
void doC3(const String& p1, const String& p2, const String& p3)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
c3++;
|
||||
}
|
||||
|
||||
void doC4(const String& p1, const String& p2, const String& p3, const String& p4)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
c4++;
|
||||
}
|
||||
|
||||
void doC5(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
c5++;
|
||||
}
|
||||
|
||||
void doC6(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
unitTest->expect(p6 == "p6");
|
||||
c6++;
|
||||
}
|
||||
|
||||
void doC7(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
unitTest->expect(p6 == "p6");
|
||||
unitTest->expect(p7 == "p7");
|
||||
c7++;
|
||||
}
|
||||
|
||||
void doC8(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7, const String& p8)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
unitTest->expect(p2 == "p2");
|
||||
unitTest->expect(p3 == "p3");
|
||||
unitTest->expect(p4 == "p4");
|
||||
unitTest->expect(p5 == "p5");
|
||||
unitTest->expect(p6 == "p6");
|
||||
unitTest->expect(p7 == "p7");
|
||||
unitTest->expect(p8 == "p8");
|
||||
c8++;
|
||||
}
|
||||
};
|
||||
|
||||
CallTracker m_callTracker;
|
||||
|
||||
void testArities ()
|
||||
{
|
||||
beginTestCase("Arities");
|
||||
|
||||
int calls = 0;
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 2
|
||||
m_queue.queue(&CallTracker::doQ0, &m_callTracker); calls++;
|
||||
m_queue.queue(&CallTracker::doC0, &m_callTracker); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 3
|
||||
m_queue.queue(&CallTracker::doQ1, &m_callTracker, "p1"); calls++;
|
||||
m_queue.queue(&CallTracker::doC1, &m_callTracker, "p1"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 4
|
||||
m_queue.queue(&CallTracker::doQ2, &m_callTracker, "p1", "p2"); calls++;
|
||||
m_queue.queue(&CallTracker::doC2, &m_callTracker, "p1", "p2"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 5
|
||||
m_queue.queue(&CallTracker::doQ3, &m_callTracker, "p1", "p2", "p3"); calls++;
|
||||
m_queue.queue(&CallTracker::doC3, &m_callTracker, "p1", "p2", "p3"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 6
|
||||
m_queue.queue(&CallTracker::doQ4, &m_callTracker, "p1", "p2", "p3", "p4"); calls++;
|
||||
m_queue.queue(&CallTracker::doC4, &m_callTracker, "p1", "p2", "p3", "p4"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 7
|
||||
m_queue.queue(&CallTracker::doQ5, &m_callTracker, "p1", "p2", "p3", "p4", "p5"); calls++;
|
||||
m_queue.queue(&CallTracker::doC5, &m_callTracker, "p1", "p2", "p3", "p4", "p5"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 8
|
||||
m_queue.queue(&CallTracker::doQ6, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6"); calls++;
|
||||
m_queue.queue(&CallTracker::doC6, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 9
|
||||
m_queue.queue(&CallTracker::doQ7, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7"); calls++;
|
||||
m_queue.queue(&CallTracker::doC7, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7"); calls++;
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 10
|
||||
m_queue.queue(&CallTracker::doQ8, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"); calls++;
|
||||
m_queue.queue(&CallTracker::doC8, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"); calls++;
|
||||
#endif
|
||||
|
||||
std::size_t performedCalls = m_queue.poll();
|
||||
|
||||
m_queue.close();
|
||||
|
||||
expect (performedCalls == calls);
|
||||
|
||||
expect (m_callTracker.c0 == 1);
|
||||
expect (m_callTracker.c1 == 1);
|
||||
expect (m_callTracker.c2 == 1);
|
||||
expect (m_callTracker.c3 == 1);
|
||||
expect (m_callTracker.c4 == 1);
|
||||
expect (m_callTracker.c5 == 1);
|
||||
|
||||
expect (m_callTracker.q0 == 1);
|
||||
expect (m_callTracker.q1 == 1);
|
||||
expect (m_callTracker.q2 == 1);
|
||||
expect (m_callTracker.q3 == 1);
|
||||
expect (m_callTracker.q4 == 1);
|
||||
expect (m_callTracker.q5 == 1);
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
testArities();
|
||||
}
|
||||
|
||||
CallQueueTests ()
|
||||
: UnitTest ("CallQueue", "beast")
|
||||
, m_queue("CallQueue Test Queue")
|
||||
, m_callTracker(this)
|
||||
{
|
||||
}
|
||||
|
||||
CallQueue m_queue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
72
modules/beast_vflib/threads/GuiServiceQueue.h
Normal file
72
modules/beast_vflib/threads/GuiServiceQueue.h
Normal file
@@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
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_GUISERVICEQUEUE_H_INCLUDED
|
||||
#define BEAST_VFLIB_GUISERVICEQUEUE_H_INCLUDED
|
||||
|
||||
#include "AppConfig.h"
|
||||
#include "modules/juce_core/juce_core.h"
|
||||
#include "modules/juce_events/juce_events.h"
|
||||
|
||||
#include "CallQueue.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
class GuiServiceQueue
|
||||
: public CallQueue
|
||||
, private juce::AsyncUpdater
|
||||
, private ThreadWithServiceQueue::EntryPoints
|
||||
{
|
||||
public:
|
||||
explicit GuiServiceQueue (const String& name)
|
||||
: CallQueue(name)
|
||||
, m_thread(name)
|
||||
{
|
||||
bassert (juce::MessageManager::getInstance()->isThisTheMessageThread());
|
||||
|
||||
m_thread.start (this);
|
||||
}
|
||||
|
||||
void close ()
|
||||
{
|
||||
m_thread.stop (true);
|
||||
|
||||
CallQueue::close ();
|
||||
}
|
||||
|
||||
void enqueue (ServiceQueueBase::Item* item)
|
||||
{
|
||||
CallQueue::enqueue (item);
|
||||
|
||||
m_thread.call (&juce::AsyncUpdater::triggerAsyncUpdate, (AsyncUpdater*)this);
|
||||
}
|
||||
|
||||
void handleAsyncUpdate()
|
||||
{
|
||||
poll();
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadWithServiceQueue m_thread;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
165
modules/beast_vflib/threads/ManualServiceQueue.h
Normal file
165
modules/beast_vflib/threads/ManualServiceQueue.h
Normal file
@@ -0,0 +1,165 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
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_MANUALSERVICEQUEUE_H_INCLUDED
|
||||
#define BEAST_VFLIB_MANUALSERVICEQUEUE_H_INCLUDED
|
||||
|
||||
#include "CallQueue.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
class ManualServiceQueue
|
||||
: public CallQueue
|
||||
{
|
||||
public:
|
||||
explicit ManualServiceQueue (const String& name)
|
||||
: CallQueue(name)
|
||||
{
|
||||
}
|
||||
|
||||
/** Calls all functors in the queue. Returns if there are no
|
||||
more functors available to run
|
||||
*/
|
||||
bool synchronize ()
|
||||
{
|
||||
if(poll() > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ManualServiceQueueTests
|
||||
: public UnitTest
|
||||
{
|
||||
public:
|
||||
struct CallTracker
|
||||
{
|
||||
ManualServiceQueueTests *unitTest;
|
||||
int c0, c1;
|
||||
int q0, q1;
|
||||
|
||||
CallTracker(ManualServiceQueueTests *parent)
|
||||
: unitTest(parent)
|
||||
, c0(0), c1(0)
|
||||
, q0(0), q1(0)
|
||||
{
|
||||
}
|
||||
|
||||
void doQ0() { q0++; }
|
||||
|
||||
void doQ1(const String& p1)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
q1++;
|
||||
}
|
||||
|
||||
void doC0() { c0++; }
|
||||
|
||||
void doC1(const String& p1)
|
||||
{
|
||||
unitTest->expect(p1 == "p1");
|
||||
c1++;
|
||||
}
|
||||
};
|
||||
|
||||
void performEmptyQueue()
|
||||
{
|
||||
beginTestCase("Empty queue");
|
||||
|
||||
ManualServiceQueue queue("ManualServiceQueueTests");
|
||||
|
||||
bool doneSomething = queue.synchronize();
|
||||
expect(!doneSomething);
|
||||
|
||||
queue.close();
|
||||
}
|
||||
|
||||
void performCalls()
|
||||
{
|
||||
beginTestCase("Calls");
|
||||
|
||||
Random r;
|
||||
r.setSeedRandomly();
|
||||
|
||||
ManualServiceQueue queue("ManualServiceQueueTests");
|
||||
|
||||
static int const batches = 1000;
|
||||
|
||||
for(std::size_t i=0; i<batches; i++)
|
||||
{
|
||||
CallTracker ct(this);
|
||||
|
||||
std::size_t batchSize = r.nextLargeNumber(10).toInteger();
|
||||
|
||||
if(batchSize > 0)
|
||||
{
|
||||
for(std::size_t y=0; y<batchSize; y++)
|
||||
{
|
||||
int callType = r.nextLargeNumber(10).toInteger();
|
||||
|
||||
if(callType % 2)
|
||||
{
|
||||
queue.queue(&CallTracker::doQ0, &ct);
|
||||
queue.call(&CallTracker::doC0, &ct);
|
||||
}
|
||||
else
|
||||
{
|
||||
queue.queue(&CallTracker::doQ1, &ct, "p1");
|
||||
queue.call(&CallTracker::doC1, &ct, "p1");
|
||||
}
|
||||
}
|
||||
|
||||
bool doneSomething = queue.synchronize();
|
||||
|
||||
expect(doneSomething);
|
||||
expect ((ct.q0 + ct.q1) == batchSize);
|
||||
expect ((ct.c0 + ct.c1) == batchSize);
|
||||
|
||||
doneSomething = queue.synchronize();
|
||||
expect(!doneSomething);
|
||||
}
|
||||
}
|
||||
|
||||
queue.close ();
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
performEmptyQueue ();
|
||||
performCalls ();
|
||||
}
|
||||
|
||||
ManualServiceQueueTests () : UnitTest ("ManualServiceQueue", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -22,106 +23,65 @@
|
||||
namespace beast {
|
||||
|
||||
ThreadWithServiceQueue::ThreadWithServiceQueue (const String& name)
|
||||
: Thread (name)
|
||||
: CallQueue(name)
|
||||
, m_thread(name, this)
|
||||
, m_entryPoints(nullptr)
|
||||
, m_calledStart(false)
|
||||
, m_calledStop(false)
|
||||
, m_interrupted(false)
|
||||
{
|
||||
}
|
||||
|
||||
ThreadWithServiceQueue::~ThreadWithServiceQueue()
|
||||
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;
|
||||
}
|
||||
// start() MUST be called.
|
||||
bassert (!m_calledStart);
|
||||
m_calledStart = true;
|
||||
|
||||
m_entryPoints = entryPoints;
|
||||
|
||||
startThread();
|
||||
m_thread.startThread ();
|
||||
}
|
||||
|
||||
void ThreadWithServiceQueue::stop (bool const wait)
|
||||
{
|
||||
// start() MUST be called.
|
||||
bassert (m_calledStart);
|
||||
|
||||
if (!m_calledStop)
|
||||
{
|
||||
CriticalSection::ScopedLockType lock (m_mutex);
|
||||
m_calledStop = true;
|
||||
|
||||
// start() MUST be called.
|
||||
bassert (m_calledStart);
|
||||
m_thread.signalThreadShouldExit();
|
||||
|
||||
if (!m_calledStop)
|
||||
{
|
||||
m_calledStop = true;
|
||||
|
||||
{
|
||||
CriticalSection::ScopedUnlockType unlock (m_mutex);
|
||||
|
||||
call (&Thread::signalThreadShouldExit, this);
|
||||
|
||||
// something could slip in here
|
||||
|
||||
// m_queue.close();
|
||||
}
|
||||
}
|
||||
// something could slip in here
|
||||
|
||||
close ();
|
||||
}
|
||||
|
||||
if (wait)
|
||||
waitForThreadToExit();
|
||||
}
|
||||
|
||||
void ThreadWithServiceQueue::interrupt ()
|
||||
{
|
||||
call (&ThreadWithServiceQueue::doInterrupt, this);
|
||||
m_thread.waitForThreadToExit ();
|
||||
}
|
||||
|
||||
bool ThreadWithServiceQueue::interruptionPoint ()
|
||||
void ThreadWithServiceQueue::runThread ()
|
||||
{
|
||||
return m_interrupted;
|
||||
}
|
||||
|
||||
void ThreadWithServiceQueue::run ()
|
||||
{
|
||||
m_entryPoints->threadInit();
|
||||
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);
|
||||
}
|
||||
}
|
||||
while (! m_thread.threadShouldExit ())
|
||||
run ();
|
||||
|
||||
// Perform the remaining calls in the queue
|
||||
|
||||
reset ();
|
||||
poll ();
|
||||
|
||||
m_entryPoints->threadExit();
|
||||
}
|
||||
|
||||
void ThreadWithServiceQueue::doInterrupt ()
|
||||
{
|
||||
m_interrupted = true;
|
||||
}
|
||||
|
||||
void ThreadWithServiceQueue::doWakeUp ()
|
||||
{
|
||||
m_interrupted = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail
|
||||
@@ -129,22 +89,27 @@ namespace detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class BindableServiceQueueTests
|
||||
class ThreadWithServiceQueueTests
|
||||
: public UnitTest
|
||||
{
|
||||
public:
|
||||
|
||||
struct BindableServiceQueueRunner
|
||||
struct ThreadWithServiceQueueRunner
|
||||
: public ThreadWithServiceQueue::EntryPoints
|
||||
{
|
||||
ThreadWithServiceQueue m_worker;
|
||||
int cCallCount, c1CallCount, idleInterruptedCount;
|
||||
int cCallCount, c1CallCount;
|
||||
int qCallCount, q1CallCount;
|
||||
int initCalled, exitCalled;
|
||||
|
||||
BindableServiceQueueRunner()
|
||||
: m_worker("BindableServiceQueueRunner")
|
||||
ThreadWithServiceQueueRunner()
|
||||
: m_worker("ThreadWithServiceQueueRunner")
|
||||
, cCallCount(0)
|
||||
, c1CallCount(0)
|
||||
, idleInterruptedCount(0)
|
||||
, qCallCount(0)
|
||||
, q1CallCount(0)
|
||||
, initCalled(0)
|
||||
, exitCalled(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -158,14 +123,9 @@ public:
|
||||
m_worker.stop(true);
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
m_worker.interrupt();
|
||||
}
|
||||
|
||||
void c()
|
||||
{
|
||||
m_worker.queue(&BindableServiceQueueRunner::cImpl, this);
|
||||
m_worker.call(&ThreadWithServiceQueueRunner::cImpl, this);
|
||||
}
|
||||
|
||||
void cImpl()
|
||||
@@ -175,38 +135,66 @@ public:
|
||||
|
||||
void c1(int p1)
|
||||
{
|
||||
m_worker.queue(&BindableServiceQueueRunner::c1Impl, this, p1);
|
||||
m_worker.call(&ThreadWithServiceQueueRunner::c1Impl, this, p1);
|
||||
}
|
||||
|
||||
void c1Impl(int p1)
|
||||
{
|
||||
c1CallCount++;
|
||||
}
|
||||
|
||||
bool threadIdle ()
|
||||
|
||||
void q()
|
||||
{
|
||||
bool interrupted = m_worker.interruptionPoint ();
|
||||
|
||||
if(interrupted)
|
||||
idleInterruptedCount++;
|
||||
|
||||
return interrupted;
|
||||
m_worker.queue(&ThreadWithServiceQueueRunner::qImpl, this);
|
||||
}
|
||||
|
||||
void qImpl()
|
||||
{
|
||||
qCallCount++;
|
||||
}
|
||||
|
||||
void q1(int p1)
|
||||
{
|
||||
m_worker.queue(&ThreadWithServiceQueueRunner::q1Impl, this, p1);
|
||||
}
|
||||
|
||||
void q1Impl(int p1)
|
||||
{
|
||||
q1CallCount++;
|
||||
}
|
||||
|
||||
void threadInit ()
|
||||
{
|
||||
initCalled++;
|
||||
}
|
||||
|
||||
void threadExit ()
|
||||
{
|
||||
exitCalled++;
|
||||
}
|
||||
};
|
||||
|
||||
static int const calls = 10000;
|
||||
static int const calls = 1000;
|
||||
|
||||
void performCalls()
|
||||
{
|
||||
Random r;
|
||||
r.setSeedRandomly();
|
||||
|
||||
BindableServiceQueueRunner runner;
|
||||
|
||||
beginTestCase("Calls and interruptions");
|
||||
ThreadWithServiceQueueRunner runner;
|
||||
|
||||
runner.start();
|
||||
|
||||
for(std::size_t i=0; i<calls; i++)
|
||||
{
|
||||
int wait = r.nextLargeNumber(10).toInteger();
|
||||
|
||||
if(wait % 2)
|
||||
runner.q();
|
||||
else
|
||||
runner.q1Impl(wait);
|
||||
}
|
||||
|
||||
for(std::size_t i=0; i<calls; i++)
|
||||
{
|
||||
int wait = r.nextLargeNumber(10).toInteger();
|
||||
@@ -216,31 +204,32 @@ public:
|
||||
else
|
||||
runner.c1Impl(wait);
|
||||
}
|
||||
|
||||
for(std::size_t i=0; i<calls; i++)
|
||||
runner.interrupt();
|
||||
|
||||
runner.stop();
|
||||
|
||||
// We can only reason that the idle method must have been interrupted
|
||||
// at least once
|
||||
expect ((runner.cCallCount + runner.c1CallCount) == calls);
|
||||
expect (runner.idleInterruptedCount > 0);
|
||||
expect ((runner.qCallCount + runner.q1CallCount) == calls);
|
||||
expect (runner.initCalled == 1);
|
||||
expect (runner.exitCalled == 1);
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
performCalls ();
|
||||
beginTestCase("Calls");
|
||||
|
||||
for(int i=0; i<100; i++)
|
||||
performCalls ();
|
||||
}
|
||||
|
||||
BindableServiceQueueTests () : UnitTest ("BindableServiceQueue", "beast")
|
||||
ThreadWithServiceQueueTests () : UnitTest ("ThreadWithServiceQueue", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static BindableServiceQueueTests bindableServiceQueueTests;
|
||||
|
||||
}
|
||||
static CallQueueTests callQueueTests;
|
||||
|
||||
static ThreadWithServiceQueueTests bindableServiceQueueTests;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright Patrick Dehne <patrick@mysonicweb.de> (www.sonicweb-radio.de)
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -20,72 +21,72 @@
|
||||
#ifndef BEAST_VFLIB_THREADWITHSERVICEQUEUE_H_INCLUDED
|
||||
#define BEAST_VFLIB_THREADWITHSERVICEQUEUE_H_INCLUDED
|
||||
|
||||
#include "BindableServiceQueue.h"
|
||||
#include "CallQueue.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
|
||||
class ThreadWithServiceQueue
|
||||
: public CallQueue
|
||||
{
|
||||
public:
|
||||
/** Entry points for a ThreadWithCallQueue.
|
||||
*/
|
||||
class EntryPoints
|
||||
{
|
||||
public:
|
||||
/** Entry points for a ThreadWithCallQueue.
|
||||
*/
|
||||
class EntryPoints
|
||||
{
|
||||
public:
|
||||
virtual ~EntryPoints () { }
|
||||
virtual ~EntryPoints () { }
|
||||
|
||||
virtual void threadInit () { }
|
||||
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;
|
||||
virtual void threadExit () { }
|
||||
};
|
||||
|
||||
explicit ThreadWithServiceQueue (const String& name);
|
||||
|
||||
~ThreadWithServiceQueue();
|
||||
|
||||
void start (EntryPoints* const entryPoints);
|
||||
|
||||
void stop (bool const wait);
|
||||
|
||||
/** Calls all functors in the queue. Blocks if there are no
|
||||
functors available to run until more functors become
|
||||
available or the queue is stopped
|
||||
|
||||
*/
|
||||
bool synchronize ();
|
||||
|
||||
/** Helper class to work around ThreadWithServiceQueue and Thread both
|
||||
having a run member
|
||||
*/
|
||||
class Worker
|
||||
: public Thread
|
||||
{
|
||||
public:
|
||||
Worker(const String& name, ThreadWithServiceQueue *parent)
|
||||
: Thread(name)
|
||||
, m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
m_parent->runThread();
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadWithServiceQueue *m_parent;
|
||||
};
|
||||
|
||||
void runThread ();
|
||||
|
||||
private:
|
||||
EntryPoints* m_entryPoints;
|
||||
bool m_calledStart;
|
||||
bool m_calledStop;
|
||||
Worker m_thread;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user