Init
This commit is contained in:
435
DependentExtensions/cat/threads/Atomic.hpp
Normal file
435
DependentExtensions/cat/threads/Atomic.hpp
Normal file
@ -0,0 +1,435 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschr<68>nkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
* Alternatively you are permitted to license the modifications under the Modified BSD License.
|
||||
*/
|
||||
|
||||
#ifndef CAT_ATOMIC_HPP
|
||||
#define CAT_ATOMIC_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
namespace Atomic {
|
||||
|
||||
|
||||
// Compare-and-Swap 2x word size (CAS2)
|
||||
// On 32-bit architectures, the arguments point to 64-bit values, and must be aligned to 8 byte boundary
|
||||
// On 64-bit architectures, the arguments point to 128-bit values, and must be aligned to 16 byte boundary
|
||||
// Returns true if the old value was equal to the expected value
|
||||
CAT_INLINE bool CAS2(volatile void *x, const void *expected_old_value, const void *new_value);
|
||||
// Will define CAT_NO_ATOMIC_CAS2 if the platform/compiler does not support atomic CAS2
|
||||
|
||||
// Add y to x, returning the previous state of x
|
||||
CAT_INLINE u32 Add(volatile u32 *x, s32 y);
|
||||
// Will define CAT_NO_ATOMIC_ADD if the platform/compiler does not support atomic add
|
||||
|
||||
// Set x to new value, returning the previous state of x
|
||||
CAT_INLINE u32 Set(volatile u32 *x, u32 new_value);
|
||||
// Will define CAT_NO_ATOMIC_SET if the platform/compiler does not support atomic set
|
||||
|
||||
// Bit Test and Set (BTS)
|
||||
// Returns true if the bit was 1 and is still 1, otherwise false
|
||||
CAT_INLINE bool BTS(volatile u32 *x, int bit);
|
||||
// Will define CAT_NO_ATOMIC_BTS if the platform/compiler does not support atomic bts
|
||||
|
||||
// Bit Test and Reset (BTR)
|
||||
// Returns true if the bit was 1 and is now 0, otherwise false
|
||||
CAT_INLINE bool BTR(volatile u32 *x, int bit);
|
||||
// Will define CAT_NO_ATOMIC_BTR if the platform/compiler does not support atomic btr
|
||||
|
||||
|
||||
} // namespace Atomic
|
||||
|
||||
|
||||
//// Compare-and-Swap
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
|
||||
|
||||
bool Atomic::CAS2(volatile void *x, const void *expected_old_value, const void *new_value)
|
||||
{
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC) && (_MSC_VER > 1400) // MSVC 2008+
|
||||
|
||||
__int64 ComparandResult[2] = { ((u64*)expected_old_value)[0],
|
||||
((u64*)expected_old_value)[1] };
|
||||
|
||||
// Requires MSVC 2008 or newer
|
||||
bool success = 1 == _InterlockedCompareExchange128((s64*)x, ((u64*)new_value)[1],
|
||||
((u64*)new_value)[0], ComparandResult);
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return success;
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u128 *target = (u128*)x;
|
||||
u64 *replace = (u64*)new_value;
|
||||
u128 *expected = (u128*)expected_old_value;
|
||||
bool retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"lock; CMPXCHG16B %0\n\t"
|
||||
"sete %%al"
|
||||
: "=m" (*target), "=a" (retval)
|
||||
: "m" (*target), "b" (replace[0]), "c" (replace[1]), "A" (*expected)
|
||||
: "memory", "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
#define CAT_NO_ATOMIC_CAS2 /* Platform/compiler does not support CAS2 */
|
||||
|
||||
(void) x; // avoid unused parameter warning
|
||||
(void) expected_old_value;
|
||||
(void) new_value;
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#else // 32-bit version:
|
||||
|
||||
|
||||
bool Atomic::CAS2(volatile void *x, const void *expected_old_value, const void *new_value)
|
||||
{
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
s64 old_value = ((s64*)expected_old_value)[0];
|
||||
|
||||
bool success = (old_value == _InterlockedCompareExchange64((s64*)x, ((s64*)new_value)[0], old_value));
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return success;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
push ebx
|
||||
mov eax, new_value
|
||||
push esi
|
||||
mov ebx, dword ptr[eax]
|
||||
mov ecx, dword ptr[eax+4]
|
||||
mov edx, expected_old_value
|
||||
mov esi, x
|
||||
mov eax, dword ptr[edx]
|
||||
mov edx, dword ptr[edx+4]
|
||||
lock CMPXCHG8B qword ptr[esi]
|
||||
pop ebx
|
||||
mov eax, 0
|
||||
pop esi
|
||||
setz al
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u64 *target = (u64*)x;
|
||||
u32 *replace = (u32*)new_value;
|
||||
u64 *expected = (u64*)expected_old_value;
|
||||
bool retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"lock; CMPXCHG8B %0\n\t"
|
||||
"sete %%al"
|
||||
: "=m" (*target), "=a" (retval)
|
||||
: "m" (*target), "b" (replace[0]), "c" (replace[1]), "A" (*expected)
|
||||
: "memory", "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
#define CAT_NO_ATOMIC_CAS2 /* Platform/compiler does not support atomic CAS2 */
|
||||
|
||||
(void) x; // avoid unused parameter warning
|
||||
(void) expected_old_value;
|
||||
(void) new_value;
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif // defined(CAT_WORD_64)
|
||||
|
||||
|
||||
//// Add y to x, returning the previous state of x
|
||||
|
||||
u32 Atomic::Add(volatile u32 *x, s32 y)
|
||||
{
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64)
|
||||
|
||||
u32 result = InterlockedAdd((volatile LONG*)x, y) - y;
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return result;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_WORD_32) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
mov edx,x
|
||||
mov eax,y
|
||||
lock XADD [edx],eax
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"lock; XADDl %%eax, %0\n\t"
|
||||
: "=m" (*x), "=a" (retval)
|
||||
: "m" (*x), "a" (y)
|
||||
: "memory", "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
#define CAT_NO_ATOMIC_ADD /* Platform/compiler does not support atomic add */
|
||||
|
||||
u32 old_x = *x;
|
||||
*x = old_x + y;
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return old_x;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//// Set x to new value, returning the previous state of x
|
||||
|
||||
u32 Atomic::Set(volatile u32 *x, u32 new_value)
|
||||
{
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
#if (_MSC_VER <= 1400) // MSVC 2005
|
||||
u32 result = _InterlockedExchange((long*)x, new_value);
|
||||
#else // MSVC 2008+
|
||||
u32 result = _InterlockedExchange((volatile LONG*)x, new_value);
|
||||
#endif
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return result;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_WORD_32) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
mov edx,x
|
||||
mov eax,new_value
|
||||
lock XCHG [edx],eax
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"lock; XCHGl %%eax, %0\n\t"
|
||||
: "=m" (*x), "=a" (retval)
|
||||
: "m" (*x), "a" (new_value)
|
||||
: "memory", "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
#define CAT_NO_ATOMIC_SET /* Platform/compiler does not support atomic set */
|
||||
|
||||
u32 old_x = *x;
|
||||
*x = new_value;
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return old_x;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//// Bit Test and Set (BTS)
|
||||
|
||||
bool Atomic::BTS(volatile u32 *x, int bit)
|
||||
{
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
#if (_MSC_VER <= 1400) // MSVC 2005
|
||||
bool success = !!_interlockedbittestandset((long*)x, bit);
|
||||
#else // MSVC 2008+
|
||||
bool success = !!_interlockedbittestandset((volatile LONG*)x, bit);
|
||||
#endif
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return success;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_WORD_32) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
mov edx,x
|
||||
mov ecx,bit
|
||||
lock BTS [edx],ecx
|
||||
mov eax,0
|
||||
setc al
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
bool retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"lock; BTSl %2, %0\n\t"
|
||||
"setc %%al"
|
||||
: "=m" (*x), "=a" (retval)
|
||||
: "Ir" (bit)
|
||||
: "memory", "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
#define CAT_NO_ATOMIC_BTS /* Platform/compiler does not support atomic bts */
|
||||
|
||||
u32 mask = 1 << bit;
|
||||
|
||||
u32 old_x = *x;
|
||||
*x = old_x | mask;
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return (old_x & mask) ? true : false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//// Bit Test and Reset (BTR)
|
||||
|
||||
bool Atomic::BTR(volatile u32 *x, int bit)
|
||||
{
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
#if (_MSC_VER <= 1400) // MSVC 2005
|
||||
bool success = !!_interlockedbittestandreset((long*)x, bit);
|
||||
#else // MSVC 2008+
|
||||
bool success = !!_interlockedbittestandreset((volatile LONG*)x, bit);
|
||||
#endif
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return success;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_WORD_32) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
mov edx,x
|
||||
mov ecx,bit
|
||||
lock BTR [edx],ecx
|
||||
mov eax,0
|
||||
setc al
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
bool retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"lock; BTRl %2, %0\n\t"
|
||||
"setc %%al"
|
||||
: "=m" (*x), "=a" (retval)
|
||||
: "Ir" (bit)
|
||||
: "memory", "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
#define CAT_NO_ATOMIC_BTR /* Platform/compiler does not support atomic btr */
|
||||
|
||||
u32 mask = 1 << bit;
|
||||
|
||||
u32 old_x = *x;
|
||||
*x = old_x & ~mask;
|
||||
|
||||
CAT_FENCE_COMPILER
|
||||
return (old_x & mask) ? true : false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_ATOMIC_HPP
|
||||
368
DependentExtensions/cat/threads/LocklessFIFO.hpp
Normal file
368
DependentExtensions/cat/threads/LocklessFIFO.hpp
Normal file
@ -0,0 +1,368 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Algorithm from "An Optimistic Approach to Lock-Free FIFO Queues"
|
||||
Edya Ladan-Mozes and Nir Shavit (2004)
|
||||
*/
|
||||
|
||||
#ifndef CAT_LOCKLESS_FIFO_HPP
|
||||
#define CAT_LOCKLESS_FIFO_HPP
|
||||
|
||||
#include <cat/threads/RegionAllocator.hpp>
|
||||
#include <cat/threads/Atomic.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#else
|
||||
# error "Not portable to your OS!"
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
namespace FIFO {
|
||||
|
||||
template<class T> class Ptr;
|
||||
template<class T> class Node;
|
||||
template<class T> class Queue;
|
||||
|
||||
|
||||
//// Ptr
|
||||
|
||||
// Union for an ABA-proof pointer
|
||||
template<class T>
|
||||
class Ptr
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
Node<T> *ptr;
|
||||
#if defined(CAT_WORD_64)
|
||||
u64 tag;
|
||||
#else
|
||||
u32 tag;
|
||||
#endif
|
||||
};
|
||||
#if defined(CAT_WORD_64)
|
||||
volatile u64 N[2];
|
||||
#else
|
||||
volatile u64 N;
|
||||
#endif
|
||||
} CAT_PACKED;
|
||||
|
||||
Ptr(); // zero everything
|
||||
|
||||
bool operator==(const Ptr<T> &rhs);
|
||||
bool operator!=(const Ptr<T> &rhs);
|
||||
};
|
||||
|
||||
|
||||
//// Derive from Data<T> for data passed through the queue
|
||||
|
||||
template<class T>
|
||||
class Node
|
||||
{
|
||||
friend class Queue<T>;
|
||||
|
||||
T *value;
|
||||
Ptr<T> next, prev;
|
||||
};
|
||||
|
||||
|
||||
//// Queue
|
||||
|
||||
// Performs lazy deallocation of data objects on behalf of the caller,
|
||||
// freeing all remaining objects when the Queue goes out of scope.
|
||||
template<class T>
|
||||
class Queue
|
||||
{
|
||||
// Pointer to head and tail
|
||||
Ptr<T> Head, Tail;
|
||||
|
||||
// Event to wait on if dequeuing
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
HANDLE hEvent;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Queue();
|
||||
~Queue();
|
||||
|
||||
public:
|
||||
void Enqueue(T *data);
|
||||
T *Dequeue();
|
||||
void FixList(Ptr<T> tail, Ptr<T> head);
|
||||
|
||||
// Enqueue a new event to wake up a thread stuck here
|
||||
T *DequeueWait();
|
||||
};
|
||||
|
||||
|
||||
//// Compare-and-Swap x2 (CAS2) atomic operation
|
||||
|
||||
template<class T>
|
||||
inline bool CAS2(Ptr<T> &destination, const Ptr<T> &expected, const Ptr<T> &replacement)
|
||||
{
|
||||
return Atomic::CAS2(&destination, &expected, &replacement);
|
||||
}
|
||||
|
||||
|
||||
//// Ptr: Templated member implementation
|
||||
|
||||
template<class T>
|
||||
Ptr<T>::Ptr()
|
||||
{
|
||||
#if defined(CAT_WORD_64)
|
||||
N[0] = 0;
|
||||
N[1] = 0;
|
||||
#else
|
||||
N = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool Ptr<T>::operator==(const Ptr<T> &n)
|
||||
{
|
||||
#if defined(CAT_WORD_64)
|
||||
return N[0] == n.N[0] && N[1] == n.N[1];
|
||||
#else
|
||||
return N == n.N;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool Ptr<T>::operator!=(const Ptr<T> &n)
|
||||
{
|
||||
#if defined(CAT_WORD_64)
|
||||
return N[0] != n.N[0] || N[1] != n.N[1];
|
||||
#else
|
||||
return N != n.N;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//// Queue: Templated member implementation
|
||||
|
||||
template<class T>
|
||||
Queue<T>::Queue()
|
||||
{
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
#endif
|
||||
|
||||
Node<T> *node = new (RegionAllocator::ii) Node<T>;
|
||||
node->value = 0;
|
||||
|
||||
Head.ptr = Tail.ptr = node;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Queue<T>::~Queue()
|
||||
{
|
||||
// Destroy objects that are still queued
|
||||
for (Node<T> *next, *ptr = Head.ptr; ptr; ptr = next)
|
||||
{
|
||||
next = ptr->next.ptr;
|
||||
|
||||
if (ptr->value)
|
||||
RegionAllocator::ii->Delete(ptr->value);
|
||||
RegionAllocator::ii->Delete(ptr);
|
||||
}
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
CloseHandle(hEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Queue<T>::Enqueue(T *val)
|
||||
{
|
||||
Ptr<T> tail;
|
||||
Node<T> *nd = new (RegionAllocator::ii) Node<T>;
|
||||
nd->value = val;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
tail = Tail;
|
||||
nd->next.ptr = tail.ptr;
|
||||
nd->next.tag = tail.tag + 1;
|
||||
|
||||
Ptr<T> new_tail;
|
||||
new_tail.ptr = nd;
|
||||
new_tail.tag = tail.tag + 1;
|
||||
|
||||
if (CAS2(Tail, tail, new_tail))
|
||||
{
|
||||
tail.ptr->prev.ptr = nd;
|
||||
tail.ptr->prev.tag = tail.tag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
SetEvent(hEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T *Queue<T>::DequeueWait()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Attempt to dequeue a message
|
||||
// If we won the race to service the message, then return it
|
||||
T *retval = Dequeue();
|
||||
if (retval) return retval;
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
// If the sychronization wait fails (handle closed), abort with 0
|
||||
if (WaitForSingleObject(hEvent, INFINITE) != WAIT_OBJECT_0)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T *Queue<T>::Dequeue()
|
||||
{
|
||||
Ptr<T> tail, head, firstNodePrev;
|
||||
Node<T> *nd_dummy;
|
||||
T *val;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
head = Head;
|
||||
tail = Tail;
|
||||
firstNodePrev = head.ptr->prev;
|
||||
val = head.ptr->value;
|
||||
|
||||
if (head == Head)
|
||||
{
|
||||
if (val != 0)
|
||||
{
|
||||
if (tail != head)
|
||||
{
|
||||
if (firstNodePrev.tag != head.tag)
|
||||
{
|
||||
FixList(tail, head);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nd_dummy = new (RegionAllocator::ii) Node<T>;
|
||||
nd_dummy->value = 0;
|
||||
nd_dummy->next.ptr = tail.ptr;
|
||||
nd_dummy->next.tag = tail.tag + 1;
|
||||
|
||||
Ptr<T> new_tail;
|
||||
new_tail.ptr = nd_dummy;
|
||||
new_tail.tag = tail.tag + 1;
|
||||
|
||||
if (CAS2(Tail, tail, new_tail))
|
||||
{
|
||||
head.ptr->prev.ptr = nd_dummy;
|
||||
head.ptr->prev.tag = tail.tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
RegionAllocator::ii->Delete(nd_dummy);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Ptr<T> new_head;
|
||||
new_head.ptr = firstNodePrev.ptr;
|
||||
new_head.tag = head.tag + 1;
|
||||
|
||||
if (CAS2(Head, head, new_head))
|
||||
{
|
||||
RegionAllocator::ii->Delete(head.ptr);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tail.ptr == head.ptr)
|
||||
return 0;
|
||||
|
||||
if (firstNodePrev.tag != head.tag)
|
||||
{
|
||||
FixList(tail, head);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Ptr<T> new_head;
|
||||
new_head.ptr = firstNodePrev.ptr;
|
||||
new_head.tag = head.tag + 1;
|
||||
|
||||
CAS2(Head, head, new_head);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Queue<T>::FixList(Ptr<T> tail, Ptr<T> head)
|
||||
{
|
||||
Ptr<T> curNode, curNodeNext, nextNodePrev;
|
||||
|
||||
curNode = tail;
|
||||
|
||||
while (head == Head && curNode != head)
|
||||
{
|
||||
curNodeNext = curNode.ptr->next;
|
||||
|
||||
if (curNodeNext.tag != curNode.tag)
|
||||
return;
|
||||
|
||||
nextNodePrev = curNodeNext.ptr->prev;
|
||||
|
||||
if (nextNodePrev.ptr != curNode.ptr || nextNodePrev.tag != curNode.tag - 1)
|
||||
{
|
||||
curNodeNext.ptr->prev.ptr = curNode.ptr;
|
||||
curNodeNext.ptr->prev.tag = curNode.tag - 1;
|
||||
}
|
||||
|
||||
curNode.ptr = curNodeNext.ptr;
|
||||
curNode.tag = curNode.tag - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace FIFO
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_LOCKLESS_FIFO_HPP
|
||||
78
DependentExtensions/cat/threads/Mutex.hpp
Normal file
78
DependentExtensions/cat/threads/Mutex.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_MUTEX_HPP
|
||||
#define CAT_MUTEX_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#else // use POSIX mutex library otherwise
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Implements a mutex that is NOT reentrant (for speed)
|
||||
class Mutex
|
||||
{
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
CRITICAL_SECTION cs;
|
||||
#else
|
||||
int init_failure;
|
||||
pthread_mutex_t mx;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
bool Valid();
|
||||
|
||||
bool Enter();
|
||||
bool Leave();
|
||||
};
|
||||
|
||||
|
||||
class AutoMutex
|
||||
{
|
||||
Mutex *_mutex;
|
||||
|
||||
public:
|
||||
AutoMutex(Mutex &mutex);
|
||||
~AutoMutex();
|
||||
|
||||
bool Release();
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_MUTEX_HPP
|
||||
93
DependentExtensions/cat/threads/RWLock.hpp
Normal file
93
DependentExtensions/cat/threads/RWLock.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_RW_LOCK_HPP
|
||||
#define CAT_RW_LOCK_HPP
|
||||
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// RWLock
|
||||
|
||||
class RWLock
|
||||
{
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
volatile u32 _rd_count;
|
||||
volatile u32 _wr_count;
|
||||
HANDLE _rd_event;
|
||||
Mutex _wr_lock;
|
||||
#else
|
||||
int init_failure;
|
||||
pthread_rwlock_t rw;
|
||||
#endif
|
||||
|
||||
public:
|
||||
RWLock();
|
||||
~RWLock();
|
||||
|
||||
void ReadLock();
|
||||
void ReadUnlock();
|
||||
|
||||
void WriteLock();
|
||||
void WriteUnlock();
|
||||
};
|
||||
|
||||
|
||||
//// AutoReadLock
|
||||
|
||||
class AutoReadLock
|
||||
{
|
||||
RWLock *_lock;
|
||||
|
||||
public:
|
||||
AutoReadLock(RWLock &lock);
|
||||
~AutoReadLock();
|
||||
|
||||
bool Release();
|
||||
};
|
||||
|
||||
|
||||
//// AutoWriteLock
|
||||
|
||||
class AutoWriteLock
|
||||
{
|
||||
RWLock *_lock;
|
||||
|
||||
public:
|
||||
AutoWriteLock(RWLock &lock);
|
||||
~AutoWriteLock();
|
||||
|
||||
bool Release();
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_RW_LOCK_HPP
|
||||
205
DependentExtensions/cat/threads/RegionAllocator.hpp
Normal file
205
DependentExtensions/cat/threads/RegionAllocator.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_REGION_ALLOCATOR_HPP
|
||||
#define CAT_REGION_ALLOCATOR_HPP
|
||||
|
||||
#include <cat/Singleton.hpp>
|
||||
#include <memory>
|
||||
#include <xstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// A region-based allocator that is lock-free, supporting
|
||||
// a range of allocation block sizes that are pre-allocated
|
||||
// in a pre-determined way, tuned to the application.
|
||||
class RegionAllocator : public Singleton<RegionAllocator>
|
||||
{
|
||||
CAT_SINGLETON(RegionAllocator);
|
||||
|
||||
protected:
|
||||
struct RegionInfoHead
|
||||
{
|
||||
u32 next_bitmap_entry;
|
||||
};
|
||||
|
||||
struct RegionInfo : public RegionInfoHead
|
||||
{
|
||||
volatile u32 bitmap[1];
|
||||
};
|
||||
|
||||
// 64, 128, 256, 512, 1024, 2048 only
|
||||
static const u32 REGION_COUNT = 6;
|
||||
static const u32 BLOCK_SIZE[REGION_COUNT];
|
||||
|
||||
u32 bytes_overall;
|
||||
u32 blocks_per_region[REGION_COUNT];
|
||||
u32 bitmap_dwords[REGION_COUNT];
|
||||
u8 *regions[REGION_COUNT];
|
||||
RegionInfo *region_info[REGION_COUNT];
|
||||
|
||||
//u32 errors;
|
||||
|
||||
public:
|
||||
bool Valid();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
public:
|
||||
void *Acquire(u32 bytes);
|
||||
void *Resize(void *ptr, u32 bytes);
|
||||
void Release(void *ptr);
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE void Delete(T *ptr)
|
||||
{
|
||||
ptr->~T();
|
||||
Release(ptr);
|
||||
}
|
||||
|
||||
// Acquires a buffer from the allocator that is the size of the type.
|
||||
// It further allocates a number of extra bytes beyond the end of the buffer.
|
||||
// Release the buffer with:
|
||||
// RegionAllocator::ii->Release(ptr);
|
||||
template<class T> T *AcquireBuffer(u32 extra_bytes = 0)
|
||||
{
|
||||
return reinterpret_cast<T*>( Acquire(sizeof(T) + extra_bytes) );
|
||||
}
|
||||
};
|
||||
|
||||
// Use STLRegionAllocator in place of the standard STL allocator
|
||||
// to make use of the RegionAllocator in STL types. Some common
|
||||
// usage typedefs follow this class definition below.
|
||||
template<typename T>
|
||||
class STLRegionAllocator
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef size_t difference_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template<typename S>
|
||||
struct rebind
|
||||
{
|
||||
typedef STLRegionAllocator<S> other;
|
||||
};
|
||||
|
||||
pointer address(reference X) const
|
||||
{
|
||||
return &X;
|
||||
}
|
||||
|
||||
const_pointer address(const_reference X) const
|
||||
{
|
||||
return &X;
|
||||
}
|
||||
|
||||
STLRegionAllocator() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
STLRegionAllocator(const STLRegionAllocator<S> &cp) throw ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
STLRegionAllocator<T> &operator=(const STLRegionAllocator<S> &cp) throw ()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
pointer allocate(size_type Count, const void *Hint = 0)
|
||||
{
|
||||
return (pointer)RegionAllocator::ii->Acquire((u32)Count * sizeof(T));
|
||||
}
|
||||
|
||||
void deallocate(pointer Ptr, size_type Count)
|
||||
{
|
||||
RegionAllocator::ii->Release(Ptr);
|
||||
}
|
||||
|
||||
void construct(pointer Ptr, const T &Val)
|
||||
{
|
||||
std::_Construct(Ptr, Val);
|
||||
}
|
||||
|
||||
void destroy(pointer Ptr)
|
||||
{
|
||||
std::_Destroy(Ptr);
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return 0x00FFFFFF;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool operator==(STLRegionAllocator <S> const &) const throw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool operator!=(STLRegionAllocator <S> const &) const throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Common usage typedefs for using RegionAllocator as the STL allocator
|
||||
typedef std::basic_ostringstream<char, std::char_traits<char>, STLRegionAllocator<char> > region_ostringstream;
|
||||
typedef std::basic_string<char, std::char_traits<char>, STLRegionAllocator<char> > region_string;
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
// Provide placement new constructor and delete pair to allow for
|
||||
// an easy syntax to create objects from the RegionAllocator:
|
||||
// T *a = new (RegionAllocator::ii) T();
|
||||
// The object can be freed with:
|
||||
// RegionAllocator::ii->Delete(a);
|
||||
// Which insures that the destructor is called before freeing memory
|
||||
inline void *operator new(size_t bytes, cat::RegionAllocator *allocator)
|
||||
{
|
||||
return allocator->Acquire((cat::u32)bytes);
|
||||
}
|
||||
|
||||
inline void operator delete(void *ptr, cat::RegionAllocator *allocator)
|
||||
{
|
||||
allocator->Release(ptr);
|
||||
}
|
||||
|
||||
|
||||
#endif // CAT_REGION_ALLOCATOR_HPP
|
||||
80
DependentExtensions/cat/threads/Thread.hpp
Normal file
80
DependentExtensions/cat/threads/Thread.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_HPP
|
||||
#define CAT_THREAD_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#else // use POSIX thread library otherwise
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
A thread that executes ThreadFunction and then exits.
|
||||
|
||||
Derive from this class and implement ThreadFunction().
|
||||
*/
|
||||
class Thread
|
||||
{
|
||||
protected:
|
||||
void *caller_param;
|
||||
volatile bool _thread_running;
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
volatile HANDLE _thread;
|
||||
static unsigned int __stdcall ThreadWrapper(void *this_object);
|
||||
#else
|
||||
pthread_t _thread;
|
||||
static void *ThreadWrapper(void *this_object);
|
||||
#endif
|
||||
|
||||
public:
|
||||
bool StartThread(void *param = 0);
|
||||
bool WaitForThread(int milliseconds = -1); // < 0 = infinite wait
|
||||
void AbortThread();
|
||||
|
||||
CAT_INLINE bool ThreadRunning() { return _thread_running; }
|
||||
|
||||
protected:
|
||||
virtual bool ThreadFunction(void *param) = 0;
|
||||
|
||||
public:
|
||||
Thread();
|
||||
CAT_INLINE virtual ~Thread() {}
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_HPP
|
||||
221
DependentExtensions/cat/threads/ThreadPool.hpp
Normal file
221
DependentExtensions/cat/threads/ThreadPool.hpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_HPP
|
||||
#define CAT_THREAD_POOL_HPP
|
||||
|
||||
#include <cat/Singleton.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/threads/RegionAllocator.hpp>
|
||||
#include <cat/io/AsyncBuffer.hpp>
|
||||
#include <cat/threads/Thread.hpp>
|
||||
#include <cat/threads/WaitableFlag.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Reference Object priorities
|
||||
enum RefObjectPriorities
|
||||
{
|
||||
REFOBJ_PRIO_0,
|
||||
REFOBJ_PRIO_COUNT = 32,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class ThreadRefObject
|
||||
|
||||
Base class for any thread-safe reference-counted thread pool object
|
||||
|
||||
Designed this way so that all of these objects can be automatically deleted
|
||||
*/
|
||||
class ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
ThreadRefObject *last, *next;
|
||||
|
||||
int _priorityLevel;
|
||||
volatile u32 _refCount;
|
||||
|
||||
public:
|
||||
ThreadRefObject(int priorityLevel);
|
||||
CAT_INLINE virtual ~ThreadRefObject() {}
|
||||
|
||||
public:
|
||||
void AddRef();
|
||||
void ReleaseRef();
|
||||
|
||||
// Safe release -- If not null, then releases and sets to null
|
||||
template<class T>
|
||||
static CAT_INLINE void SafeRelease(T * &object)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
object->ReleaseRef();
|
||||
object = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Auto release for ThreadRefObject references
|
||||
template<class T>
|
||||
class AutoRef
|
||||
{
|
||||
T *_ref;
|
||||
|
||||
public:
|
||||
CAT_INLINE AutoRef(T *ref = 0) throw() { _ref = ref; }
|
||||
CAT_INLINE ~AutoRef() throw() { ThreadRefObject::SafeRelease(_ref); }
|
||||
CAT_INLINE AutoRef &operator=(T *ref) throw() { Reset(ref); return *this; }
|
||||
|
||||
CAT_INLINE T *Get() throw() { return _ref; }
|
||||
CAT_INLINE T *operator->() throw() { return _ref; }
|
||||
CAT_INLINE T &operator*() throw() { return *_ref; }
|
||||
CAT_INLINE operator T*() { return _ref; }
|
||||
|
||||
CAT_INLINE void Forget() throw() { _ref = 0; }
|
||||
CAT_INLINE void Reset(T *ref = 0) throw() { ThreadRefObject::SafeRelease(_ref); _ref = ref; }
|
||||
};
|
||||
|
||||
|
||||
//// TLS
|
||||
|
||||
class ThreadPoolLocalStorage
|
||||
{
|
||||
public:
|
||||
BigTwistedEdwards *math;
|
||||
FortunaOutput *csprng;
|
||||
|
||||
ThreadPoolLocalStorage();
|
||||
~ThreadPoolLocalStorage();
|
||||
|
||||
bool Valid();
|
||||
};
|
||||
|
||||
|
||||
//// Shutdown
|
||||
|
||||
class ShutdownWait;
|
||||
class ShutdownObserver;
|
||||
|
||||
class ShutdownWait
|
||||
{
|
||||
friend class ShutdownObserver;
|
||||
|
||||
WaitableFlag _kill_flag;
|
||||
ShutdownObserver *_observer;
|
||||
|
||||
void OnShutdownDone();
|
||||
|
||||
public:
|
||||
// Priority number must be higher than users'
|
||||
ShutdownWait(int priorityLevel);
|
||||
/*virtual*/ ~ShutdownWait();
|
||||
|
||||
CAT_INLINE ShutdownObserver *GetObserver() { return _observer; }
|
||||
|
||||
bool WaitForShutdown(u32 milliseconds);
|
||||
};
|
||||
|
||||
class ShutdownObserver : public ThreadRefObject
|
||||
{
|
||||
friend class ShutdownWait;
|
||||
|
||||
ShutdownWait *_wait;
|
||||
|
||||
private:
|
||||
ShutdownObserver(int priorityLevel, ShutdownWait *wait);
|
||||
~ShutdownObserver();
|
||||
};
|
||||
|
||||
|
||||
//// ThreadPoolWorker
|
||||
|
||||
class ThreadPoolWorker : public Thread
|
||||
{
|
||||
public:
|
||||
virtual bool ThreadFunction(void *port);
|
||||
};
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
typedef HANDLE ThreadPoolHandle;
|
||||
#else
|
||||
typedef int ThreadPoolHandle;
|
||||
#endif
|
||||
|
||||
/*
|
||||
class ThreadPool
|
||||
|
||||
Startup() : Call to start up the thread pool
|
||||
Shutdown() : Call to destroy the thread pool and objects
|
||||
*/
|
||||
class ThreadPool : public Singleton<ThreadPool>
|
||||
{
|
||||
friend class ThreadRefObject;
|
||||
|
||||
CAT_SINGLETON(ThreadPool);
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
HANDLE _port;
|
||||
#endif
|
||||
|
||||
int _processor_count, _active_thread_count;
|
||||
|
||||
static const int MAX_THREADS = 256;
|
||||
ThreadPoolWorker _threads[MAX_THREADS];
|
||||
|
||||
// Track sockets for graceful termination
|
||||
Mutex _objectRefLock[REFOBJ_PRIO_COUNT];
|
||||
ThreadRefObject *_objectRefHead[REFOBJ_PRIO_COUNT];
|
||||
|
||||
protected:
|
||||
void TrackObject(ThreadRefObject *object);
|
||||
void UntrackObject(ThreadRefObject *object);
|
||||
|
||||
bool SpawnThread();
|
||||
bool SpawnThreads();
|
||||
|
||||
public:
|
||||
bool Startup();
|
||||
void Shutdown();
|
||||
bool Associate(ThreadPoolHandle h, ThreadRefObject *key);
|
||||
|
||||
int GetProcessorCount() { return _processor_count; }
|
||||
int GetThreadCount() { return _active_thread_count; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_HPP
|
||||
92
DependentExtensions/cat/threads/WaitableFlag.hpp
Normal file
92
DependentExtensions/cat/threads/WaitableFlag.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_WAITABLE_FLAG_HPP
|
||||
#define CAT_WAITABLE_FLAG_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#else // use POSIX thread library otherwise
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
class WaitableFlag
|
||||
|
||||
Can be set, reset or waited upon.
|
||||
|
||||
Initially unset.
|
||||
Flag is edge-triggered.
|
||||
Successful waiting will reset the flag.
|
||||
Only one thread can wait at a time.
|
||||
|
||||
Designed to synchronize threads:
|
||||
One thread can wait for this flag to be raised by another thread before continuing.
|
||||
*/
|
||||
class WaitableFlag
|
||||
{
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
HANDLE _event;
|
||||
#else
|
||||
bool _valid, _valid_cond, _valid_mutex;
|
||||
volatile u32 _flag;
|
||||
pthread_cond_t _cond;
|
||||
pthread_mutex_t _mutex;
|
||||
#endif
|
||||
|
||||
void Cleanup();
|
||||
|
||||
public:
|
||||
WaitableFlag();
|
||||
CAT_INLINE virtual ~WaitableFlag()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
CAT_INLINE bool Valid()
|
||||
{
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
return _event != 0;
|
||||
#else
|
||||
return _valid;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Set();
|
||||
bool Wait(int milliseconds = -1); // < 0 = wait forever
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_WAITABLE_FLAG_HPP
|
||||
Reference in New Issue
Block a user