From 9534516b42794cbb7777d4b65d22dc33f9cd1bc8 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 20 Sep 2013 02:36:47 -0700 Subject: [PATCH] Add some thread classes and fix SharedData with a simple mutex adapter --- Builds/VisualStudio2012/beast.vcxproj | 8 +- Builds/VisualStudio2012/beast.vcxproj.filters | 27 +- beast/Thread.h | 28 ++ .../beast_core/memory => beast}/Uncopyable.h | 11 +- beast/thread/LockGuard.h | 51 +++ beast/thread/SharedData.h | 299 ++++++++++++++++++ beast/thread/SharedLockGuard.h | 52 +++ beast/thread/SharedMutexAdapter.h | 65 ++++ modules/beast_core/beast_core.h | 4 +- modules/beast_core/memory/SharedFunction.h | 4 +- modules/beast_core/memory/SharedPtr.h | 16 + modules/beast_core/thread/CallQueue.h | 4 +- modules/beast_core/thread/Listeners.h | 4 +- .../beast_core/thread/impl/TrackedMutex.cpp | 12 +- modules/beast_core/threads/SharedData.h | 295 ----------------- modules/beast_core/threads/Thread.h | 4 +- modules/beast_db/keyvalue/KeyvaDB.cpp | 22 +- 17 files changed, 574 insertions(+), 332 deletions(-) create mode 100644 beast/Thread.h rename {modules/beast_core/memory => beast}/Uncopyable.h (95%) create mode 100644 beast/thread/LockGuard.h create mode 100644 beast/thread/SharedData.h create mode 100644 beast/thread/SharedLockGuard.h create mode 100644 beast/thread/SharedMutexAdapter.h delete mode 100644 modules/beast_core/threads/SharedData.h diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj index 387b043837..4a9f54f584 100644 --- a/Builds/VisualStudio2012/beast.vcxproj +++ b/Builds/VisualStudio2012/beast.vcxproj @@ -85,11 +85,17 @@ + + + + + + @@ -224,7 +230,6 @@ - @@ -286,7 +291,6 @@ - diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters index c22a2ee528..c1e7053db9 100644 --- a/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Builds/VisualStudio2012/beast.vcxproj.filters @@ -204,6 +204,9 @@ {775ab0d6-aa5f-43d7-ab3b-3c01652a9ef1} + + {da8084c0-491b-4eb0-b750-97182a9deed4} + @@ -576,9 +579,6 @@ beast_core\diagnostic - - beast_core\memory - beast_core\maths @@ -699,9 +699,6 @@ beast_core\threads - - beast_core\threads - beast_core\thread @@ -1080,6 +1077,24 @@ beast\mpl + + beast + + + beast\thread + + + beast\thread + + + beast\thread + + + beast\thread + + + beast + diff --git a/beast/Thread.h b/beast/Thread.h new file mode 100644 index 0000000000..33849429c6 --- /dev/null +++ b/beast/Thread.h @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREAD_H_INCLUDED +#define BEAST_THREAD_H_INCLUDED + +#include "thread/LockGuard.h" +#include "thread/SharedLockGuard.h" +#include "thread/SharedMutexAdapter.h" +#include "thread/SharedData.h" + +#endif diff --git a/modules/beast_core/memory/Uncopyable.h b/beast/Uncopyable.h similarity index 95% rename from modules/beast_core/memory/Uncopyable.h rename to beast/Uncopyable.h index 0ddf154c4e..20a41770ba 100644 --- a/modules/beast_core/memory/Uncopyable.h +++ b/beast/Uncopyable.h @@ -20,6 +20,11 @@ #ifndef BEAST_UNCOPYABLE_H_INCLUDED #define BEAST_UNCOPYABLE_H_INCLUDED +namespace beast +{ + +// Ideas from boost + /** Prevent copy construction and assignment. This is used to suppress warnings and prevent unsafe operations on @@ -59,12 +64,14 @@ class Uncopyable { protected: - inline Uncopyable () { } - inline ~Uncopyable () { } + Uncopyable () { } + ~Uncopyable () { } private: Uncopyable (Uncopyable const&); Uncopyable const& operator= (Uncopyable const&); }; +} + #endif diff --git a/beast/thread/LockGuard.h b/beast/thread/LockGuard.h new file mode 100644 index 0000000000..b933a9e6f7 --- /dev/null +++ b/beast/thread/LockGuard.h @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREAD_LOCKGUARD_H_INCLUDED +#define BEAST_THREAD_LOCKGUARD_H_INCLUDED + +#include "../Uncopyable.h" + +namespace beast +{ + +template +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 diff --git a/beast/thread/SharedData.h b/beast/thread/SharedData.h new file mode 100644 index 0000000000..6039785517 --- /dev/null +++ b/beast/thread/SharedData.h @@ -0,0 +1,299 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREAD_SHAREDDATA_H_INCLUDED +#define BEAST_THREAD_SHAREDDATA_H_INCLUDED + +namespace beast +{ + +class CriticalSection; + +/** Structured, multi-threaded access to a shared state. + + This container combines locking semantics with data access semantics to + create an alternative to the typical synchronization method of first + acquiring a lock and then accessing data members. + + With this container, access to the underlying data is only possible after + first acquiring a lock. The steps of acquiring the lock and obtaining + a const or non-const reference to the data are combined into one + RAII style operation. + + There are three types of access: + + - Access + Provides access to the shared state via a non-const reference or pointer. + Access acquires a unique lock on the mutex associated with the + container. + + - ConstAccess + Provides access to the shared state via a const reference or pointer. + ConstAccess acquires a shared lock on the mutex associated with the + container. + + - UnlockedAccess + Provides access to the shared state via a const reference or pointer. + No locking is performed. It is the callers responsibility to ensure that + the operation is synchronized. This can be useful for diagnostics or + assertions, or for when it is known that no other threads can access + the data. + + Usage example: + + @code + + struct State + { + int value1; + String value2; + }; + + typedef SharedData SharedState; + + SharedState m_state; + + void readExample () + { + SharedState::ConstAccess state (m_state); + + print (state->value1); // read access + print (state->value2); // read access + + state->value1 = 42; // write disallowed: compile error + } + + void writeExample () + { + SharedState::Access state (m_state); + + state->value2 = "Label"; // write access, allowed + } + + @endcode + + Requirements for Value: + Constructible + Destructible + + Requirements for SharedMutexType: + X is SharedMutexType, a is an instance of X: + X a; DefaultConstructible + X::LockGuardType Names a type that implements the LockGuard concept. + X::SharedLockGuardType Names a type that implements the SharedLockGuard concept. + + @tparam Value The type which the container holds. + @tparam SharedMutexType The type of shared mutex to use. +*/ +template > +class SharedData : public Uncopyable +{ +private: + typedef typename SharedMutexType::LockGuardType LockGuardType; + typedef typename SharedMutexType::SharedLockGuardType SharedLockGuardType; + +public: + typedef Value ValueType; + + class Access; + class ConstAccess; + class UnlockedAccess; + + /** Create a shared data container. + Up to 8 parameters can be specified in the constructor. These parameters + are forwarded to the corresponding constructor in Data. If no + constructor in Data matches the parameter list, a compile error is + generated. + */ + /** @{ */ + SharedData () { } + + template + explicit SharedData (T1 t1) + : m_value (t1) { } + + template + SharedData (T1 t1, T2 t2) + : m_value (t1, t2) { } + + template + SharedData (T1 t1, T2 t2, T3 t3) + : m_value (t1, t2, t3) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4) + : m_value (t1, t2, t3, t4) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) + : m_value (t1, t2, t3, t4, t5) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) + : m_value (t1, t2, t3, t4, t5, t6) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : m_value (t1, t2, t3, t4, t5, t6, t7) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) + : m_value (t1, t2, t3, t4, t5, t6, t7, t8) { } + /** @} */ + +private: + Value m_value; + SharedMutexType m_mutex; +}; + +//------------------------------------------------------------------------------ + +/** Provides non-const access to the contents of a SharedData. + This acquires a unique lock on the underlying mutex. +*/ +template +class SharedData ::Access : public Uncopyable +{ +public: + explicit Access (SharedData& state) + : m_state (state) + , m_lock (m_state.m_mutex) + { + } + + /** Returns a const reference to the data. */ + Data const& get () const + { + return m_state.m_value; + } + + /** Returns a const reference to the data. */ + Data const& operator* () const + { + return get (); + } + + /** Returns a const pointer to the data. */ + Data const* operator-> () const + { + return &get (); + } + + /** Returns a non-const reference to the data. */ + Data& get () + { + return m_state.m_value; + } + + /** Returns a non-const reference to the data. */ + Data& operator* () + { + return get (); + } + + /** Returns a non-const pointer to the data. */ + Data* operator-> () + { + return &get (); + } + +private: + SharedData& m_state; + typename SharedData::LockGuardType m_lock; +}; + +//------------------------------------------------------------------------------ + +/** Provides const access to the contents of a SharedData. + This acquires a shared lock on the underlying mutex. +*/ +template +class SharedData ::ConstAccess : public Uncopyable +{ +public: + /** Create a ConstAccess from the specified SharedData */ + explicit ConstAccess (SharedData const volatile& state) + : m_state (const_cast (state)) + , m_lock (m_state.m_mutex) + { + } + + /** Returns a const reference to the data. */ + Data const& get () const + { + return m_state.m_value; + } + + /** Returns a const reference to the data. */ + Data const& operator* () const + { + return get (); + } + + /** Returns a const pointer to the data. */ + Data const* operator-> () const + { + return &get (); + } + +private: + SharedData const& m_state; + typename SharedData::SharedLockGuardType m_lock; +}; + +//------------------------------------------------------------------------------ + +/** Provides const access to the contents of a SharedData. + This acquires a shared lock on the underlying mutex. +*/ +template +class SharedData ::UnlockedAccess : public Uncopyable +{ +public: + /** Create an UnlockedAccess from the specified SharedData */ + explicit UnlockedAccess (SharedData const volatile& state) + : m_state (const_cast (state)) + { + } + + /** Returns a const reference to the data. */ + Data const& get () const + { + return m_state.m_value; + } + + /** Returns a const reference to the data. */ + Data const& operator* () const + { + return get (); + } + + /** Returns a const pointer to the data. */ + Data const* operator-> () const + { + return &get (); + } + +private: + SharedData const& m_state; +}; + +} + +#endif diff --git a/beast/thread/SharedLockGuard.h b/beast/thread/SharedLockGuard.h new file mode 100644 index 0000000000..07fd7ab097 --- /dev/null +++ b/beast/thread/SharedLockGuard.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREAD_SHAREDLOCKGUARD_H_INCLUDED +#define BEAST_THREAD_SHAREDLOCKGUARD_H_INCLUDED + +#include "../Uncopyable.h" + +namespace beast +{ + +/** A scoped container that acquires a shared lock. */ +template +class SharedLockGuard : public Uncopyable +{ +public: + typedef Mutex MutexType; + + explicit SharedLockGuard (Mutex const& mutex) + : m_mutex (mutex) + { + m_mutex.lock_shared(); + } + + ~SharedLockGuard () + { + m_mutex.unlock_shared(); + } + +private: + Mutex const& m_mutex; +}; + +} + +#endif diff --git a/beast/thread/SharedMutexAdapter.h b/beast/thread/SharedMutexAdapter.h new file mode 100644 index 0000000000..2e5252a6b2 --- /dev/null +++ b/beast/thread/SharedMutexAdapter.h @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREAD_SHAREDMUTEXADAPTER_H_INCLUDED +#define BEAST_THREAD_SHAREDMUTEXADAPTER_H_INCLUDED + +namespace beast +{ + +/** Adapts a regular Lockable to conform to the SharedMutex concept. + Shared locks become unique locks with this interface. Two threads may not + simultaneously acquire ownership of the lock. Typically the Mutex template + parameter will be a CriticalSection. +*/ +template +class SharedMutexAdapter +{ +public: + typedef Mutex MutexType; + typedef LockGuard LockGuardType; + typedef SharedLockGuard SharedLockGuardType; + + void lock() const + { + m_mutex.lock(); + } + + void unlock() const + { + m_mutex.unlock(); + } + + void lock_shared() const + { + m_mutex.lock(); + } + + void unlock_shared() const + { + m_mutex.unlock(); + } + +private: + Mutex mutable m_mutex; +}; + +} + +#endif diff --git a/modules/beast_core/beast_core.h b/modules/beast_core/beast_core.h index 727149d13b..6d44572508 100644 --- a/modules/beast_core/beast_core.h +++ b/modules/beast_core/beast_core.h @@ -78,6 +78,7 @@ #include "../../beast/CStdInt.h" #include "../../beast/StaticAssert.h" +#include "../../beast/Uncopyable.h" namespace beast { @@ -94,7 +95,6 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n // Add new includes to the bottom. #include "diagnostic/ContractChecks.h" -#include "memory/Uncopyable.h" #include "memory/Memory.h" #include "maths/MathsFunctions.h" #include "memory/ByteOrder.h" @@ -108,6 +108,7 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n // New header-only library modeled more closely according to boost #include "../../beast/intrusive/ForwardList.h" #include "../../beast/Net.h" +#include "../../beast/Thread.h" //------------------------------------------------------------------------------ @@ -161,7 +162,6 @@ namespace beast #include "memory/MemoryAlignment.h" #include "memory/CacheLine.h" #include "threads/ReadWriteMutex.h" -#include "threads/SharedData.h" #include "diagnostic/SafeBool.h" #include "threads/WaitableEvent.h" #include "threads/Thread.h" diff --git a/modules/beast_core/memory/SharedFunction.h b/modules/beast_core/memory/SharedFunction.h index 693982da17..0d7b78089a 100644 --- a/modules/beast_core/memory/SharedFunction.h +++ b/modules/beast_core/memory/SharedFunction.h @@ -53,7 +53,7 @@ public: R operator() () { - return m_f (); + return (m_f)(); } private: @@ -136,7 +136,7 @@ public: R operator() (P1 p1) { - return m_f (p1); + return (m_f)(p1); } private: diff --git a/modules/beast_core/memory/SharedPtr.h b/modules/beast_core/memory/SharedPtr.h index 989950d24a..f69431c5a9 100644 --- a/modules/beast_core/memory/SharedPtr.h +++ b/modules/beast_core/memory/SharedPtr.h @@ -262,6 +262,22 @@ private: //------------------------------------------------------------------------------ +// bind() helpers for pointer to member function + +template +const T* get_pointer (SharedPtr const& ptr) +{ + return ptr.get(); +} + +template +T* get_pointer (SharedPtr& ptr) +{ + return ptr.get(); +} + +//------------------------------------------------------------------------------ + /** SharedPtr comparisons. */ /** @{ */ template diff --git a/modules/beast_core/thread/CallQueue.h b/modules/beast_core/thread/CallQueue.h index 352844e028..3c2ee4a25d 100644 --- a/modules/beast_core/thread/CallQueue.h +++ b/modules/beast_core/thread/CallQueue.h @@ -299,7 +299,7 @@ public: void stateChanged () { - SharedData ::ReadAccess state (sharedState); + SharedData ::ConstAccess state (sharedState); // (read state) } @@ -308,7 +308,7 @@ public: void changeState () { - SharedData ::WriteAccess state (sharedState); + SharedData ::Access state (sharedState); // (read and write state) diff --git a/modules/beast_core/thread/Listeners.h b/modules/beast_core/thread/Listeners.h index e6f33ecb3b..dde6a203f7 100644 --- a/modules/beast_core/thread/Listeners.h +++ b/modules/beast_core/thread/Listeners.h @@ -137,7 +137,7 @@ void addListener (Listener* listener, CallQueue& callQueue) { // Acquire read access to the shared state. - SharedData ::ReadAccess state (m_state); + SharedData ::ConstAccess state (m_state); // Add the listener. m_listeners.add (listener, callQueue); @@ -171,7 +171,7 @@ // Update shared state. { - SharedData ::WriteAccess state (m_state); + SharedData ::Access state (m_state); m_state->outputLevel = newOutputLevel; } diff --git a/modules/beast_core/thread/impl/TrackedMutex.cpp b/modules/beast_core/thread/impl/TrackedMutex.cpp index f76fa6aa93..bf62599dca 100644 --- a/modules/beast_core/thread/impl/TrackedMutex.cpp +++ b/modules/beast_core/thread/impl/TrackedMutex.cpp @@ -205,7 +205,7 @@ bool TrackedMutex::Agent::getLockedList (Array & output) { TrackedMutex const& mutex = *iter; { - TrackedMutex::SharedState::ReadAccess state (mutex.m_state); + TrackedMutex::SharedState::ConstAccess state (mutex.m_state); output.add (state->owner); } } @@ -237,7 +237,7 @@ String TrackedMutex::getName () const noexcept TrackedMutex::Record TrackedMutex::getOwnerRecord () const noexcept { { - SharedState::ReadAccess state (m_state); + SharedState::ConstAccess state (m_state); return state->owner; } } @@ -245,7 +245,7 @@ TrackedMutex::Record TrackedMutex::getOwnerRecord () const noexcept TrackedMutex::Agent TrackedMutex::getOwnerAgent () const noexcept { { - SharedState::ReadAccess state (m_state); + SharedState::ConstAccess state (m_state); if (state->thread != nullptr) return Agent (state->thread); } @@ -298,7 +298,7 @@ void TrackedMutex::generateGlobalBlockedReport (StringArray& report) { String s; TrackedMutex const& mutex (*iter); - TrackedMutex::SharedState::ReadAccess state (mutex.m_state); + TrackedMutex::SharedState::ConstAccess state (mutex.m_state); s << " " << mutex.getName () << " from " << state->owner.getSourceLocation (); report.add (s); @@ -372,7 +372,7 @@ void TrackedMutex::acquired (char const* fileName, int lineNumber) const noexcep { // Take a state lock. - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); // Set the mutex ownership record state->owner = Record (getName (), threadName, sourceLocation); @@ -428,7 +428,7 @@ void TrackedMutex::release () const noexcept { // Take the mutex' state lock - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); // Clear the mutex ownership record state->owner = Record (); diff --git a/modules/beast_core/threads/SharedData.h b/modules/beast_core/threads/SharedData.h deleted file mode 100644 index 3afc5b123a..0000000000 --- a/modules/beast_core/threads/SharedData.h +++ /dev/null @@ -1,295 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_SHAREDDATA_H_INCLUDED -#define BEAST_SHAREDDATA_H_INCLUDED - -/** Structured access to a shared state. - - This template wraps an object containing members representing state - information shared between multiple threads of execution, where any thread - may need to read or write as needed. Synchronized access to the concurrent - state is enforced at compile time through strongly typed accessor classes. - This interface design facilitates source code pattern matching to find all - areas where a concurrent state is accessed. - - There are three types of access: - - - ReadAccess - - Allows read access to the underlying object as `const`. ReadAccess may - be granted to one or more threads simultaneously. If one or more - threads have ReadAccess, requests to obtain WriteAccess are blocked. - - - WriteAccess - - Allows exclusive read/write access the underlying object. A WriteAccess - request blocks until all existing ReadAccess and WriteAccess requests - are released. While a WriteAccess exists, requests for ReadAccess - will block. - - - UnlockedAccess - - Allows read access to the underlying object without using the lock. - This can be helpful when designing concurrent structures through - composition. It also makes it easier to search for places in code - which use unlocked access. - - This code example demonstrates various forms of access to a SharedData: - - @code - - struct SharedData - { - int value1; - String value2; - }; - - typedef SharedData SharedState; - - SharedState sharedState; - - void readExample () - { - SharedState::ReadAccess state (sharedState); - - print (state->value1); // read access - print (state->value2); // read access - - state->value1 = 42; // write disallowed: compile error - } - - void writeExample () - { - SharedState::WriteAccess state (sharedState); - - state->value2 = "Label"; // write access - } - - @endcode - - Forwarding constructors with up to eight parameters are provided. This lets - you write constructors into the underlying data object. For example: - - @code - - struct SharedData - { - explicit SharedData (int numSlots) - { - m_array.reserve (numSlots); - } - - std::vector m_array; - }; - - // Construct SharedData with one parameter - SharedData sharedState (16); - - @endcode - - @param Object The type of object to encapsulate. - - @warning Recursive calls are not supported. It is generally not possible for - a thread of execution to acquire write access while it already has - read access. Such an attempt will result in undefined behavior. - Calling into unknown code while holding a lock can cause deadlock. - See @ref CallQueue::queue(). -*/ -template -class SharedData : public Uncopyable -{ -public: - class ReadAccess; - class WriteAccess; - class UnlockedAccess; - - /** Create a concurrent state. - - Up to 8 parameters can be specified in the constructor. These parameters - are forwarded to the corresponding constructor in Object. If no - constructor in Object matches the parameter list, a compile error is - generated. - */ - /** @{ */ - SharedData () { } - - template - explicit SharedData (T1 t1) - : m_obj (t1) { } - - template - SharedData (T1 t1, T2 t2) - : m_obj (t1, t2) { } - - template - SharedData (T1 t1, T2 t2, T3 t3) - : m_obj (t1, t2, t3) { } - - template - SharedData (T1 t1, T2 t2, T3 t3, T4 t4) - : m_obj (t1, t2, t3, t4) { } - - template - SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) - : m_obj (t1, t2, t3, t4, t5) { } - - template - SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) - : m_obj (t1, t2, t3, t4, t5, t6) { } - - template - SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : m_obj (t1, t2, t3, t4, t5, t6, t7) { } - - template - SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) - : m_obj (t1, t2, t3, t4, t5, t6, t7, t8) { } - /** @} */ - -private: - typedef ReadWriteMutex ReadWriteMutexType; - - Object m_obj; - ReadWriteMutexType m_mutex; -}; - -//------------------------------------------------------------------------------ - -/** Unlocked access to a SharedData. - - Use sparingly. -*/ -template -class SharedData ::UnlockedAccess : public Uncopyable -{ -public: - explicit UnlockedAccess (SharedData const& state) - : m_state (state) - { - } - - Object const& getObject () const - { - return m_state.m_obj; - } - Object const& operator* () const - { - return getObject (); - } - Object const* operator-> () const - { - return &getObject (); - } - -private: - SharedData const& m_state; -}; - -//------------------------------------------------------------------------------ - -/** Read only access to a SharedData */ -template -class SharedData ::ReadAccess : public Uncopyable -{ -public: - /** Create a ReadAccess from the specified SharedData */ - explicit ReadAccess (SharedData const volatile& state) - : m_state (const_cast (state)) - , m_lock (m_state.m_mutex) - { - } - - /** Obtain a read only reference to Object */ - Object const& getObject () const - { - return m_state.m_obj; - } - - /** Obtain a read only reference to Object */ - Object const& operator* () const - { - return getObject (); - } - - /** Obtain a read only smart pointer to Object */ - Object const* operator-> () const - { - return &getObject (); - } - -private: - SharedData const& m_state; - ReadWriteMutexType::ScopedReadLockType m_lock; -}; - -//------------------------------------------------------------------------------ - -/** Read/write access to a SharedData */ -template -class SharedData ::WriteAccess : public Uncopyable -{ -public: - explicit WriteAccess (SharedData& state) - : m_state (state) - , m_lock (m_state.m_mutex) - { - } - - /** Obtain a read only reference to Object */ - Object const* getObject () const - { - return m_state.m_obj; - } - - /** Obtain a read only reference to Object */ - Object const& operator* () const - { - return getObject (); - } - - /** Obtain a read only smart pointer to Object */ - Object const* operator-> () const - { - return &getObject (); - } - - /** Obtain a read/write pointer to Object */ - Object& getObject () - { - return m_state.m_obj; - } - - /** Obtain a read/write reference to Object */ - Object& operator* () - { - return getObject (); - } - - /** Obtain a read/write smart pointer to Object */ - Object* operator-> () - { - return &getObject (); - } - -private: - SharedData& m_state; - ReadWriteMutexType::ScopedWriteLockType m_lock; -}; - -#endif diff --git a/modules/beast_core/threads/Thread.h b/modules/beast_core/threads/Thread.h index c1e7de8743..8aa85024c0 100644 --- a/modules/beast_core/threads/Thread.h +++ b/modules/beast_core/threads/Thread.h @@ -21,8 +21,8 @@ */ //============================================================================== -#ifndef BEAST_THREAD_H_INCLUDED -#define BEAST_THREAD_H_INCLUDED +#ifndef BEAST_JUCE_THREAD_H_INCLUDED +#define BEAST_JUCE_THREAD_H_INCLUDED //============================================================================== /** diff --git a/modules/beast_db/keyvalue/KeyvaDB.cpp b/modules/beast_db/keyvalue/KeyvaDB.cpp index 3ef2e1b825..e53ef99732 100644 --- a/modules/beast_db/keyvalue/KeyvaDB.cpp +++ b/modules/beast_db/keyvalue/KeyvaDB.cpp @@ -255,7 +255,7 @@ public: , m_keyBlockDepth (keyBlockDepth) , m_keyStorage (keyBytes) { - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); openFile (&state->keyFile, keyPath); @@ -289,7 +289,7 @@ public: ~KeyvaDBImp () { - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); flushInternal (state); } @@ -310,7 +310,7 @@ public: //-------------------------------------------------------------------------- - Result createMasterRecord (SharedState::WriteAccess& state) + Result createMasterRecord (SharedState::Access& state) { MemoryBlock buffer (masterHeaderBytes, true); @@ -344,7 +344,7 @@ public: // void readKeyRecord (KeyRecord* const keyRecord, KeyIndex const keyIndex, - SharedState::WriteAccess& state) + SharedState::Access& state) { FileOffset const byteOffset = calcKeyRecordOffset (keyIndex); @@ -391,7 +391,7 @@ public: // Write a key record from memory void writeKeyRecord (KeyRecord const& keyRecord, KeyIndex const keyIndex, - SharedState::WriteAccess& state, + SharedState::Access& state, bool includingKey) { FileOffset const byteOffset = calcKeyRecordOffset (keyIndex); @@ -442,7 +442,7 @@ public: // Append a value to the value file. // VFALCO TODO return a Result - void writeValue (void const* const value, ByteSize valueBytes, SharedState::WriteAccess& state) + void writeValue (void const* const value, ByteSize valueBytes, SharedState::Access& state) { Result result = state->valFile.setPosition (state->valFileSize); @@ -493,7 +493,7 @@ public: // // Returns true if the key was found. // - bool find (FindResult* findResult, void const* key, SharedState::WriteAccess& state) + bool find (FindResult* findResult, void const* key, SharedState::Access& state) { // Not okay to call this with an empty key file! bassert (state->hasKeys ()); @@ -546,7 +546,7 @@ public: { FindResult findResult (m_keyStorage.getData ()); - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); bool found = false; @@ -594,7 +594,7 @@ public: { bassert (valueBytes > 0); - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); if (state->hasKeys ()) { @@ -681,12 +681,12 @@ public: void flush () { - SharedState::WriteAccess state (m_state); + SharedState::Access state (m_state); flushInternal (state); } - void flushInternal (SharedState::WriteAccess& state) + void flushInternal (SharedState::Access& state) { state->keyFile.flush (); state->valFile.flush ();