Squashed 'src/beast/' content from commit 43e6d34

git-subtree-dir: src/beast
git-subtree-split: 43e6d345e4
This commit is contained in:
Vinnie Falco
2013-09-11 09:57:14 -07:00
commit 86ba8ffca6
487 changed files with 263286 additions and 0 deletions

View File

@@ -0,0 +1,561 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
namespace detail
{
// Example:
//
// m_mutex[2] @ beast_deadlineTimer.cpp(25)
//
String detail::TrackedMutexBasics::createName (String name,
char const* fileName, int lineNumber, int instanceNumber)
{
return name +
((instanceNumber > 1) ?
(String ("[") + String::fromNumber (instanceNumber) + "] (") : " (") +
Debug::getFileNameFromPath (fileName) + "," +
String::fromNumber (lineNumber) + ")";
}
Atomic <int> TrackedMutexBasics::lastThreadId;
ThreadLocalValue <TrackedMutexBasics::PerThreadDataStorage> TrackedMutexBasics::threadLocal;
TrackedMutexBasics::PerThreadData::PerThreadData ()
: id (++lastThreadId)
{
}
TrackedMutexBasics::PerThreadData& TrackedMutexBasics::getPerThreadData ()
{
PerThreadData& thread (*reinterpret_cast <PerThreadData*>(&threadLocal.get ()));
// Manually call the constructor with placement new if needed
if (! thread.id)
{
::new (&thread) PerThreadData ();
bassert (thread.id != 0);
}
return thread;
}
CriticalSection& TrackedMutexBasics::getGlobalMutex ()
{
static CriticalSection mutex;
return mutex;
}
TrackedMutexBasics::Lists& TrackedMutexBasics::getLists ()
{
static Lists lists;
return lists;
}
//------------------------------------------------------------------------------
} // namespace detail
//==============================================================================
TrackedMutex::Record::Record (String mutexName,
String threadName, String sourceLocation)
: m_mutexName (mutexName)
, m_threadName (threadName)
, m_sourceLocation (sourceLocation)
{
}
TrackedMutex::Record::Record () noexcept
{
}
TrackedMutex::Record::Record (Record const& other) noexcept
: m_mutexName (other.m_mutexName)
, m_threadName (other.m_threadName)
, m_sourceLocation (other.m_sourceLocation)
{
}
TrackedMutex::Record& TrackedMutex::Record::operator= (Record const& other) noexcept
{
m_mutexName = other.m_mutexName;
m_threadName = other.m_threadName;
m_sourceLocation = other.m_sourceLocation;
return *this;
}
bool TrackedMutex::Record::isNull () const noexcept
{
return m_mutexName == "";
}
bool TrackedMutex::Record::isNotNull () const noexcept
{
return m_mutexName != "";
}
bool TrackedMutex::Record::asBoolean () const noexcept
{
return isNotNull ();
}
String TrackedMutex::Record::getMutexName () const noexcept
{
return m_mutexName;
}
String TrackedMutex::Record::getThreadName () const noexcept
{
return m_threadName;
}
String TrackedMutex::Record::getSourceLocation () const noexcept
{
return m_sourceLocation;
}
//------------------------------------------------------------------------------
TrackedMutex::Agent::Agent (detail::TrackedMutexBasics::PerThreadData* thread)
: m_thread (thread)
, m_threadName (thread->threadName)
{
}
TrackedMutex::Agent::Agent () noexcept
: m_thread (nullptr)
{
}
TrackedMutex::Agent::Agent (Agent const& other) noexcept
: m_thread (other.m_thread)
, m_threadName (other.m_threadName)
, m_blocked (other.m_blocked)
{
}
TrackedMutex::Agent& TrackedMutex::Agent::operator= (Agent const& other) noexcept
{
m_thread = other.m_thread;
m_threadName = other.m_threadName;
m_blocked = other.m_blocked;
return *this;
}
bool TrackedMutex::Agent::isNull () const noexcept
{
return m_thread == nullptr;
}
bool TrackedMutex::Agent::isNotNull () const noexcept
{
return m_thread != nullptr;
}
bool TrackedMutex::Agent::asBoolean () const noexcept
{
return isNotNull ();
}
String TrackedMutex::Agent::getThreadName () const noexcept
{
return m_threadName;
}
TrackedMutex::Record TrackedMutex::Agent::getBlockedRecord () const noexcept
{
return m_blocked;
}
bool TrackedMutex::Agent::getLockedList (Array <Record>& output)
{
bassert (isNotNull ());
output.clearQuick ();
typedef detail::TrackedMutexBasics::ThreadLockList ListType;
{
CriticalSection::ScopedLockType lock (m_thread->mutex);
ListType const& list (m_thread->list);
output.ensureStorageAllocated (list.size ());
for (ListType::const_iterator iter = list.begin ();
iter != list.end (); ++iter)
{
TrackedMutex const& mutex = *iter;
{
TrackedMutex::SharedState::ReadAccess state (mutex.m_state);
output.add (state->owner);
}
}
}
return output.size () > 0;
}
//------------------------------------------------------------------------------
TrackedMutex::State::State ()
: thread (nullptr)
{
}
//------------------------------------------------------------------------------
TrackedMutex::TrackedMutex (String const& name) noexcept
: m_name (name)
, m_count (0)
{
}
String TrackedMutex::getName () const noexcept
{
return m_name;
}
TrackedMutex::Record TrackedMutex::getOwnerRecord () const noexcept
{
{
SharedState::ReadAccess state (m_state);
return state->owner;
}
}
TrackedMutex::Agent TrackedMutex::getOwnerAgent () const noexcept
{
{
SharedState::ReadAccess state (m_state);
if (state->thread != nullptr)
return Agent (state->thread);
}
return Agent ();
}
//------------------------------------------------------------------------------
void TrackedMutex::generateGlobalBlockedReport (StringArray& report)
{
report.clear ();
{
CriticalSection::ScopedLockType lock (
detail::TrackedMutexBasics::getGlobalMutex ());
typedef detail::TrackedMutexBasics::GlobalThreadList ListType;
ListType const& list (detail::TrackedMutexBasics::getLists ().allThreads);
for (ListType::const_iterator iter = list.begin (); iter != list.end (); ++iter)
{
detail::TrackedMutexBasics::PerThreadData const* thread (
&(*iter));
typedef detail::TrackedMutexBasics::ThreadLockList LockedList;
LockedList const& owned (thread->list);
if (thread->blocked)
{
String s;
s << thread->threadName << " blocked on " <<
thread->blocked->getName () << " at " <<
thread->sourceLocation;
if (owned.size () > 0)
s << " and owns these locks:";
report.add (s);
}
else if (owned.size () > 0)
{
String s;
s << thread->threadName << " owns these locks:";
report.add (s);
}
if (owned.size () > 0)
{
for (LockedList::const_iterator iter = owned.begin (); iter != owned.end (); ++iter)
{
String s;
TrackedMutex const& mutex (*iter);
TrackedMutex::SharedState::ReadAccess state (mutex.m_state);
s << " " << mutex.getName () <<
" from " << state->owner.getSourceLocation ();
report.add (s);
}
}
}
}
}
//------------------------------------------------------------------------------
// Called before we attempt to acquire the mutex.
//
void TrackedMutex::block (char const* fileName, int lineNumber) const noexcept
{
// Get calling thread data.
detail::TrackedMutexBasics::PerThreadData& thread
(detail::TrackedMutexBasics::getPerThreadData ());
++thread.refCount;
String const sourceLocation (makeSourceLocation (fileName, lineNumber));
{
// Take a global lock.
CriticalSection::ScopedLockType globalLock (
detail::TrackedMutexBasics::getGlobalMutex ());
{
// Take a thread lock.
CriticalSection::ScopedLockType threadLock (thread.mutex);
// Set the thread's blocked record
thread.blocked = this;
thread.threadName = makeThreadName (thread);
thread.sourceLocation = sourceLocation;
// Add this thread to threads list.
if (thread.refCount == 1)
detail::TrackedMutexBasics::getLists().allThreads.push_back (thread);
}
}
}
//------------------------------------------------------------------------------
// Called after we already have ownership of the mutex
//
void TrackedMutex::acquired (char const* fileName, int lineNumber) const noexcept
{
// Retrieve the per-thread data for the calling thread.
detail::TrackedMutexBasics::PerThreadData& thread
(detail::TrackedMutexBasics::getPerThreadData ());
// If this goes off it means block() wasn't called.
bassert (thread.refCount > 0);
++m_count;
// Take ownership on the first count.
if (m_count == 1)
{
// Thread is a new owner of the mutex.
String const sourceLocation (makeSourceLocation (fileName, lineNumber));
String const threadName (makeThreadName (thread));
{
// Take a global lock.
CriticalSection::ScopedLockType globalLock (
detail::TrackedMutexBasics::getGlobalMutex ());
{
// Take a state lock.
SharedState::WriteAccess state (m_state);
// Set the mutex ownership record
state->owner = Record (getName (), threadName, sourceLocation);
state->thread = &thread;
{
// Take a thread lock.
CriticalSection::ScopedLockType threadLock (thread.mutex);
// Add the mutex to the thread's list.
thread.list.push_back (const_cast <TrackedMutex&>(*this));
// Unblock the thread record.
thread.blocked = nullptr;
thread.sourceLocation = "";
}
}
}
}
else
{
// Thread already had ownership of the mutex.
bassert (SharedState::UnlockedAccess (m_state)->thread == &thread);
// If this goes off it means we counted wrong.
bassert (thread.refCount >= m_count);
}
}
//------------------------------------------------------------------------------
void TrackedMutex::release () const noexcept
{
// If this goes off it means we don't own the mutex!
bassert (m_count > 0);
// Retrieve the per-thread data for the calling thread.
detail::TrackedMutexBasics::PerThreadData& thread
(detail::TrackedMutexBasics::getPerThreadData ());
// If this goes off it means we counted wrong.
bassert (thread.refCount >= m_count);
--m_count;
--thread.refCount;
// Give up ownership when the count drops to zero.
if (m_count == 0)
{
// Take the global mutex
CriticalSection::ScopedLockType globalLock (
detail::TrackedMutexBasics::getGlobalMutex ());
{
// Take the mutex' state lock
SharedState::WriteAccess state (m_state);
// Clear the mutex ownership record
state->owner = Record ();
state->thread = nullptr;
{
// Take the thread mutex
CriticalSection::ScopedLockType threadLock (thread.mutex);
// Remove this mutex from the list of the thread's owned locks.
thread.list.erase (thread.list.iterator_to (
const_cast <TrackedMutex&>(*this)));
// Remove this thread from the threads list.
if (thread.refCount == 0)
{
typedef detail::TrackedMutexBasics::GlobalThreadList ListType;
ListType& list (detail::TrackedMutexBasics::getLists().allThreads);
list.erase (list.iterator_to (thread));
}
}
}
}
}
//------------------------------------------------------------------------------
String TrackedMutex::makeThreadName (
detail::TrackedMutexBasics::PerThreadData const& thread) noexcept
{
String threadName;
Thread const* const currentThread (Thread::getCurrentThread ());
if (currentThread != nullptr)
threadName = currentThread->getThreadName ();
threadName = threadName + "[" + String::fromNumber (thread.id) + "]";
return threadName;
}
String TrackedMutex::makeSourceLocation (char const* fileName, int lineNumber) noexcept
{
String const sourceLocation (Debug::getFileNameFromPath (fileName, 1) + "(" +
String::fromNumber (lineNumber) + ")");
return sourceLocation;
}
//==============================================================================
namespace detail
{
class TrackedMutexUnitTests : public UnitTest
{
public:
typedef TrackedMutexType <CriticalSection> Mutex;
struct LockingThread : public Thread
{
Mutex& m_m1;
Mutex& m_m2;
WaitableEvent m_start;
explicit LockingThread (String name, Mutex& m1, Mutex& m2)
: Thread (name)
, m_m1 (m1)
, m_m2 (m2)
{
startThread ();
}
void waitForStart ()
{
m_start.wait ();
}
void run ()
{
Mutex::ScopedLockType l2 (m_m2, __FILE__, __LINE__);
{
Mutex::ScopedLockType l1 (m_m1, __FILE__, __LINE__);
m_start.signal ();
{
Mutex::ScopedUnlockType ul1 (m_m1, __FILE__, __LINE__);
this->wait ();
}
}
}
};
//--------------------------------------------------------------------------
void report (String name)
{
beginTestCase (name);
StringArray report;
TrackedMutex::generateGlobalBlockedReport (report);
logReport (report);
pass ();
}
void runTest ()
{
Mutex m1 ("M1", __FILE__, __LINE__);
Mutex m2 ("M2", __FILE__, __LINE__);
{
Mutex::ScopedLockType l1 (m1, __FILE__, __LINE__);
LockingThread t1 ("T1", m1, m2);
{
Mutex::ScopedUnlockType ul1 (m1, __FILE__, __LINE__);
t1.waitForStart ();
}
report ("#1");
{
t1.notify ();
Mutex::ScopedUnlockType ul1 (m1, __FILE__, __LINE__);
t1.waitForThreadToExit ();
}
}
}
TrackedMutexUnitTests () : UnitTest ("TrackedMutex", "beast", runManual)
{
}
};
static TrackedMutexUnitTests trackedMutexUnitTests;
} // namespace detail

View File

@@ -0,0 +1,168 @@
//------------------------------------------------------------------------------
/*
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_CORE_THREAD_IMPL_TRACKEDMUTEX_H_INCLUDED
#define BEAST_CORE_THREAD_IMPL_TRACKEDMUTEX_H_INCLUDED
/** Common types and member functions for a TrackedMutex */
class TrackedMutex
: public detail::TrackedMutexBasics::ThreadLockList::Node
{
public:
class Agent;
class Location;
//--------------------------------------------------------------------------
/** A triplet identifying a mutex, a thread, and source code location.
*/
class Record : public SafeBool <Record>
{
public:
Record () noexcept;
Record (Record const& other) noexcept;
Record& operator= (Record const& other) noexcept;
bool isNull () const noexcept;
bool isNotNull () const noexcept;
bool asBoolean () const noexcept;
/** Returns the name of the mutex.
Since the Mutex may not exist after the Record record is
created, we only provide a String, which is always valid.
*/
String getMutexName () const noexcept;
/** Returns the name of the associated thread.
The name is generated at the time the record is created,
and might have changed since that time, or may no longer exist.
*/
String getThreadName () const noexcept;
/** Returns the position within the source code.
This will either be the place a lock was acquired, or the place
where a thread is trying to acquire a lock. The vaue is only
meaningful at the time the Record is created. Since then, the
thread may have changed its state.
*/
String getSourceLocation () const noexcept;
private:
friend class TrackedMutex;
Record (String mutexName, String threadName, String sourceLocation);
String m_mutexName;
String m_threadName;
String m_sourceLocation;
};
//--------------------------------------------------------------------------
/** Describes a thread that can acquire mutexes. */
class Agent : public SafeBool <Agent>
{
public:
Agent () noexcept;
Agent (Agent const& other) noexcept;
Agent& operator= (Agent const& other) noexcept;
bool isNull () const noexcept;
bool isNotNull () const noexcept;
bool asBoolean () const noexcept;
/** Returns the name of the thread.
The name is generated at the time the Agent record is created,
and might have changed since that time.
*/
String getThreadName () const noexcept;
/** Returns a Record indicating where the thread is blocked on a mutex.
If the thread is not blocked, a null Record is returned.
The value is only meaningful at the moment of the call as conditions
can change.
*/
Record getBlockedRecord () const noexcept;
/** Retrieve a list of other locks that this thread holds.
Each lock is represented by a Location indicating the place
The value is only meaningful at the moment of the call as conditions
can change.
@return `true` if the list is not empty.
*/
bool getLockedList (Array <Record>& list);
private:
friend class TrackedMutex;
explicit Agent (detail::TrackedMutexBasics::PerThreadData* thread);
detail::TrackedMutexBasics::PerThreadData* m_thread;
String m_threadName;
Record m_blocked;
};
//--------------------------------------------------------------------------
/** Retrieve the name of this mutex.
Thread safety: May be called from any thread.
*/
String getName () const noexcept;
/** Retrieve a Record for the current owner.
It is only valid at the one instant in time, as the person holding it
might have released it shortly afterwards. If there is no owner,
a null Record is returned.
*/
Record getOwnerRecord () const noexcept;
/** Retrieve the Agent for the current owner.
It is only valid at the one instant in time, as the person holding it
might have released it shortly afterwards. If there is no owner,
a null Agent is returned.
*/
Agent getOwnerAgent () const noexcept;
/** Produce a report on the state of all blocked threads. */
static void generateGlobalBlockedReport (StringArray& report);
protected:
static String makeThreadName (detail::TrackedMutexBasics::PerThreadData const&) noexcept;
static String makeSourceLocation (char const* fileName, int lineNumber) noexcept;
TrackedMutex (String const& name) noexcept;
void block (char const* fileName, int lineNumber) const noexcept;
void acquired (char const* fileName, int lineNumber) const noexcept;
void release () const noexcept;
private:
struct State
{
State ();
Record owner;
detail::TrackedMutexBasics::PerThreadData* thread;
};
typedef SharedData <State> SharedState;
String const m_name;
int mutable m_count;
SharedState mutable m_state;
};
#endif

View File

@@ -0,0 +1,95 @@
//------------------------------------------------------------------------------
/*
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_CORE_THREAD_TRACKEDMUTEXTYPE_H_INCLUDED
#define BEAST_CORE_THREAD_TRACKEDMUTEXTYPE_H_INCLUDED
/** A template that gives a Mutex diagnostic tracking capabilities. */
template <typename Mutex>
class TrackedMutexType
: public TrackedMutex
{
public:
/** The type of ScopedLock to use with this TrackedMutexType object. */
typedef detail::TrackedScopedLock <TrackedMutexType <Mutex> > ScopedLockType;
/** The type of ScopedTrylock to use with this TrackedMutexType object. */
typedef detail::TrackedScopedTryLock <TrackedMutexType <Mutex> > ScopedTryLockType;
/** The type of ScopedUnlock to use with this TrackedMutexType object. */
typedef detail::TrackedScopedUnlock <TrackedMutexType <Mutex> > ScopedUnlockType;
/** Construct a mutex, keyed to a particular class.
Just pass 'this' for owner and give it the name of the data member
of your class.
*/
template <typename Object>
TrackedMutexType (Object const* object,
String name,
char const* fileName,
int lineNumber)
: TrackedMutex (detail::TrackedMutexBasics::createName <Object> (
name, fileName, lineNumber))
{
}
/** Construct a mutex, without a class association.
These will all get numbered together as a group.
*/
TrackedMutexType (String name, char const* fileName, int lineNumber)
: TrackedMutex (detail::TrackedMutexBasics::createName (name,
fileName, lineNumber))
{
}
~TrackedMutexType () noexcept
{
}
inline void lock (char const* fileName, int lineNumber) const noexcept
{
block (fileName, lineNumber);
MutexTraits <Mutex>::lock (m_mutex);
acquired (fileName, lineNumber);
}
inline void unlock () const noexcept
{
release ();
MutexTraits <Mutex>::unlock (m_mutex);
}
// VFALCO NOTE: We could use enable_if here...
inline bool try_lock (char const* fileName, int lineNumber) const noexcept
{
bool const success = MutexTraits <Mutex>::try_lock (m_mutex);
if (success)
{
// Hack, call block to prevent counts from going wrong.
block (fileName, lineNumber);
acquired (fileName, lineNumber);
}
return success;
}
private:
Mutex const m_mutex;
};
#endif

View File

@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
/*
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_CORE_THREAD_IMPL_UNTRACKEDMUTEX_H_INCLUDED
#define BEAST_CORE_THREAD_IMPL_UNTRACKEDMUTEX_H_INCLUDED
/** A drop-in replacement for TrackedMutex without the tracking.
*/
template <typename Mutex>
class UntrackedMutexType
: public Uncopyable
{
public:
typedef detail::UntrackedScopedLock <UntrackedMutexType <Mutex> > ScopedLockType;
typedef detail::UntrackedScopedTryLock <UntrackedMutexType <Mutex> > ScopedTryLockType;
typedef detail::UntrackedScopedUnlock <UntrackedMutexType <Mutex> > ScopedUnlockType;
template <typename Object>
inline UntrackedMutexType (Object const*, String name, char const*, int) noexcept
{
}
inline UntrackedMutexType (String, char const*, int) noexcept
{
}
inline UntrackedMutexType () noexcept
{
}
inline ~UntrackedMutexType () noexcept
{
}
inline void lock () const noexcept
{
MutexTraits <Mutex>::lock (m_mutex);
}
inline void lock (char const*, int) const noexcept
{
MutexTraits <Mutex>::lock (m_mutex);
}
inline void unlock () const noexcept
{
MutexTraits <Mutex>::unlock (m_mutex);
}
// VFALCO NOTE: We could use enable_if here...
inline bool try_lock () const noexcept
{
return MutexTraits <Mutex>::try_lock (m_mutex);
}
inline bool try_lock (char const*, int) const noexcept
{
return MutexTraits <Mutex>::try_lock (m_mutex);
}
private:
Mutex mutable m_mutex;
};
#endif