mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-02 08:55:53 +00:00
beast, beast::asio improvements and fixes:
* New maybe_const_t alias for maybe_const * New asio::enable_wait_for_async for safe cleanup * New asio::memory_buffer, a managed boost::asio compatible buffer * shared_handler improvements: - Can be 'empty' (no stored handler). - Default constructible as 'empty'. - Safe evaluation in bool contexts, false==empty * Fix is_call_possible metafunction: - Works on empty argument lists - Works with reference types * Replace SafeBool idiom with C++11 explicit operator bool * Move IPAddress function definitions to the header * Move cyclic_iterator to container/ * Remove unused BufferType * Remove obsolete classes: - NamedPipe - ReadWriteLock - ScopedReadLock - ScopedWriteLock - LockGuard
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<ItemGroup>
|
||||
<None Include="..\..\.gitattributes" />
|
||||
<None Include="..\..\.gitignore" />
|
||||
<None Include="..\..\beast\asio\README.md" />
|
||||
<None Include="..\..\beast\crypto\impl\sha2\README" />
|
||||
<None Include="..\..\beast\crypto\impl\sha2\sha2test.pl" />
|
||||
<None Include="..\..\beast\http\impl\http-parser\.gitignore" />
|
||||
@@ -86,8 +87,10 @@
|
||||
<ClInclude Include="..\..\beast\asio\abstract_socket.h" />
|
||||
<ClInclude Include="..\..\beast\asio\bind_handler.h" />
|
||||
<ClInclude Include="..\..\beast\asio\buffer_sequence.h" />
|
||||
<ClInclude Include="..\..\beast\asio\enable_wait_for_async.h" />
|
||||
<ClInclude Include="..\..\beast\asio\io_latency_probe.h" />
|
||||
<ClInclude Include="..\..\beast\asio\IPAddressConversion.h" />
|
||||
<ClInclude Include="..\..\beast\asio\memory_buffer.h" />
|
||||
<ClInclude Include="..\..\beast\asio\placeholders.h" />
|
||||
<ClInclude Include="..\..\beast\asio\shared_handler.h" />
|
||||
<ClInclude Include="..\..\beast\asio\socket_wrapper.h" />
|
||||
@@ -133,6 +136,7 @@
|
||||
<ClInclude Include="..\..\beast\container\aged_unordered_multimap.h" />
|
||||
<ClInclude Include="..\..\beast\container\aged_unordered_multiset.h" />
|
||||
<ClInclude Include="..\..\beast\container\aged_unordered_set.h" />
|
||||
<ClInclude Include="..\..\beast\container\cyclic_iterator.h" />
|
||||
<ClInclude Include="..\..\beast\container\detail\aged_associative_container.h" />
|
||||
<ClInclude Include="..\..\beast\container\detail\aged_ordered_container.h" />
|
||||
<ClInclude Include="..\..\beast\container\detail\aged_container_iterator.h" />
|
||||
@@ -152,7 +156,6 @@
|
||||
<ClInclude Include="..\..\beast\cxx14\memory.h" />
|
||||
<ClInclude Include="..\..\beast\cxx14\type_traits.h" />
|
||||
<ClInclude Include="..\..\beast\cxx14\utility.h" />
|
||||
<ClInclude Include="..\..\beast\cyclic_iterator.h" />
|
||||
<ClInclude Include="..\..\beast\FixedArray.h" />
|
||||
<ClInclude Include="..\..\beast\HeapBlock.h" />
|
||||
<ClInclude Include="..\..\beast\HTTP.h" />
|
||||
@@ -185,14 +188,12 @@
|
||||
<ClInclude Include="..\..\beast\MPL.h" />
|
||||
<ClInclude Include="..\..\beast\mpl\IsCallPossible.h" />
|
||||
<ClInclude Include="..\..\beast\Net.h" />
|
||||
<ClInclude Include="..\..\beast\net\BufferType.h" />
|
||||
<ClInclude Include="..\..\beast\net\detail\Parse.h" />
|
||||
<ClInclude Include="..\..\beast\net\DynamicBuffer.h" />
|
||||
<ClInclude Include="..\..\beast\net\IPAddress.h" />
|
||||
<ClInclude Include="..\..\beast\net\IPAddressV4.h" />
|
||||
<ClInclude Include="..\..\beast\net\IPAddressV6.h" />
|
||||
<ClInclude Include="..\..\beast\net\IPEndpoint.h" />
|
||||
<ClInclude Include="..\..\beast\SafeBool.h" />
|
||||
<ClInclude Include="..\..\beast\SmartPtr.h" />
|
||||
<ClInclude Include="..\..\beast\smart_ptr\AbstractObject.h" />
|
||||
<ClInclude Include="..\..\beast\smart_ptr\ContainerDeletePolicy.h" />
|
||||
@@ -214,7 +215,6 @@
|
||||
<ClInclude Include="..\..\beast\Chrono.h" />
|
||||
<ClInclude Include="..\..\beast\threads\detail\BindHandler.h" />
|
||||
<ClInclude Include="..\..\beast\threads\detail\DispatchedHandler.h" />
|
||||
<ClInclude Include="..\..\beast\threads\LockGuard.h" />
|
||||
<ClInclude Include="..\..\beast\threads\RecursiveMutex.h" />
|
||||
<ClInclude Include="..\..\beast\threads\semaphore.h" />
|
||||
<ClInclude Include="..\..\beast\threads\ServiceQueue.h" />
|
||||
@@ -333,7 +333,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\native\posix_SharedCode.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\native\win32_ComSmartPtr.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\network\MACAddress.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\network\NamedPipe.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\network\Socket.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\streams\BufferedInputStream.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\streams\FileInputSource.h" />
|
||||
@@ -362,10 +361,7 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\HighResolutionTimer.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\InterProcessLock.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\Process.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ReadWriteLock.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ScopedLock.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ScopedReadLock.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ScopedWriteLock.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\SpinDelay.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\thread\DeadlineTimer.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\thread\Workers.h" />
|
||||
@@ -433,6 +429,30 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\bind_handler_tests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\enable_wait_for_async.test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\shared_handler_tests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\wrap_handler_tests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\boost\Boost.cpp" />
|
||||
<ClCompile Include="..\..\beast\chrono\Chrono.cpp" />
|
||||
<ClCompile Include="..\..\beast\chrono\impl\basic_seconds_clock.cpp">
|
||||
@@ -1115,12 +1135,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\posix_NamedPipe.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\win32_Files.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@@ -1163,12 +1177,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\network\NamedPipe.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\network\Socket.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@@ -1277,12 +1285,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\threads\ReadWriteLock.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\threads\SpinDelay.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
<None Include="..\..\scripts\compile.sh">
|
||||
<Filter>scripts</Filter>
|
||||
</None>
|
||||
<None Include="..\..\beast\asio\README.md">
|
||||
<Filter>beast\asio</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="beast_core">
|
||||
@@ -309,6 +312,9 @@
|
||||
<Filter Include="beast\cxx14\tests">
|
||||
<UniqueIdentifier>{1271ee71-5754-46ef-845b-84e53eed11c0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\asio\tests">
|
||||
<UniqueIdentifier>{f2594738-6447-447b-8f51-2d42fbe8a6ee}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\modules\beast_core\beast_core.h">
|
||||
@@ -419,9 +425,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\network\MACAddress.h">
|
||||
<Filter>beast_core\network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\network\NamedPipe.h">
|
||||
<Filter>beast_core\network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\network\Socket.h">
|
||||
<Filter>beast_core\network</Filter>
|
||||
</ClInclude>
|
||||
@@ -482,18 +485,9 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\Process.h">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ReadWriteLock.h">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ScopedLock.h">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ScopedReadLock.h">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\ScopedWriteLock.h">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\time\PerformanceCounter.h">
|
||||
<Filter>beast_core\time</Filter>
|
||||
</ClInclude>
|
||||
@@ -956,9 +950,6 @@
|
||||
<ClInclude Include="..\..\beast\Chrono.h">
|
||||
<Filter>beast</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\SafeBool.h">
|
||||
<Filter>beast</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\config\BeastConfig.h" />
|
||||
<ClInclude Include="..\..\beast\utility\Error.h">
|
||||
<Filter>beast\utility</Filter>
|
||||
@@ -1014,9 +1005,6 @@
|
||||
<ClInclude Include="..\..\beast\net\DynamicBuffer.h">
|
||||
<Filter>beast\net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\net\BufferType.h">
|
||||
<Filter>beast\net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_asio\http\HTTPRequestParser.h">
|
||||
<Filter>beast_asio\http</Filter>
|
||||
</ClInclude>
|
||||
@@ -1032,9 +1020,6 @@
|
||||
<ClInclude Include="..\..\beast\Threads.h">
|
||||
<Filter>beast</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\threads\LockGuard.h">
|
||||
<Filter>beast\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\threads\RecursiveMutex.h">
|
||||
<Filter>beast\threads</Filter>
|
||||
</ClInclude>
|
||||
@@ -1149,9 +1134,6 @@
|
||||
<ClInclude Include="..\..\beast\insight\HookImpl.h">
|
||||
<Filter>beast\insight</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\cyclic_iterator.h">
|
||||
<Filter>beast</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\threads\semaphore.h">
|
||||
<Filter>beast\threads</Filter>
|
||||
</ClInclude>
|
||||
@@ -1323,6 +1305,15 @@
|
||||
<ClInclude Include="..\..\beast\http\impl\http_parser.h">
|
||||
<Filter>beast\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\container\cyclic_iterator.h">
|
||||
<Filter>beast\container</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\asio\enable_wait_for_async.h">
|
||||
<Filter>beast\asio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\asio\memory_buffer.h">
|
||||
<Filter>beast\asio</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\DynamicObject.cpp">
|
||||
@@ -1406,9 +1397,6 @@
|
||||
<ClCompile Include="..\..\modules\beast_core\native\linux_Threads.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\posix_NamedPipe.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\native\win32_Files.cpp">
|
||||
<Filter>beast_core\native</Filter>
|
||||
</ClCompile>
|
||||
@@ -1427,9 +1415,6 @@
|
||||
<ClCompile Include="..\..\modules\beast_core\network\MACAddress.cpp">
|
||||
<Filter>beast_core\network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\network\NamedPipe.cpp">
|
||||
<Filter>beast_core\network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\network\Socket.cpp">
|
||||
<Filter>beast_core\network</Filter>
|
||||
</ClCompile>
|
||||
@@ -1475,9 +1460,6 @@
|
||||
<ClCompile Include="..\..\modules\beast_core\threads\HighResolutionTimer.cpp">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\threads\ReadWriteLock.cpp">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\time\PerformanceCounter.cpp">
|
||||
<Filter>beast_core\time</Filter>
|
||||
</ClCompile>
|
||||
@@ -1910,6 +1892,18 @@
|
||||
<ClCompile Include="..\..\beast\asio\abstract_socket.cpp">
|
||||
<Filter>beast\asio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\bind_handler_tests.cpp">
|
||||
<Filter>beast\asio\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\shared_handler_tests.cpp">
|
||||
<Filter>beast\asio\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\wrap_handler_tests.cpp">
|
||||
<Filter>beast\asio\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\asio\tests\enable_wait_for_async.test.cpp">
|
||||
<Filter>beast\asio\tests</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\TODO.txt">
|
||||
|
||||
2
TODO.txt
2
TODO.txt
@@ -58,8 +58,6 @@ BEAST TODO
|
||||
|
||||
- Rename SharedData to SharedState or something?
|
||||
|
||||
- Figure out what to do with ReadWriteLock, and NamedPipe which uses it?
|
||||
|
||||
- Put BEAST_PUBLIC_FUNCTION in front of all loose functions
|
||||
|
||||
- restructure the repo sources to look like this:
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef BEAST_NET_H_INCLUDED
|
||||
#define BEAST_NET_H_INCLUDED
|
||||
|
||||
#include "net/BufferType.h"
|
||||
#include "net/DynamicBuffer.h"
|
||||
|
||||
#include "net/IPEndpoint.h"
|
||||
|
||||
@@ -1,95 +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_SAFEBOOL_H_INCLUDED
|
||||
#define BEAST_SAFEBOOL_H_INCLUDED
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class SafeBoolBase
|
||||
{
|
||||
private:
|
||||
void disallowed () const { }
|
||||
|
||||
public:
|
||||
void allowed () const { }
|
||||
|
||||
protected:
|
||||
typedef void (SafeBoolBase::*boolean_t) () const;
|
||||
|
||||
SafeBoolBase () { }
|
||||
SafeBoolBase (SafeBoolBase const&) { }
|
||||
SafeBoolBase& operator= (SafeBoolBase const&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
~SafeBoolBase () { }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** Safe evaluation of class as `bool`.
|
||||
|
||||
This allows a class to be safely evaluated as a bool without the usual
|
||||
harmful side effects of the straightforward operator conversion approach.
|
||||
To use it, derive your class from SafeBool and implement `asBoolean()` as:
|
||||
|
||||
@code
|
||||
|
||||
bool asBoolean () const;
|
||||
|
||||
@endcode
|
||||
|
||||
Ideas from http://www.artima.com/cppsource/safebool.html
|
||||
|
||||
@class SafeBool
|
||||
*/
|
||||
template <typename T = void>
|
||||
class SafeBool : public detail::SafeBoolBase
|
||||
{
|
||||
public:
|
||||
operator detail::SafeBoolBase::boolean_t () const
|
||||
{
|
||||
return (static_cast <T const*> (this))->asBoolean ()
|
||||
? &SafeBoolBase::allowed : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
~SafeBool () { }
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
void operator== (SafeBool <T> const& lhs, SafeBool <U> const& rhs)
|
||||
{
|
||||
lhs.disallowed ();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void operator!= (SafeBool <T> const& lhs, SafeBool <U> const& rhs)
|
||||
{
|
||||
lhs.disallowed ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef BEAST_THREADS_H_INCLUDED
|
||||
#define BEAST_THREADS_H_INCLUDED
|
||||
|
||||
#include "threads/LockGuard.h"
|
||||
#include "threads/UnlockGuard.h"
|
||||
#include "threads/TryLockGuard.h"
|
||||
#include "threads/SharedLockGuard.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "tests/wrap_handler_tests.cpp"
|
||||
#include "tests/bind_handler_tests.cpp"
|
||||
#include "tests/enable_wait_for_async.test.cpp"
|
||||
#include "tests/shared_handler_tests.cpp"
|
||||
|
||||
#include "abstract_socket.cpp" // TEMPORARY!
|
||||
|
||||
14
beast/asio/README.md
Normal file
14
beast/asio/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# beast::asio
|
||||
|
||||
Wrappers and utilities to make working with boost::asio easier.
|
||||
|
||||
## Rules for asynchronous objects
|
||||
|
||||
If an object calls asynchronous initiating functions it must either:
|
||||
|
||||
1. Manage its lifetime by being reference counted
|
||||
|
||||
or
|
||||
|
||||
2. Wait for all pending completion handlers to be called before
|
||||
allowing itself to be destroyed.
|
||||
@@ -99,6 +99,21 @@ public:
|
||||
{
|
||||
return m_buffers.end ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
template <class ConstBufferSequence>
|
||||
void
|
||||
assign (ConstBufferSequence const& buffers)
|
||||
{
|
||||
auto const n (std::distance (
|
||||
std::begin (buffers), std::end (buffers)));
|
||||
|
||||
for (int i = 0, auto iter (std::begin (buffers));
|
||||
iter != std::end (buffers); ++iter, ++i)
|
||||
m_buffers[i] = Buffer (boost::asio::buffer_cast <void*> (
|
||||
*iter), boost::asio::buffer_size (*iter));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef buffer_sequence <boost::asio::const_buffer> const_buffers;
|
||||
|
||||
265
beast/asio/enable_wait_for_async.h
Normal file
265
beast/asio/enable_wait_for_async.h
Normal file
@@ -0,0 +1,265 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_ENABLE_WAIT_FOR_ASYNC_H_INCLUDED
|
||||
#define BEAST_ASIO_ENABLE_WAIT_FOR_ASYNC_H_INCLUDED
|
||||
|
||||
#include "wrap_handler.h"
|
||||
|
||||
#include "../mpl/IsCallPossible.h"
|
||||
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include "../cxx14/type_traits.h" // <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Owner, class Handler>
|
||||
class ref_counted_wrapped_handler
|
||||
{
|
||||
private:
|
||||
static_assert (std::is_same <std::decay_t <Owner>, Owner>::value,
|
||||
"Owner cannot be a const or reference type");
|
||||
|
||||
Handler m_handler;
|
||||
std::reference_wrapper <Owner> m_owner;
|
||||
bool m_continuation;
|
||||
|
||||
public:
|
||||
ref_counted_wrapped_handler (Owner& owner,
|
||||
Handler&& handler, bool continuation)
|
||||
: m_handler (std::move (handler))
|
||||
, m_owner (owner)
|
||||
, m_continuation (continuation ? true :
|
||||
boost_asio_handler_cont_helpers::is_continuation (m_handler))
|
||||
{
|
||||
m_owner.get().increment();
|
||||
}
|
||||
|
||||
ref_counted_wrapped_handler (Owner& owner,
|
||||
Handler const& handler, bool continuation)
|
||||
: m_handler (handler)
|
||||
, m_owner (owner)
|
||||
, m_continuation (continuation ? true :
|
||||
boost_asio_handler_cont_helpers::is_continuation (m_handler))
|
||||
{
|
||||
m_owner.get().increment();
|
||||
}
|
||||
|
||||
~ref_counted_wrapped_handler ()
|
||||
{
|
||||
m_owner.get().decrement();
|
||||
}
|
||||
|
||||
ref_counted_wrapped_handler (ref_counted_wrapped_handler const& other)
|
||||
: m_handler (other.m_handler)
|
||||
, m_owner (other.m_owner)
|
||||
, m_continuation (other.m_continuation)
|
||||
{
|
||||
m_owner.get().increment();
|
||||
}
|
||||
|
||||
ref_counted_wrapped_handler (ref_counted_wrapped_handler&& other)
|
||||
: m_handler (std::move (other.m_handler))
|
||||
, m_owner (other.m_owner)
|
||||
, m_continuation (other.m_continuation)
|
||||
{
|
||||
m_owner.get().increment();
|
||||
}
|
||||
|
||||
ref_counted_wrapped_handler& operator= (
|
||||
ref_counted_wrapped_handler const&) = delete;
|
||||
|
||||
template <class... Args>
|
||||
void
|
||||
operator() (Args&&... args)
|
||||
{
|
||||
m_handler (std::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void
|
||||
operator() (Args&&... args) const
|
||||
{
|
||||
m_handler (std::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function& f,
|
||||
ref_counted_wrapped_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (f, h->m_handler);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function const& f,
|
||||
ref_counted_wrapped_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (f, h->m_handler);
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate (std::size_t size,
|
||||
ref_counted_wrapped_handler* h)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate (size, h->m_handler);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate (void* p, std::size_t size,
|
||||
ref_counted_wrapped_handler* h)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate (p, size, h->m_handler);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation (ref_counted_wrapped_handler* h)
|
||||
{
|
||||
return h->m_continuation;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Facilitates blocking until no completion handlers are remaining.
|
||||
If Derived has this member function:
|
||||
|
||||
@code
|
||||
void on_wait_for_async (void)
|
||||
@endcode
|
||||
|
||||
Then it will be called every time the number of pending completion
|
||||
handlers transitions to zero from a non-zero value. The call is made
|
||||
while holding the internal mutex.
|
||||
*/
|
||||
template <class Derived>
|
||||
class enable_wait_for_async
|
||||
{
|
||||
private:
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(
|
||||
has_on_wait_for_async,on_wait_for_async);
|
||||
|
||||
void increment()
|
||||
{
|
||||
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
|
||||
++m_count;
|
||||
}
|
||||
|
||||
void notify (std::true_type)
|
||||
{
|
||||
static_cast <Derived*> (this)->on_wait_for_async();
|
||||
}
|
||||
|
||||
void notify (std::false_type)
|
||||
{
|
||||
}
|
||||
|
||||
void decrement()
|
||||
{
|
||||
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
|
||||
--m_count;
|
||||
if (m_count == 0)
|
||||
{
|
||||
m_cond.notify_all();
|
||||
notify (std::integral_constant <bool,
|
||||
has_on_wait_for_async<Derived, void(void)>::value>());
|
||||
}
|
||||
}
|
||||
|
||||
template <class Owner, class Handler>
|
||||
friend class detail::ref_counted_wrapped_handler;
|
||||
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cond;
|
||||
std::size_t m_count;
|
||||
|
||||
public:
|
||||
/** Blocks if there are any pending completion handlers. */
|
||||
void
|
||||
wait_for_async()
|
||||
{
|
||||
std::unique_lock <decltype (m_mutex)> lock (m_mutex);
|
||||
while (m_count != 0)
|
||||
m_cond.wait (lock);
|
||||
}
|
||||
|
||||
protected:
|
||||
enable_wait_for_async()
|
||||
: m_count (0)
|
||||
{
|
||||
}
|
||||
|
||||
~enable_wait_for_async()
|
||||
{
|
||||
assert (m_count == 0);
|
||||
}
|
||||
|
||||
/** Wraps the specified handler so it can be counted. */
|
||||
/** @{ */
|
||||
template <class Handler>
|
||||
detail::ref_counted_wrapped_handler <
|
||||
enable_wait_for_async,
|
||||
std::remove_reference_t <Handler>
|
||||
>
|
||||
wrap_with_counter (Handler&& handler, bool continuation = false)
|
||||
{
|
||||
return detail::ref_counted_wrapped_handler <enable_wait_for_async,
|
||||
std::remove_reference_t <Handler>> (*this,
|
||||
std::forward <Handler> (handler), continuation);
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
detail::ref_counted_wrapped_handler <
|
||||
enable_wait_for_async,
|
||||
std::remove_reference_t <Handler>
|
||||
>
|
||||
wrap_with_counter (continuation_t, Handler&& handler)
|
||||
{
|
||||
return detail::ref_counted_wrapped_handler <enable_wait_for_async,
|
||||
std::remove_reference_t <Handler>> (*this,
|
||||
std::forward <Handler> (handler), true);
|
||||
}
|
||||
/** @} */
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
423
beast/asio/memory_buffer.h
Normal file
423
beast/asio/memory_buffer.h
Normal file
@@ -0,0 +1,423 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ASIO_MEMORY_BUFFER_H_INCLUDED
|
||||
#define BEAST_ASIO_MEMORY_BUFFER_H_INCLUDED
|
||||
|
||||
#include "../utility/empty_base_optimization.h"
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
template <
|
||||
class T,
|
||||
class Alloc = std::allocator <T>
|
||||
>
|
||||
class memory_buffer
|
||||
: private empty_base_optimization <Alloc>
|
||||
{
|
||||
private:
|
||||
static_assert (std::is_trivially_constructible <T>::value,
|
||||
"T must be trivially constructible");
|
||||
|
||||
typedef empty_base_optimization <Alloc> Base;
|
||||
|
||||
using AllocTraits = std::allocator_traits <Alloc>;
|
||||
|
||||
T* m_base;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef T const* const_pointer;
|
||||
typedef Alloc allocator_type;
|
||||
typedef T* iterator;
|
||||
typedef T const* const_iterator;
|
||||
typedef std::reverse_iterator <iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator <const_iterator> const_reverse_iterator;
|
||||
|
||||
memory_buffer ()
|
||||
: m_base (nullptr)
|
||||
, m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
memory_buffer (memory_buffer&& other)
|
||||
: Base (std::move (other))
|
||||
, m_base (other.m_base)
|
||||
, m_size (other.m_size)
|
||||
{
|
||||
other.m_base = nullptr;
|
||||
other.m_size = 0;
|
||||
}
|
||||
|
||||
explicit memory_buffer (size_type n)
|
||||
: m_base (AllocTraits::allocate (Base::member(), n))
|
||||
, m_size (n)
|
||||
{
|
||||
}
|
||||
|
||||
explicit memory_buffer (Alloc const& alloc)
|
||||
: Base (alloc)
|
||||
, m_base (nullptr)
|
||||
, m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
memory_buffer (size_type n, Alloc const& alloc)
|
||||
: Base (alloc)
|
||||
, m_base (AllocTraits::allocate (Base::member(), n))
|
||||
, m_size (n)
|
||||
{
|
||||
}
|
||||
|
||||
~memory_buffer()
|
||||
{
|
||||
if (m_base != nullptr)
|
||||
AllocTraits::deallocate (Base::member(), m_base, m_size);
|
||||
}
|
||||
|
||||
memory_buffer& operator= (memory_buffer const&) = delete;
|
||||
|
||||
allocator_type
|
||||
get_allocator() const
|
||||
{
|
||||
return Base::member;
|
||||
}
|
||||
|
||||
//
|
||||
// asio support
|
||||
//
|
||||
|
||||
boost::asio::mutable_buffer
|
||||
buffer()
|
||||
{
|
||||
return boost::asio::mutable_buffer (
|
||||
data(), bytes());
|
||||
}
|
||||
|
||||
boost::asio::const_buffer
|
||||
buffer() const
|
||||
{
|
||||
return boost::asio::const_buffer (
|
||||
data(), bytes());
|
||||
}
|
||||
|
||||
boost::asio::mutable_buffers_1
|
||||
buffers()
|
||||
{
|
||||
return boost::asio::mutable_buffers_1 (
|
||||
data(), bytes());
|
||||
}
|
||||
|
||||
boost::asio::const_buffers_1
|
||||
buffers() const
|
||||
{
|
||||
return boost::asio::const_buffers_1 (
|
||||
data(), bytes());
|
||||
}
|
||||
|
||||
operator boost::asio::mutable_buffer()
|
||||
{
|
||||
return buffer();
|
||||
}
|
||||
|
||||
operator boost::asio::const_buffer() const
|
||||
{
|
||||
return buffer();
|
||||
}
|
||||
|
||||
operator boost::asio::mutable_buffers_1()
|
||||
{
|
||||
return buffers();
|
||||
}
|
||||
|
||||
operator boost::asio::const_buffers_1() const
|
||||
{
|
||||
return buffers();
|
||||
}
|
||||
|
||||
//
|
||||
// Element access
|
||||
//
|
||||
|
||||
reference
|
||||
at (size_type pos)
|
||||
{
|
||||
if (! (pos < size()))
|
||||
throw std::out_of_range ("bad array index");
|
||||
return m_base [pos];
|
||||
}
|
||||
|
||||
const_reference
|
||||
at (size_type pos) const
|
||||
{
|
||||
if (! (pos < size()))
|
||||
throw std::out_of_range ("bad array index");
|
||||
return m_base [pos];
|
||||
}
|
||||
|
||||
reference
|
||||
operator[] (size_type pos) noexcept
|
||||
{
|
||||
return m_base [pos];
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator[] (size_type pos) const noexcept
|
||||
{
|
||||
return m_base [pos];
|
||||
}
|
||||
|
||||
reference
|
||||
back() noexcept
|
||||
{
|
||||
return m_base [m_size - 1];
|
||||
}
|
||||
|
||||
const_reference
|
||||
back() const noexcept
|
||||
{
|
||||
return m_base [m_size - 1];
|
||||
}
|
||||
|
||||
reference
|
||||
front() noexcept
|
||||
{
|
||||
return *m_base;
|
||||
}
|
||||
|
||||
const_reference
|
||||
front() const noexcept
|
||||
{
|
||||
return *m_base;
|
||||
}
|
||||
|
||||
pointer
|
||||
data() noexcept
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
|
||||
const_pointer
|
||||
data() const noexcept
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
|
||||
iterator
|
||||
begin() noexcept
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const noexcept
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
cbegin() const noexcept
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
|
||||
iterator
|
||||
end() noexcept
|
||||
{
|
||||
return m_base + m_size;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const noexcept
|
||||
{
|
||||
return m_base + m_size;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
cend() const noexcept
|
||||
{
|
||||
return m_base + m_size;
|
||||
}
|
||||
|
||||
reverse_iterator
|
||||
rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator (end());
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator (cend());
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator (cend());
|
||||
}
|
||||
|
||||
reverse_iterator
|
||||
rend() noexcept
|
||||
{
|
||||
return reverse_iterator (begin());
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator (cbegin());
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator (cbegin());
|
||||
}
|
||||
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_type
|
||||
max_size() const noexcept
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
size_type
|
||||
capacity() const noexcept
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
size_type bytes() const
|
||||
{
|
||||
return m_size * sizeof(T);
|
||||
}
|
||||
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
|
||||
template <class U, class A>
|
||||
friend
|
||||
void
|
||||
swap (memory_buffer <U, A>& lhs,
|
||||
memory_buffer <U, A>& rhs) noexcept;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class T, class Alloc>
|
||||
void
|
||||
swap (memory_buffer <T, Alloc>& lhs,
|
||||
memory_buffer <T, Alloc>& rhs) noexcept
|
||||
{
|
||||
std::swap (lhs.m_base, rhs.m_base);
|
||||
std::swap (lhs.m_size, rhs.m_size);
|
||||
}
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
inline
|
||||
bool
|
||||
operator== (memory_buffer <T, A1> const& lhs,
|
||||
memory_buffer <T, A2> const& rhs)
|
||||
{
|
||||
return std::equal (lhs.cbegin(), lhs.cend(),
|
||||
rhs.cbegin(), rhs.cend());
|
||||
}
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
inline
|
||||
bool
|
||||
operator!= (memory_buffer <T, A1> const& lhs,
|
||||
memory_buffer <T, A2> const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
inline
|
||||
bool
|
||||
operator< (memory_buffer <T, A1> const& lhs,
|
||||
memory_buffer <T, A2> const& rhs)
|
||||
{
|
||||
return std::lexicographical_compare (
|
||||
lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
|
||||
}
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
inline
|
||||
bool
|
||||
operator>= (memory_buffer <T, A1> const& lhs,
|
||||
memory_buffer <T, A2> const& rhs)
|
||||
{
|
||||
return ! (lhs < rhs);
|
||||
}
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
inline
|
||||
bool
|
||||
operator> (memory_buffer <T, A1> const& lhs,
|
||||
memory_buffer <T, A2> const& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
inline
|
||||
bool
|
||||
operator<= (memory_buffer <T, A1> const& lhs,
|
||||
memory_buffer <T, A2> const& rhs)
|
||||
{
|
||||
return ! (rhs < lhs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef BEAST_ASIO_SHARED_HANDLER_H_INCLUDED
|
||||
#define BEAST_ASIO_SHARED_HANDLER_H_INCLUDED
|
||||
|
||||
#include "../Config.h"
|
||||
|
||||
#include "../mpl/IsCallPossible.h"
|
||||
|
||||
#include <functional>
|
||||
@@ -260,9 +262,7 @@ public:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Handler shared reference that provides io_service execution guarantees. */
|
||||
template <
|
||||
class Signature
|
||||
>
|
||||
template <class Signature>
|
||||
class shared_handler
|
||||
{
|
||||
private:
|
||||
@@ -318,6 +318,7 @@ public:
|
||||
operator= (std::nullptr_t)
|
||||
{
|
||||
m_ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_handler&
|
||||
@@ -327,15 +328,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
empty() const
|
||||
shared_handler&
|
||||
operator= (shared_handler&& rhs)
|
||||
{
|
||||
return ! m_ptr.operator bool();
|
||||
m_ptr = std::move (rhs.m_ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
explicit
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return !empty();
|
||||
return m_ptr.operator bool();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -225,14 +225,9 @@ private:
|
||||
|
||||
boost::asio::io_service& get_io_service () override
|
||||
{
|
||||
#if 0
|
||||
// Apparently has_get_io_service always results in false
|
||||
return get_io_service (
|
||||
Enabled <has_get_io_service <this_layer_type,
|
||||
boost::asio::io_service&()> > ());
|
||||
#else
|
||||
return get_io_service (std::true_type ());
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
|
||||
108
beast/asio/tests/enable_wait_for_async.test.cpp
Normal file
108
beast/asio/tests/enable_wait_for_async.test.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 "BeastConfig.h"
|
||||
|
||||
#include "../../../modules/beast_core/beast_core.h" // for UnitTest
|
||||
|
||||
#include "../bind_handler.h"
|
||||
#include "../enable_wait_for_async.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class enable_wait_for_async_Tests : public UnitTest
|
||||
{
|
||||
public:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
void test()
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
void operator()(error_code)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct owner : asio::enable_wait_for_async <owner>
|
||||
{
|
||||
bool notified;
|
||||
|
||||
owner()
|
||||
: notified (false)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
{
|
||||
boost::asio::io_service ios;
|
||||
ios.post (asio::bind_handler (handler(),
|
||||
error_code()));
|
||||
ios.run();
|
||||
ios.reset();
|
||||
wait_for_async();
|
||||
}
|
||||
|
||||
{
|
||||
boost::asio::io_service ios;
|
||||
ios.post (wrap_with_counter (asio::bind_handler (
|
||||
handler(), error_code())));
|
||||
ios.run();
|
||||
wait_for_async();
|
||||
}
|
||||
|
||||
{
|
||||
boost::asio::io_service ios;
|
||||
handler h;
|
||||
ios.post (wrap_with_counter (std::bind (
|
||||
&handler::operator(), &h,
|
||||
error_code())));
|
||||
ios.run();
|
||||
wait_for_async();
|
||||
}
|
||||
}
|
||||
|
||||
void on_wait_for_async()
|
||||
{
|
||||
notified = true;
|
||||
}
|
||||
};
|
||||
|
||||
beginTestCase ("wait_for_async");
|
||||
owner o;
|
||||
o();
|
||||
expect (o.notified);
|
||||
}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
test();
|
||||
}
|
||||
|
||||
enable_wait_for_async_Tests() : UnitTest ("enable_wait_for_async", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static enable_wait_for_async_Tests enable_wait_for_async_tests;
|
||||
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef BEAST_CRYPTO_UNSIGNEDINTEGER_H_INCLUDED
|
||||
#define BEAST_CRYPTO_UNSIGNEDINTEGER_H_INCLUDED
|
||||
|
||||
#include "../SafeBool.h"
|
||||
#include "UnsignedIntegerCalc.h"
|
||||
#include "MurmurHash.h"
|
||||
|
||||
@@ -38,7 +37,7 @@ namespace beast {
|
||||
may not be aligned.
|
||||
*/
|
||||
template <std::size_t Bytes>
|
||||
class UnsignedInteger : public SafeBool <UnsignedInteger <Bytes> >
|
||||
class UnsignedInteger
|
||||
{
|
||||
public:
|
||||
/** Constant for determining the number of bytes. */
|
||||
@@ -201,9 +200,9 @@ public:
|
||||
|
||||
/** Support conversion to `bool`.
|
||||
@return `true` if any bit is non-zero.
|
||||
@see SafeBool
|
||||
*/
|
||||
bool asBoolean () const
|
||||
explicit
|
||||
operator bool() const
|
||||
{
|
||||
return isNotZero ();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ struct DoubleWidthUInt <std::uint32_t>
|
||||
which return results by value cannot be included in the interface.
|
||||
*/
|
||||
template <typename UInt>
|
||||
class UnsignedIntegerCalc : public SafeBool <UnsignedIntegerCalc <UInt> >
|
||||
class UnsignedIntegerCalc
|
||||
{
|
||||
public:
|
||||
typedef typename detail::DoubleWidthUInt <UInt>::type UIntBig;
|
||||
@@ -182,7 +182,8 @@ public:
|
||||
}
|
||||
|
||||
/** Safe conversion to `bool`, `true` means a non-zero value. */
|
||||
bool asBoolean () const
|
||||
explicit
|
||||
operator bool() const
|
||||
{
|
||||
return isNotZero ();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef BEAST_MPL_ISCALLPOSSIBLE_H_INCLUDED
|
||||
#define BEAST_MPL_ISCALLPOSSIBLE_H_INCLUDED
|
||||
|
||||
#include "../cxx14/type_traits.h" // <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
@@ -160,10 +162,11 @@ struct trait_name##_detail
|
||||
BEAST_DEFINE_HAS_MEMBER_FUNCTION(has_member, member_function_name); \
|
||||
}; \
|
||||
\
|
||||
template <typename T, typename IsCallPossibleSignature> \
|
||||
template <typename DT, typename IsCallPossibleSignature> \
|
||||
struct trait_name \
|
||||
{ \
|
||||
private: \
|
||||
typedef std::remove_reference_t <DT> T; \
|
||||
class yes {}; \
|
||||
class no { yes m[2]; }; \
|
||||
struct derived : public T \
|
||||
@@ -197,6 +200,18 @@ struct trait_name
|
||||
static const bool value = false; \
|
||||
}; \
|
||||
\
|
||||
template <typename Result> \
|
||||
struct impl<true, Result(void)> \
|
||||
{ \
|
||||
static typename beast::mpl::is_call_possible_detail::add_reference<derived_type>::type test_me; \
|
||||
\
|
||||
static const bool value = \
|
||||
sizeof( \
|
||||
return_value_check<T, Result>::deduce( \
|
||||
(test_me.member_function_name(), beast::mpl::is_call_possible_detail::void_exp_result<T>())) \
|
||||
) == sizeof(yes); \
|
||||
}; \
|
||||
\
|
||||
template <typename Result, typename Arg> \
|
||||
struct impl<true, Result(Arg)> \
|
||||
{ \
|
||||
|
||||
@@ -1,106 +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_NET_BASICS_BUFFERTYPE_H_INCLUDED
|
||||
#define BEAST_NET_BASICS_BUFFERTYPE_H_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** General linear memory buffer.
|
||||
This wraps the underlying buffer type and provides additional methods
|
||||
to create a uniform interface. Specializations allow asio-compatible
|
||||
buffers without having to include boost/asio.h.
|
||||
*/
|
||||
/** @{ */
|
||||
template <bool IsConst>
|
||||
class BufferType
|
||||
{
|
||||
private:
|
||||
typedef typename std::conditional <IsConst,
|
||||
void const*, void*>::type pointer_type;
|
||||
|
||||
typedef typename std::conditional <IsConst,
|
||||
uint8 const, uint8>::type byte_type;
|
||||
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
|
||||
BufferType ()
|
||||
: m_data (nullptr)
|
||||
, m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
BufferType (BufferType <OtherIsConst> const& other)
|
||||
: m_data (other.template cast <pointer_type> ())
|
||||
, m_size (other.size ())
|
||||
{
|
||||
}
|
||||
|
||||
BufferType (pointer_type data, std::size_t size) noexcept
|
||||
: m_data (data)
|
||||
, m_size (size)
|
||||
{
|
||||
}
|
||||
|
||||
BufferType& operator= (BufferType const& other) noexcept
|
||||
{
|
||||
m_data = other.cast <pointer_type> ();
|
||||
m_size = other.size ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
BufferType& operator= (
|
||||
BufferType <OtherIsConst> const& other) noexcept
|
||||
{
|
||||
m_data = other.template cast <pointer_type> ();
|
||||
m_size = other.size ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T cast () const noexcept
|
||||
{
|
||||
return static_cast <T> (m_data);
|
||||
}
|
||||
|
||||
size_type size () const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
BufferType operator+ (size_type n) const noexcept
|
||||
{
|
||||
return BufferType (cast <byte_type*> (),
|
||||
size () - std::min (size(), n));
|
||||
}
|
||||
|
||||
private:
|
||||
pointer_type m_data;
|
||||
std::size_t m_size;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -40,61 +40,159 @@ class Address
|
||||
{
|
||||
public:
|
||||
/** Create an unspecified IPv4 address. */
|
||||
Address ();
|
||||
Address ()
|
||||
: m_type (ipv4)
|
||||
{
|
||||
}
|
||||
|
||||
/** Create an IPv4 address. */
|
||||
Address (AddressV4 const& addr);
|
||||
Address (AddressV4 const& addr)
|
||||
: m_type (ipv4)
|
||||
, m_v4 (addr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Create an IPv6 address. */
|
||||
Address (AddressV6 const& addr);
|
||||
Address (AddressV6 const& addr)
|
||||
: m_type (ipv6)
|
||||
, m_v6 (addr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Assign a copy from another address in any format. */
|
||||
/** @{ */
|
||||
Address& operator= (AddressV4 const& addr);
|
||||
Address& operator= (AddressV6 const& addr);
|
||||
Address&
|
||||
operator= (AddressV4 const& addr)
|
||||
{
|
||||
m_type = ipv4;
|
||||
m_v6 = AddressV6();
|
||||
m_v4 = addr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Address&
|
||||
operator= (AddressV6 const& addr)
|
||||
{
|
||||
m_type = ipv6;
|
||||
m_v4 = AddressV4();
|
||||
m_v6 = addr;
|
||||
return *this;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Create an Address from a string.
|
||||
@return A pair with the address, and bool set to `true` on success.
|
||||
*/
|
||||
static std::pair <Address, bool> from_string (std::string const& s);
|
||||
static
|
||||
std::pair <Address, bool>
|
||||
from_string (std::string const& s);
|
||||
|
||||
/** Returns a string representing the address. */
|
||||
std::string to_string () const;
|
||||
std::string
|
||||
to_string () const
|
||||
{
|
||||
return (is_v4 ())
|
||||
? IP::to_string (to_v4())
|
||||
: IP::to_string (to_v6());
|
||||
}
|
||||
|
||||
/** Returns `true` if this address represents an IPv4 address. */
|
||||
bool is_v4 () const
|
||||
{ return m_type == ipv4; }
|
||||
bool
|
||||
is_v4 () const
|
||||
{
|
||||
return m_type == ipv4;
|
||||
}
|
||||
|
||||
/** Returns `true` if this address represents an IPv6 address. */
|
||||
bool is_v6 () const
|
||||
{ return m_type == ipv6; }
|
||||
bool
|
||||
is_v6() const
|
||||
{
|
||||
return m_type == ipv6;
|
||||
}
|
||||
|
||||
/** Returns the IPv4 address.
|
||||
Precondition:
|
||||
is_v4() returns true
|
||||
is_v4() == `true`
|
||||
*/
|
||||
AddressV4 const& to_v4 () const;
|
||||
AddressV4 const&
|
||||
to_v4 () const
|
||||
{
|
||||
if (m_type != ipv4)
|
||||
throw std::bad_cast();
|
||||
return m_v4;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the IPv6 address.
|
||||
Precondition:
|
||||
is_v6() returns true
|
||||
is_v6() == `true`
|
||||
*/
|
||||
AddressV6 const& to_v6 () const;
|
||||
AddressV6 const&
|
||||
to_v6 () const
|
||||
{
|
||||
if (m_type != ipv6)
|
||||
throw std::bad_cast();
|
||||
return m_v6;
|
||||
}
|
||||
|
||||
/** Arithmetic comparison. */
|
||||
/** @{ */
|
||||
friend bool operator== (Address const& lhs, Address const& rhs);
|
||||
friend bool operator< (Address const& lhs, Address const& rhs);
|
||||
friend
|
||||
bool
|
||||
operator== (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
if (lhs.is_v4 ())
|
||||
{
|
||||
if (rhs.is_v4 ())
|
||||
return lhs.to_v4() == rhs.to_v4();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.is_v6 ())
|
||||
return lhs.to_v6() == rhs.to_v6();
|
||||
}
|
||||
|
||||
friend bool operator!= (Address const& lhs, Address const& rhs)
|
||||
{ return ! (lhs == rhs); }
|
||||
friend bool operator> (Address const& lhs, Address const& rhs)
|
||||
{ return rhs < lhs; }
|
||||
friend bool operator<= (Address const& lhs, Address const& rhs)
|
||||
{ return ! (lhs > rhs); }
|
||||
friend bool operator>= (Address const& lhs, Address const& rhs)
|
||||
{ return ! (rhs > lhs); }
|
||||
return false;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator< (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
if (lhs.m_type < rhs.m_type)
|
||||
return true;
|
||||
if (lhs.is_v4 ())
|
||||
return lhs.to_v4() < rhs.to_v4();
|
||||
return lhs.to_v6() < rhs.to_v6();
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!= (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator> (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator<= (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
return ! (lhs > rhs);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator>= (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
return ! (rhs > lhs);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
@@ -114,36 +212,104 @@ private:
|
||||
// Properties
|
||||
|
||||
/** Returns `true` if this is a loopback address. */
|
||||
bool is_loopback (Address const& addr);
|
||||
inline
|
||||
bool
|
||||
is_loopback (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_loopback (addr.to_v4 ())
|
||||
: is_loopback (addr.to_v6 ());
|
||||
}
|
||||
|
||||
/** Returns `true` if the address is unspecified. */
|
||||
bool is_unspecified (Address const& addr);
|
||||
inline
|
||||
bool
|
||||
is_unspecified (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_unspecified (addr.to_v4 ())
|
||||
: is_unspecified (addr.to_v6 ());
|
||||
}
|
||||
|
||||
/** Returns `true` if the address is a multicast address. */
|
||||
bool is_multicast (Address const& addr);
|
||||
inline
|
||||
bool
|
||||
is_multicast (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_multicast (addr.to_v4 ())
|
||||
: is_multicast (addr.to_v6 ());
|
||||
}
|
||||
|
||||
/** Returns `true` if the address is a private unroutable address. */
|
||||
bool is_private (Address const& addr);
|
||||
inline
|
||||
bool
|
||||
is_private (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_private (addr.to_v4 ())
|
||||
: is_private (addr.to_v6 ());
|
||||
}
|
||||
|
||||
/** Returns `true` if the address is a public routable address. */
|
||||
bool is_public (Address const& addr);
|
||||
inline
|
||||
bool
|
||||
is_public (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_public (addr.to_v4 ())
|
||||
: is_public (addr.to_v6 ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** boost::hash support. */
|
||||
std::size_t hash_value (Address const& addr);
|
||||
inline
|
||||
std::size_t
|
||||
hash_value (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? hash_value (addr.to_v4())
|
||||
: hash_value (addr.to_v6());
|
||||
}
|
||||
|
||||
/** Returns the address represented as a string. */
|
||||
inline std::string to_string (Address const& addr)
|
||||
{ return addr.to_string (); }
|
||||
{
|
||||
return addr.to_string ();
|
||||
}
|
||||
|
||||
/** Output stream conversion. */
|
||||
template <typename OutputStream>
|
||||
OutputStream& operator<< (OutputStream& os, Address const& addr)
|
||||
{ return os << to_string (addr); }
|
||||
OutputStream&
|
||||
operator<< (OutputStream& os, Address const& addr)
|
||||
{
|
||||
return os << to_string (addr);
|
||||
}
|
||||
|
||||
/** Input stream conversion. */
|
||||
std::istream& operator>> (std::istream& is, Address& addr);
|
||||
inline
|
||||
std::istream&
|
||||
operator>> (std::istream& is, Address& addr)
|
||||
{
|
||||
// VFALCO TODO Support ipv6!
|
||||
AddressV4 addrv4;
|
||||
is >> addrv4;
|
||||
addr = Address (addrv4);
|
||||
return is;
|
||||
}
|
||||
|
||||
inline
|
||||
std::pair <Address, bool>
|
||||
Address::from_string (std::string const& s)
|
||||
{
|
||||
std::stringstream is (s);
|
||||
Address addr;
|
||||
is >> addr;
|
||||
if (! is.fail() && is.rdbuf()->in_avail() == 0)
|
||||
return std::make_pair (addr, true);
|
||||
return std::make_pair (Address (), false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -154,8 +320,11 @@ namespace std {
|
||||
template <>
|
||||
struct hash <beast::IP::Address>
|
||||
{
|
||||
std::size_t operator() (beast::IP::Address const& addr) const
|
||||
{ return hash_value (addr); }
|
||||
std::size_t
|
||||
operator() (beast::IP::Address const& addr) const
|
||||
{
|
||||
return hash_value (addr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -25,150 +25,6 @@
|
||||
namespace beast {
|
||||
namespace IP {
|
||||
|
||||
Address::Address ()
|
||||
: m_type (ipv4)
|
||||
{
|
||||
}
|
||||
|
||||
Address::Address (AddressV4 const& addr)
|
||||
: m_type (ipv4)
|
||||
, m_v4 (addr)
|
||||
{
|
||||
}
|
||||
|
||||
Address::Address (AddressV6 const& addr)
|
||||
: m_type (ipv6)
|
||||
, m_v6 (addr)
|
||||
{
|
||||
}
|
||||
|
||||
Address& Address::operator= (AddressV4 const& addr)
|
||||
{
|
||||
m_type = ipv4;
|
||||
m_v6 = AddressV6();
|
||||
m_v4 = addr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Address& Address::operator= (AddressV6 const& addr)
|
||||
{
|
||||
m_type = ipv6;
|
||||
m_v4 = AddressV4();
|
||||
m_v6 = addr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair <Address, bool> Address::from_string (std::string const& s)
|
||||
{
|
||||
std::stringstream is (s);
|
||||
Address addr;
|
||||
is >> addr;
|
||||
if (! is.fail() && is.rdbuf()->in_avail() == 0)
|
||||
return std::make_pair (addr, true);
|
||||
return std::make_pair (Address (), false);
|
||||
}
|
||||
|
||||
std::string Address::to_string () const
|
||||
{
|
||||
return (is_v4 ())
|
||||
? IP::to_string (to_v4())
|
||||
: IP::to_string (to_v6());
|
||||
}
|
||||
|
||||
AddressV4 const& Address::to_v4 () const
|
||||
{
|
||||
if (m_type != ipv4)
|
||||
throw std::bad_cast();
|
||||
return m_v4;
|
||||
}
|
||||
|
||||
AddressV6 const& Address::to_v6 () const
|
||||
{
|
||||
if (m_type != ipv6)
|
||||
throw std::bad_cast();
|
||||
return m_v6;
|
||||
}
|
||||
|
||||
bool operator== (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
if (lhs.is_v4 ())
|
||||
{
|
||||
if (rhs.is_v4 ())
|
||||
return lhs.to_v4() == rhs.to_v4();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.is_v6 ())
|
||||
return lhs.to_v6() == rhs.to_v6();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator< (Address const& lhs, Address const& rhs)
|
||||
{
|
||||
if (lhs.m_type < rhs.m_type)
|
||||
return true;
|
||||
if (lhs.is_v4 ())
|
||||
return lhs.to_v4() < rhs.to_v4();
|
||||
return lhs.to_v6() < rhs.to_v6();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool is_loopback (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_loopback (addr.to_v4 ())
|
||||
: is_loopback (addr.to_v6 ());
|
||||
}
|
||||
|
||||
bool is_unspecified (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_unspecified (addr.to_v4 ())
|
||||
: is_unspecified (addr.to_v6 ());
|
||||
}
|
||||
|
||||
bool is_multicast (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_multicast (addr.to_v4 ())
|
||||
: is_multicast (addr.to_v6 ());
|
||||
}
|
||||
|
||||
bool is_private (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_private (addr.to_v4 ())
|
||||
: is_private (addr.to_v6 ());
|
||||
}
|
||||
|
||||
bool is_public (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? is_public (addr.to_v4 ())
|
||||
: is_public (addr.to_v6 ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::size_t hash_value (Address const& addr)
|
||||
{
|
||||
return (addr.is_v4 ())
|
||||
? hash_value (addr.to_v4())
|
||||
: hash_value (addr.to_v6());
|
||||
}
|
||||
|
||||
std::istream& operator>> (std::istream& is, Address& addr)
|
||||
{
|
||||
// VFALCO TODO Support ipv6!
|
||||
AddressV4 addrv4;
|
||||
is >> addrv4;
|
||||
addr = Address (addrv4);
|
||||
return is;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class IPAddressTests : public UnitTest
|
||||
|
||||
@@ -1,50 +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_THREADS_LOCKGUARD_H_INCLUDED
|
||||
#define BEAST_THREADS_LOCKGUARD_H_INCLUDED
|
||||
|
||||
#include "../Uncopyable.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
template <typename Mutex>
|
||||
class LockGuard : public Uncopyable
|
||||
{
|
||||
public:
|
||||
typedef Mutex MutexType;
|
||||
|
||||
explicit LockGuard (Mutex const& mutex)
|
||||
: m_mutex (mutex)
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
~LockGuard ()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex const& m_mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -25,10 +25,11 @@
|
||||
#define BEAST_THREADS_RECURSIVEMUTEX_H_INCLUDED
|
||||
|
||||
#include "../Config.h"
|
||||
#include "LockGuard.h"
|
||||
#include "UnlockGuard.h"
|
||||
#include "TryLockGuard.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#if ! BEAST_WINDOWS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
@@ -38,7 +39,7 @@ namespace beast {
|
||||
class RecursiveMutex
|
||||
{
|
||||
public:
|
||||
typedef LockGuard <RecursiveMutex> ScopedLockType;
|
||||
typedef std::lock_guard <RecursiveMutex> ScopedLockType;
|
||||
typedef UnlockGuard <RecursiveMutex> ScopedUnlockType;
|
||||
typedef TryLockGuard <RecursiveMutex> ScopedTryLockType;
|
||||
|
||||
|
||||
@@ -30,19 +30,20 @@ template <typename ScopedType, typename Context, typename Handler>
|
||||
class ScopedWrapper
|
||||
{
|
||||
public:
|
||||
ScopedWrapper (Context const& context, Handler const& handler)
|
||||
ScopedWrapper (Context& context, Handler const& handler)
|
||||
: m_context (context)
|
||||
, m_handler (handler)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
ScopedType const scope (m_context);
|
||||
ScopedType scope (m_context);
|
||||
m_handler();
|
||||
}
|
||||
|
||||
private:
|
||||
Context const& m_context;
|
||||
Context& m_context;
|
||||
Handler m_handler;
|
||||
};
|
||||
|
||||
@@ -63,9 +64,11 @@ public:
|
||||
public:
|
||||
explicit Scope (ScopedWrapperContext const& owner)
|
||||
: m_scope (owner.m_context)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
scoped_type m_scope;
|
||||
scoped_type mutable m_scope;
|
||||
};
|
||||
|
||||
ScopedWrapperContext ()
|
||||
@@ -74,7 +77,8 @@ public:
|
||||
template <typename Arg>
|
||||
explicit ScopedWrapperContext (Arg& arg)
|
||||
: m_context (arg)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
detail::ScopedWrapper <ScopedType, Context, Handler> wrap (
|
||||
@@ -85,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Context m_context;
|
||||
Context mutable m_context;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
#ifndef BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED
|
||||
#define BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED
|
||||
|
||||
#include "LockGuard.h"
|
||||
#include "SharedLockGuard.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Adapts a regular Lockable to conform to the SharedMutex concept.
|
||||
@@ -35,7 +36,7 @@ class SharedMutexAdapter
|
||||
{
|
||||
public:
|
||||
typedef Mutex MutexType;
|
||||
typedef LockGuard <SharedMutexAdapter> LockGuardType;
|
||||
typedef std::lock_guard <SharedMutexAdapter> LockGuardType;
|
||||
typedef SharedLockGuard <SharedMutexAdapter> SharedLockGuardType;
|
||||
|
||||
void lock() const
|
||||
|
||||
@@ -25,9 +25,10 @@
|
||||
#define BEAST_THREADS_SPINLOCK_H_INCLUDED
|
||||
|
||||
#include "../Atomic.h"
|
||||
#include "LockGuard.h"
|
||||
#include "UnlockGuard.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace beast {
|
||||
|
||||
//==============================================================================
|
||||
@@ -47,7 +48,7 @@ class BEAST_API SpinLock : public Uncopyable
|
||||
{
|
||||
public:
|
||||
/** Provides the type of scoped lock to use for locking a SpinLock. */
|
||||
typedef LockGuard <SpinLock> ScopedLockType;
|
||||
typedef std::lock_guard <SpinLock> ScopedLockType;
|
||||
|
||||
/** Provides the type of scoped unlocker to use with a SpinLock. */
|
||||
typedef UnlockGuard <SpinLock> ScopedUnlockType;
|
||||
|
||||
@@ -187,8 +187,8 @@ private:
|
||||
Type object;
|
||||
};
|
||||
|
||||
mutable Atomic<ObjectHolder*> first;
|
||||
SpinLock lock;
|
||||
Atomic<ObjectHolder*> mutable first;
|
||||
SpinLock mutable lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ struct maybe_const
|
||||
typename std::remove_const <T>::type>::type type;
|
||||
};
|
||||
|
||||
/** Alias for omitting `typename`. */
|
||||
template <bool IsConst, class T>
|
||||
using maybe_const_t = typename maybe_const <IsConst,T>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "../Config.h"
|
||||
|
||||
#include "../SafeBool.h"
|
||||
#include "../strings/String.h"
|
||||
|
||||
#include <stdexcept>
|
||||
@@ -43,7 +42,6 @@ namespace beast {
|
||||
*/
|
||||
class Error
|
||||
: public std::exception
|
||||
, public SafeBool <Error>
|
||||
{
|
||||
public:
|
||||
/** Numeric code.
|
||||
@@ -88,7 +86,10 @@ public:
|
||||
Code code () const;
|
||||
bool failed () const;
|
||||
|
||||
bool asBoolean () const;
|
||||
explicit operator bool () const
|
||||
{
|
||||
return code () != success;
|
||||
}
|
||||
|
||||
String const getReasonText () const;
|
||||
String const getSourceFilename () const;
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#ifndef BEAST_UTILITY_JOURNAL_H_INCLUDED
|
||||
#define BEAST_UTILITY_JOURNAL_H_INCLUDED
|
||||
|
||||
#include "../SafeBool.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace beast {
|
||||
@@ -150,7 +148,7 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class Stream : public SafeBool <Stream>
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
/** Create a stream which produces no output. */
|
||||
@@ -177,7 +175,12 @@ public:
|
||||
/** Returns `true` if sink logs anything at this stream's severity. */
|
||||
/** @{ */
|
||||
bool active() const;
|
||||
bool asBoolean() const;
|
||||
|
||||
explicit
|
||||
operator bool() const
|
||||
{
|
||||
return ! m_disabled;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Output stream support. */
|
||||
|
||||
@@ -81,11 +81,6 @@ bool Error::failed () const
|
||||
return code () != success;
|
||||
}
|
||||
|
||||
bool Error::asBoolean () const
|
||||
{
|
||||
return code () != success;
|
||||
}
|
||||
|
||||
String const Error::getReasonText () const
|
||||
{
|
||||
return m_reasonText;
|
||||
|
||||
@@ -211,11 +211,6 @@ bool Journal::Stream::active () const
|
||||
return ! m_disabled && m_sink->active (m_level);
|
||||
}
|
||||
|
||||
bool Journal::Stream::asBoolean () const
|
||||
{
|
||||
return active();
|
||||
}
|
||||
|
||||
Journal::Stream& Journal::Stream::operator= (Stream const& other)
|
||||
{
|
||||
m_sink = other.m_sink;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace InputParser {
|
||||
Or you can use stop() to decide if you should return.
|
||||
After a stop you can use failed () to determine if parsing failed.
|
||||
*/
|
||||
struct State : SafeBool <State>
|
||||
struct State
|
||||
{
|
||||
enum State_t
|
||||
{
|
||||
@@ -54,7 +54,7 @@ struct State : SafeBool <State>
|
||||
bool stop () const noexcept { return m_state != pass; }
|
||||
bool passed () const noexcept { return m_state == pass; }
|
||||
bool failed () const noexcept { return m_state == fail; }
|
||||
bool asBoolean () const noexcept { return m_state == pass; } // for SafeBool<>
|
||||
explicit operator bool() const noexcept { return m_state == pass; }
|
||||
|
||||
private:
|
||||
State_t m_state;
|
||||
|
||||
@@ -163,7 +163,6 @@ namespace beast
|
||||
#include "misc/Uuid.cpp"
|
||||
|
||||
#include "network/MACAddress.cpp"
|
||||
#include "network/NamedPipe.cpp"
|
||||
#include "network/Socket.cpp"
|
||||
|
||||
#include "streams/BufferedInputStream.cpp"
|
||||
@@ -188,7 +187,6 @@ namespace beast
|
||||
#include "thread/Workers.cpp"
|
||||
|
||||
#include "threads/ChildProcess.cpp"
|
||||
#include "threads/ReadWriteLock.cpp"
|
||||
#include "threads/SpinDelay.cpp"
|
||||
|
||||
#include "time/PerformanceCounter.cpp"
|
||||
@@ -218,7 +216,6 @@ namespace beast
|
||||
|
||||
#if ! BEAST_WINDOWS
|
||||
#include "native/posix_SharedCode.h"
|
||||
#include "native/posix_NamedPipe.cpp"
|
||||
#endif
|
||||
|
||||
#if BEAST_MAC || BEAST_IOS
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
#include "../../beast/Memory.h"
|
||||
#include "../../beast/Intrusive.h"
|
||||
#include "../../beast/Net.h"
|
||||
#include "../../beast/SafeBool.h"
|
||||
#include "../../beast/Strings.h"
|
||||
#include "../../beast/TypeTraits.h"
|
||||
#include "../../beast/Threads.h"
|
||||
@@ -181,8 +180,6 @@ class FileOutputStream;
|
||||
#include "misc/Uuid.h"
|
||||
#include "misc/WindowsRegistry.h"
|
||||
#include "network/MACAddress.h"
|
||||
#include "threads/ReadWriteLock.h"
|
||||
#include "network/NamedPipe.h"
|
||||
#include "network/Socket.h"
|
||||
#include "streams/BufferedInputStream.h"
|
||||
#include "streams/MemoryInputStream.h"
|
||||
@@ -198,8 +195,6 @@ class FileOutputStream;
|
||||
#include "threads/HighResolutionTimer.h"
|
||||
#include "threads/InterProcessLock.h"
|
||||
#include "threads/Process.h"
|
||||
#include "threads/ScopedReadLock.h"
|
||||
#include "threads/ScopedWriteLock.h"
|
||||
#include "diagnostic/UnitTest.h"
|
||||
#include "xml/XmlDocument.h"
|
||||
#include "xml/XmlElement.h"
|
||||
|
||||
@@ -130,7 +130,7 @@ void UnitTest::beginTestCase (String const& name)
|
||||
m_case = new Case (name, m_className);
|
||||
}
|
||||
|
||||
bool UnitTest::expect (bool trueCondition, String const& failureMessage)
|
||||
bool UnitTest::expect_bool (bool trueCondition, String const& failureMessage)
|
||||
{
|
||||
if (trueCondition)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ bool UnitTest::expect (bool trueCondition, String const& failureMessage)
|
||||
return trueCondition;
|
||||
}
|
||||
|
||||
bool UnitTest::unexpected (bool falseCondition, String const& failureMessage)
|
||||
bool UnitTest::unexpected_bool (bool falseCondition, String const& failureMessage)
|
||||
{
|
||||
return expect (! falseCondition, failureMessage);
|
||||
}
|
||||
|
||||
@@ -266,16 +266,34 @@ public:
|
||||
|
||||
If Suite is true, a pass is logged; if it's false, a failure is logged.
|
||||
If the failure message is specified, it will be written to the log if the test fails.
|
||||
|
||||
Requirements:
|
||||
Condition must be explicitly convertible to bool
|
||||
*/
|
||||
bool expect (bool trueCondition, String const& failureMessage = String::empty);
|
||||
template <class Condition>
|
||||
bool expect (Condition trueCondition, String const& failureMessage = String::empty)
|
||||
{
|
||||
return expect_bool (!!trueCondition, failureMessage);
|
||||
}
|
||||
|
||||
bool expect_bool (bool trueCondition, String const& failureMessage);
|
||||
|
||||
/** Checks that the result of a test is false, and logs this result.
|
||||
|
||||
This is basically the opposite of expect().
|
||||
|
||||
@see expect
|
||||
|
||||
Requirements:
|
||||
Condition must be explicitly convertible to bool
|
||||
*/
|
||||
bool unexpected (bool falseCondition, String const& failureMessage = String::empty);
|
||||
template <class Condition>
|
||||
bool unexpected (Condition falseCondition, String const& failureMessage = String::empty)
|
||||
{
|
||||
return unexpected_bool (!!falseCondition, failureMessage);
|
||||
}
|
||||
|
||||
bool unexpected_bool (bool falseCondition, String const& failureMessage);
|
||||
|
||||
/** Compares two values, and if they don't match, prints out a message containing the
|
||||
expected and actual result values.
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class NamedPipe::Pimpl : LeakChecked <Pimpl>, public Uncopyable
|
||||
{
|
||||
public:
|
||||
Pimpl (const String& pipePath, bool createPipe)
|
||||
: pipeInName (pipePath + "_in"),
|
||||
pipeOutName (pipePath + "_out"),
|
||||
pipeIn (-1), pipeOut (-1),
|
||||
createdPipe (createPipe),
|
||||
stopReadOperation (false)
|
||||
{
|
||||
signal (SIGPIPE, signalHandler);
|
||||
beast_siginterrupt (SIGPIPE, 1);
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
{
|
||||
if (pipeIn != -1) ::close (pipeIn);
|
||||
if (pipeOut != -1) ::close (pipeOut);
|
||||
|
||||
if (createdPipe)
|
||||
{
|
||||
unlink (pipeInName.toUTF8());
|
||||
unlink (pipeOutName.toUTF8());
|
||||
}
|
||||
}
|
||||
|
||||
int read (char* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
|
||||
{
|
||||
const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
|
||||
|
||||
if (pipeIn == -1)
|
||||
{
|
||||
pipeIn = openPipe (createdPipe ? pipeInName : pipeOutName, O_RDWR | O_NONBLOCK, timeoutEnd);
|
||||
|
||||
if (pipeIn == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bytesRead = 0;
|
||||
|
||||
while (bytesRead < maxBytesToRead)
|
||||
{
|
||||
const int bytesThisTime = maxBytesToRead - bytesRead;
|
||||
const int numRead = (int) ::read (pipeIn, destBuffer, (size_t) bytesThisTime);
|
||||
|
||||
if (numRead <= 0)
|
||||
{
|
||||
if (errno != EWOULDBLOCK || stopReadOperation || hasExpired (timeoutEnd))
|
||||
return -1;
|
||||
|
||||
const int maxWaitingTime = 30;
|
||||
waitForInput (pipeIn, timeoutEnd == 0 ? maxWaitingTime
|
||||
: bmin (maxWaitingTime,
|
||||
(int) (timeoutEnd - Time::getMillisecondCounter())));
|
||||
continue;
|
||||
}
|
||||
|
||||
bytesRead += numRead;
|
||||
destBuffer += numRead;
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
int write (const char* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
|
||||
{
|
||||
const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
|
||||
|
||||
if (pipeOut == -1)
|
||||
{
|
||||
pipeOut = openPipe (createdPipe ? pipeOutName : pipeInName, O_WRONLY, timeoutEnd);
|
||||
|
||||
if (pipeOut == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bytesWritten = 0;
|
||||
|
||||
while (bytesWritten < numBytesToWrite && ! hasExpired (timeoutEnd))
|
||||
{
|
||||
const int bytesThisTime = numBytesToWrite - bytesWritten;
|
||||
const int numWritten = (int) ::write (pipeOut, sourceBuffer, (size_t) bytesThisTime);
|
||||
|
||||
if (numWritten <= 0)
|
||||
return -1;
|
||||
|
||||
bytesWritten += numWritten;
|
||||
sourceBuffer += numWritten;
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
bool createFifos() const
|
||||
{
|
||||
return (mkfifo (pipeInName .toUTF8(), 0666) == 0 || errno == EEXIST)
|
||||
&& (mkfifo (pipeOutName.toUTF8(), 0666) == 0 || errno == EEXIST);
|
||||
}
|
||||
|
||||
const String pipeInName, pipeOutName;
|
||||
int pipeIn, pipeOut;
|
||||
|
||||
const bool createdPipe;
|
||||
bool stopReadOperation;
|
||||
|
||||
private:
|
||||
static void signalHandler (int) {}
|
||||
|
||||
static uint32 getTimeoutEnd (const int timeOutMilliseconds)
|
||||
{
|
||||
return timeOutMilliseconds >= 0 ? Time::getMillisecondCounter() + (uint32) timeOutMilliseconds : 0;
|
||||
}
|
||||
|
||||
static bool hasExpired (const uint32 timeoutEnd)
|
||||
{
|
||||
return timeoutEnd != 0 && Time::getMillisecondCounter() >= timeoutEnd;
|
||||
}
|
||||
|
||||
int openPipe (const String& name, int flags, const uint32 timeoutEnd)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const int p = ::open (name.toUTF8(), flags);
|
||||
|
||||
if (p != -1 || hasExpired (timeoutEnd) || stopReadOperation)
|
||||
return p;
|
||||
|
||||
Thread::sleep (2);
|
||||
}
|
||||
}
|
||||
|
||||
static void waitForInput (const int handle, const int timeoutMsecs) noexcept
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = timeoutMsecs / 1000;
|
||||
timeout.tv_usec = (timeoutMsecs % 1000) * 1000;
|
||||
|
||||
fd_set rset;
|
||||
FD_ZERO (&rset);
|
||||
FD_SET (handle, &rset);
|
||||
|
||||
select (handle + 1, &rset, nullptr, 0, &timeout);
|
||||
}
|
||||
};
|
||||
|
||||
void NamedPipe::close()
|
||||
{
|
||||
if (pimpl != nullptr)
|
||||
{
|
||||
pimpl->stopReadOperation = true;
|
||||
|
||||
char buffer[1] = { 0 };
|
||||
ssize_t done = ::write (pimpl->pipeIn, buffer, 1);
|
||||
(void) done;
|
||||
|
||||
ScopedWriteLock sl (lock);
|
||||
pimpl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
|
||||
{
|
||||
#if BEAST_IOS
|
||||
pimpl = new Pimpl (File::getSpecialLocation (File::tempDirectory)
|
||||
.getChildFile (File::createLegalFileName (pipeName)).getFullPathName(), createPipe);
|
||||
#else
|
||||
pimpl = new Pimpl ("/tmp/" + File::createLegalFileName (pipeName), createPipe);
|
||||
#endif
|
||||
|
||||
if (createPipe && ! pimpl->createFifos())
|
||||
{
|
||||
pimpl = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
|
||||
{
|
||||
ScopedReadLock sl (lock);
|
||||
return pimpl != nullptr ? pimpl->read (static_cast <char*> (destBuffer), maxBytesToRead, timeOutMilliseconds) : -1;
|
||||
}
|
||||
|
||||
int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
|
||||
{
|
||||
ScopedReadLock sl (lock);
|
||||
return pimpl != nullptr ? pimpl->write (static_cast <const char*> (sourceBuffer), numBytesToWrite, timeOutMilliseconds) : -1;
|
||||
}
|
||||
@@ -883,226 +883,3 @@ void File::revealToUser() const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class NamedPipe::Pimpl : LeakChecked <NamedPipe::Pimpl>, public Uncopyable
|
||||
{
|
||||
public:
|
||||
Pimpl (const String& pipeName, const bool createPipe)
|
||||
: filename ("\\\\.\\pipe\\" + File::createLegalFileName (pipeName)),
|
||||
pipeH (INVALID_HANDLE_VALUE),
|
||||
cancelEvent (CreateEvent (0, FALSE, FALSE, 0)),
|
||||
connected (false), ownsPipe (createPipe), shouldStop (false)
|
||||
{
|
||||
if (createPipe)
|
||||
pipeH = CreateNamedPipe (filename.toWideCharPointer(),
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
|
||||
PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, 0);
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
{
|
||||
disconnectPipe();
|
||||
|
||||
if (pipeH != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (pipeH);
|
||||
|
||||
CloseHandle (cancelEvent);
|
||||
}
|
||||
|
||||
bool connect (const int timeOutMs)
|
||||
{
|
||||
if (! ownsPipe)
|
||||
{
|
||||
if (pipeH != INVALID_HANDLE_VALUE)
|
||||
return true;
|
||||
|
||||
const Time timeOutEnd (Time::getCurrentTime() + RelativeTime::milliseconds (timeOutMs));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
{
|
||||
const ScopedLock sl (createFileLock);
|
||||
|
||||
if (pipeH == INVALID_HANDLE_VALUE)
|
||||
pipeH = CreateFile (filename.toWideCharPointer(),
|
||||
GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||
}
|
||||
|
||||
if (pipeH != INVALID_HANDLE_VALUE)
|
||||
return true;
|
||||
|
||||
if (shouldStop || (timeOutMs >= 0 && Time::getCurrentTime() > timeOutEnd))
|
||||
return false;
|
||||
|
||||
Thread::sleep (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (! connected)
|
||||
{
|
||||
OverlappedEvent over;
|
||||
|
||||
if (ConnectNamedPipe (pipeH, &over.over) == 0)
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_PIPE_CONNECTED: connected = true; break;
|
||||
case ERROR_IO_PENDING:
|
||||
case ERROR_PIPE_LISTENING: connected = waitForIO (over, timeOutMs); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
void disconnectPipe()
|
||||
{
|
||||
if (ownsPipe && connected)
|
||||
{
|
||||
DisconnectNamedPipe (pipeH);
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
int read (void* destBuffer, const int maxBytesToRead, const int timeOutMilliseconds)
|
||||
{
|
||||
while (connect (timeOutMilliseconds))
|
||||
{
|
||||
if (maxBytesToRead <= 0)
|
||||
return 0;
|
||||
|
||||
OverlappedEvent over;
|
||||
unsigned long numRead;
|
||||
|
||||
if (ReadFile (pipeH, destBuffer, (DWORD) maxBytesToRead, &numRead, &over.over))
|
||||
return (int) numRead;
|
||||
|
||||
const DWORD lastError = GetLastError();
|
||||
|
||||
if (lastError == ERROR_IO_PENDING)
|
||||
{
|
||||
if (! waitForIO (over, timeOutMilliseconds))
|
||||
return -1;
|
||||
|
||||
if (GetOverlappedResult (pipeH, &over.over, &numRead, FALSE))
|
||||
return (int) numRead;
|
||||
}
|
||||
|
||||
if (ownsPipe && (GetLastError() == ERROR_BROKEN_PIPE || GetLastError() == ERROR_PIPE_NOT_CONNECTED))
|
||||
disconnectPipe();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
|
||||
{
|
||||
if (connect (timeOutMilliseconds))
|
||||
{
|
||||
if (numBytesToWrite <= 0)
|
||||
return 0;
|
||||
|
||||
OverlappedEvent over;
|
||||
unsigned long numWritten;
|
||||
|
||||
if (WriteFile (pipeH, sourceBuffer, (DWORD) numBytesToWrite, &numWritten, &over.over))
|
||||
return (int) numWritten;
|
||||
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
{
|
||||
if (! waitForIO (over, timeOutMilliseconds))
|
||||
return -1;
|
||||
|
||||
if (GetOverlappedResult (pipeH, &over.over, &numWritten, FALSE))
|
||||
return (int) numWritten;
|
||||
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE && ownsPipe)
|
||||
disconnectPipe();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const String filename;
|
||||
HANDLE pipeH, cancelEvent;
|
||||
bool connected, ownsPipe, shouldStop;
|
||||
CriticalSection createFileLock;
|
||||
|
||||
private:
|
||||
struct OverlappedEvent
|
||||
{
|
||||
OverlappedEvent()
|
||||
{
|
||||
zerostruct (over);
|
||||
over.hEvent = CreateEvent (0, TRUE, FALSE, 0);
|
||||
}
|
||||
|
||||
~OverlappedEvent()
|
||||
{
|
||||
CloseHandle (over.hEvent);
|
||||
}
|
||||
|
||||
OVERLAPPED over;
|
||||
};
|
||||
|
||||
bool waitForIO (OverlappedEvent& over, int timeOutMilliseconds)
|
||||
{
|
||||
if (shouldStop)
|
||||
return false;
|
||||
|
||||
HANDLE handles[] = { over.over.hEvent, cancelEvent };
|
||||
DWORD waitResult = WaitForMultipleObjects (2, handles, FALSE,
|
||||
timeOutMilliseconds >= 0 ? timeOutMilliseconds
|
||||
: INFINITE);
|
||||
|
||||
if (waitResult == WAIT_OBJECT_0)
|
||||
return true;
|
||||
|
||||
CancelIo (pipeH);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void NamedPipe::close()
|
||||
{
|
||||
if (pimpl != nullptr)
|
||||
{
|
||||
pimpl->shouldStop = true;
|
||||
SetEvent (pimpl->cancelEvent);
|
||||
|
||||
ScopedWriteLock sl (lock);
|
||||
pimpl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
|
||||
{
|
||||
pimpl = new Pimpl (pipeName, createPipe);
|
||||
|
||||
if (createPipe && pimpl->pipeH == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
pimpl = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
|
||||
{
|
||||
ScopedReadLock sl (lock);
|
||||
return pimpl != nullptr ? pimpl->read (destBuffer, maxBytesToRead, timeOutMilliseconds) : -1;
|
||||
}
|
||||
|
||||
int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
|
||||
{
|
||||
ScopedReadLock sl (lock);
|
||||
return pimpl != nullptr ? pimpl->write (sourceBuffer, numBytesToWrite, timeOutMilliseconds) : -1;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ bool TrackedMutex::Record::isNotNull () const noexcept
|
||||
return m_mutexName != "";
|
||||
}
|
||||
|
||||
bool TrackedMutex::Record::asBoolean () const noexcept
|
||||
TrackedMutex::Record::operator bool() const noexcept
|
||||
{
|
||||
return isNotNull ();
|
||||
}
|
||||
@@ -170,7 +170,7 @@ bool TrackedMutex::Agent::isNotNull () const noexcept
|
||||
return m_thread != nullptr;
|
||||
}
|
||||
|
||||
bool TrackedMutex::Agent::asBoolean () const noexcept
|
||||
TrackedMutex::Agent::operator bool() const noexcept
|
||||
{
|
||||
return isNotNull ();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
|
||||
/** A triplet identifying a mutex, a thread, and source code location.
|
||||
*/
|
||||
class Record : public SafeBool <Record>
|
||||
class Record
|
||||
{
|
||||
public:
|
||||
Record () noexcept;
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
bool isNull () const noexcept;
|
||||
bool isNotNull () const noexcept;
|
||||
bool asBoolean () const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
/** Returns the name of the mutex.
|
||||
Since the Mutex may not exist after the Record record is
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Describes a thread that can acquire mutexes. */
|
||||
class Agent : public SafeBool <Agent>
|
||||
class Agent
|
||||
{
|
||||
public:
|
||||
Agent () noexcept;
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
|
||||
bool isNull () const noexcept;
|
||||
bool isNotNull () const noexcept;
|
||||
bool asBoolean () const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
/** Returns the name of the thread.
|
||||
The name is generated at the time the Agent record is created,
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
ReadWriteLock::ReadWriteLock() noexcept
|
||||
: numWaitingWriters (0),
|
||||
numWriters (0),
|
||||
writerThreadId (0)
|
||||
{
|
||||
readerThreads.ensureStorageAllocated (16);
|
||||
}
|
||||
|
||||
ReadWriteLock::~ReadWriteLock() noexcept
|
||||
{
|
||||
bassert (readerThreads.size() == 0);
|
||||
bassert (numWriters == 0);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ReadWriteLock::enterRead() const noexcept
|
||||
{
|
||||
while (! tryEnterRead())
|
||||
waitEvent.wait (100);
|
||||
}
|
||||
|
||||
bool ReadWriteLock::tryEnterRead() const noexcept
|
||||
{
|
||||
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
|
||||
|
||||
const SpinLock::ScopedLockType sl (accessLock);
|
||||
|
||||
for (int i = 0; i < readerThreads.size(); ++i)
|
||||
{
|
||||
ThreadRecursionCount& trc = readerThreads.getReference(i);
|
||||
|
||||
if (trc.threadID == threadId)
|
||||
{
|
||||
trc.count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (numWriters + numWaitingWriters == 0
|
||||
|| (threadId == writerThreadId && numWriters > 0))
|
||||
{
|
||||
ThreadRecursionCount trc = { threadId, 1 };
|
||||
readerThreads.add (trc);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadWriteLock::exitRead() const noexcept
|
||||
{
|
||||
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
|
||||
const SpinLock::ScopedLockType sl (accessLock);
|
||||
|
||||
for (int i = 0; i < readerThreads.size(); ++i)
|
||||
{
|
||||
ThreadRecursionCount& trc = readerThreads.getReference(i);
|
||||
|
||||
if (trc.threadID == threadId)
|
||||
{
|
||||
if (--(trc.count) == 0)
|
||||
{
|
||||
readerThreads.remove (i);
|
||||
waitEvent.signal();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bassertfalse; // unlocking a lock that wasn't locked..
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ReadWriteLock::enterWrite() const noexcept
|
||||
{
|
||||
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
|
||||
const SpinLock::ScopedLockType sl (accessLock);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (readerThreads.size() + numWriters == 0
|
||||
|| threadId == writerThreadId
|
||||
|| (readerThreads.size() == 1
|
||||
&& readerThreads.getReference(0).threadID == threadId))
|
||||
{
|
||||
writerThreadId = threadId;
|
||||
++numWriters;
|
||||
break;
|
||||
}
|
||||
|
||||
++numWaitingWriters;
|
||||
accessLock.exit();
|
||||
waitEvent.wait (100);
|
||||
accessLock.enter();
|
||||
--numWaitingWriters;
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadWriteLock::tryEnterWrite() const noexcept
|
||||
{
|
||||
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
|
||||
const SpinLock::ScopedLockType sl (accessLock);
|
||||
|
||||
if (readerThreads.size() + numWriters == 0
|
||||
|| threadId == writerThreadId
|
||||
|| (readerThreads.size() == 1
|
||||
&& readerThreads.getReference(0).threadID == threadId))
|
||||
{
|
||||
writerThreadId = threadId;
|
||||
++numWriters;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadWriteLock::exitWrite() const noexcept
|
||||
{
|
||||
const SpinLock::ScopedLockType sl (accessLock);
|
||||
|
||||
// check this thread actually had the lock..
|
||||
bassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId());
|
||||
|
||||
if (--numWriters == 0)
|
||||
{
|
||||
writerThreadId = 0;
|
||||
waitEvent.signal();
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.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_READWRITELOCK_H_INCLUDED
|
||||
#define BEAST_READWRITELOCK_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A critical section that allows multiple simultaneous readers.
|
||||
|
||||
Features of this type of lock are:
|
||||
|
||||
- Multiple readers can hold the lock at the same time, but only one writer
|
||||
can hold it at once.
|
||||
- Writers trying to gain the lock will be blocked until all readers and writers
|
||||
have released it
|
||||
- Readers trying to gain the lock while a writer is waiting to acquire it will be
|
||||
blocked until the writer has obtained and released it
|
||||
- If a thread already has a read lock and tries to obtain a write lock, it will succeed if
|
||||
there are no other readers
|
||||
- If a thread already has the write lock and tries to obtain a read lock, this will succeed.
|
||||
- Recursive locking is supported.
|
||||
|
||||
@see ScopedReadLock, ScopedWriteLock, CriticalSection
|
||||
*/
|
||||
class BEAST_API ReadWriteLock : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/**
|
||||
Creates a ReadWriteLock object.
|
||||
*/
|
||||
ReadWriteLock() noexcept;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
If the object is deleted whilst locked, any subsequent behaviour
|
||||
is unpredictable.
|
||||
*/
|
||||
~ReadWriteLock() noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Locks this object for reading.
|
||||
|
||||
Multiple threads can simulaneously lock the object for reading, but if another
|
||||
thread has it locked for writing, then this will block until it releases the
|
||||
lock.
|
||||
|
||||
@see exitRead, ScopedReadLock
|
||||
*/
|
||||
void enterRead() const noexcept;
|
||||
|
||||
/** Tries to lock this object for reading.
|
||||
|
||||
Multiple threads can simulaneously lock the object for reading, but if another
|
||||
thread has it locked for writing, then this will fail and return false.
|
||||
|
||||
@returns true if the lock is successfully gained.
|
||||
@see exitRead, ScopedReadLock
|
||||
*/
|
||||
bool tryEnterRead() const noexcept;
|
||||
|
||||
/** Releases the read-lock.
|
||||
|
||||
If the caller thread hasn't got the lock, this can have unpredictable results.
|
||||
|
||||
If the enterRead() method has been called multiple times by the thread, each
|
||||
call must be matched by a call to exitRead() before other threads will be allowed
|
||||
to take over the lock.
|
||||
|
||||
@see enterRead, ScopedReadLock
|
||||
*/
|
||||
void exitRead() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Locks this object for writing.
|
||||
|
||||
This will block until any other threads that have it locked for reading or
|
||||
writing have released their lock.
|
||||
|
||||
@see exitWrite, ScopedWriteLock
|
||||
*/
|
||||
void enterWrite() const noexcept;
|
||||
|
||||
/** Tries to lock this object for writing.
|
||||
|
||||
This is like enterWrite(), but doesn't block - it returns true if it manages
|
||||
to obtain the lock.
|
||||
|
||||
@returns true if the lock is successfully gained.
|
||||
@see enterWrite
|
||||
*/
|
||||
bool tryEnterWrite() const noexcept;
|
||||
|
||||
/** Releases the write-lock.
|
||||
|
||||
If the caller thread hasn't got the lock, this can have unpredictable results.
|
||||
|
||||
If the enterWrite() method has been called multiple times by the thread, each
|
||||
call must be matched by a call to exit() before other threads will be allowed
|
||||
to take over the lock.
|
||||
|
||||
@see enterWrite, ScopedWriteLock
|
||||
*/
|
||||
void exitWrite() const noexcept;
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
SpinLock accessLock;
|
||||
WaitableEvent waitEvent;
|
||||
mutable int numWaitingWriters, numWriters;
|
||||
mutable Thread::ThreadID writerThreadId;
|
||||
|
||||
struct ThreadRecursionCount
|
||||
{
|
||||
Thread::ThreadID threadID;
|
||||
int count;
|
||||
};
|
||||
|
||||
mutable Array <ThreadRecursionCount> readerThreads;
|
||||
};
|
||||
|
||||
|
||||
#endif // BEAST_READWRITELOCK_H_INCLUDED
|
||||
@@ -1,82 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.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_SCOPEDREADLOCK_H_INCLUDED
|
||||
#define BEAST_SCOPEDREADLOCK_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Automatically locks and unlocks a ReadWriteLock object.
|
||||
|
||||
Use one of these as a local variable to control access to a ReadWriteLock.
|
||||
|
||||
e.g. @code
|
||||
|
||||
ReadWriteLock myLock;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const ScopedReadLock myScopedLock (myLock);
|
||||
// myLock is now locked
|
||||
|
||||
...do some stuff...
|
||||
|
||||
// myLock gets unlocked here.
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ReadWriteLock, ScopedWriteLock
|
||||
*/
|
||||
class BEAST_API ScopedReadLock : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a ScopedReadLock.
|
||||
|
||||
As soon as it is created, this will call ReadWriteLock::enterRead(), and
|
||||
when the ScopedReadLock object is deleted, the ReadWriteLock will
|
||||
be unlocked.
|
||||
|
||||
Make sure this object is created and deleted by the same thread,
|
||||
otherwise there are no guarantees what will happen! Best just to use it
|
||||
as a local stack object, rather than creating one with the new() operator.
|
||||
*/
|
||||
inline explicit ScopedReadLock (const ReadWriteLock& lock) noexcept : lock_ (lock) { lock.enterRead(); }
|
||||
|
||||
/** Destructor.
|
||||
|
||||
The ReadWriteLock's exitRead() method will be called when the destructor is called.
|
||||
|
||||
Make sure this object is created and deleted by the same thread,
|
||||
otherwise there are no guarantees what will happen!
|
||||
*/
|
||||
inline ~ScopedReadLock() noexcept { lock_.exitRead(); }
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const ReadWriteLock& lock_;
|
||||
};
|
||||
|
||||
|
||||
#endif // BEAST_SCOPEDREADLOCK_H_INCLUDED
|
||||
@@ -1,82 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.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_SCOPEDWRITELOCK_H_INCLUDED
|
||||
#define BEAST_SCOPEDWRITELOCK_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Automatically locks and unlocks a ReadWriteLock object.
|
||||
|
||||
Use one of these as a local variable to control access to a ReadWriteLock.
|
||||
|
||||
e.g. @code
|
||||
|
||||
ReadWriteLock myLock;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const ScopedWriteLock myScopedLock (myLock);
|
||||
// myLock is now locked
|
||||
|
||||
...do some stuff...
|
||||
|
||||
// myLock gets unlocked here.
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ReadWriteLock, ScopedReadLock
|
||||
*/
|
||||
class BEAST_API ScopedWriteLock : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a ScopedWriteLock.
|
||||
|
||||
As soon as it is created, this will call ReadWriteLock::enterWrite(), and
|
||||
when the ScopedWriteLock object is deleted, the ReadWriteLock will
|
||||
be unlocked.
|
||||
|
||||
Make sure this object is created and deleted by the same thread,
|
||||
otherwise there are no guarantees what will happen! Best just to use it
|
||||
as a local stack object, rather than creating one with the new() operator.
|
||||
*/
|
||||
inline explicit ScopedWriteLock (const ReadWriteLock& lock) noexcept : lock_ (lock) { lock.enterWrite(); }
|
||||
|
||||
/** Destructor.
|
||||
|
||||
The ReadWriteLock's exitWrite() method will be called when the destructor is called.
|
||||
|
||||
Make sure this object is created and deleted by the same thread,
|
||||
otherwise there are no guarantees what will happen!
|
||||
*/
|
||||
inline ~ScopedWriteLock() noexcept { lock_.exitWrite(); }
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const ReadWriteLock& lock_;
|
||||
};
|
||||
|
||||
|
||||
#endif // BEAST_SCOPEDWRITELOCK_H_INCLUDED
|
||||
Reference in New Issue
Block a user