summaryrefslogtreecommitdiff
path: root/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h
diff options
context:
space:
mode:
Diffstat (limited to 'distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h')
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h209
1 files changed, 209 insertions, 0 deletions
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h b/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h
new file mode 100755
index 00000000..84ddae70
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h
@@ -0,0 +1,209 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __TStack_h__
+#define __TStack_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <libkern/OSAtomic.h>
+#else
+// #include <DriverSynchronization.h>
+#include <CAAtomic.h>
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
+ #include <CoreServices/CoreServices.h>
+#endif
+
+// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
+// class T must implement set_next() and get_next()
+template <class T>
+class TAtomicStack {
+public:
+ TAtomicStack() : mHead(NULL) { }
+
+ // non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
+ void push_NA(T *item)
+ {
+ item->set_next(mHead);
+ mHead = item;
+ }
+
+ T * pop_NA()
+ {
+ T *result = mHead;
+ if (result)
+ mHead = result->get_next();
+ return result;
+ }
+
+ bool empty() { return mHead == NULL; }
+
+ T * head() { return mHead; }
+
+ // atomic routines
+ void push_atomic(T *item)
+ {
+ T *head;
+ do {
+ head = mHead;
+ item->set_next(head);
+ } while (!compare_and_swap(head, item, &mHead));
+ }
+
+ void push_multiple_atomic(T *item)
+ // pushes entire linked list headed by item
+ {
+ T *head, *p = item, *tail;
+ // find the last one -- when done, it will be linked to head
+ do {
+ tail = p;
+ p = p->get_next();
+ } while (p);
+ do {
+ head = mHead;
+ tail->set_next(head);
+ } while (!compare_and_swap(head, item, &mHead));
+ }
+
+ T * pop_atomic_single_reader()
+ // this may only be used when only one thread may potentially pop from the stack.
+ // if multiple threads may pop, this suffers from the ABA problem.
+ // <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
+ {
+ T *result;
+ do {
+ if ((result = mHead) == NULL)
+ break;
+ } while (!compare_and_swap(result, result->get_next(), &mHead));
+ return result;
+ }
+
+ T * pop_atomic()
+ // This is inefficient for large linked lists.
+ // prefer pop_all() to a series of calls to pop_atomic.
+ // push_multiple_atomic has to traverse the entire list.
+ {
+ T *result = pop_all();
+ if (result) {
+ T *next = result->get_next();
+ if (next)
+ // push all the remaining items back onto the stack
+ push_multiple_atomic(next);
+ }
+ return result;
+ }
+
+ T * pop_all()
+ {
+ T *result;
+ do {
+ if ((result = mHead) == NULL)
+ break;
+ } while (!compare_and_swap(result, NULL, &mHead));
+ return result;
+ }
+
+ T* pop_all_reversed()
+ {
+ TAtomicStack<T> reversed;
+ T *p = pop_all(), *next;
+ while (p != NULL) {
+ next = p->get_next();
+ reversed.push_NA(p);
+ p = next;
+ }
+ return reversed.mHead;
+ }
+
+ static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
+ {
+#if TARGET_OS_MAC
+ #if __LP64__
+ return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
+ #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
+ #else
+ return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+ #endif
+#else
+ //return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+ return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
+#endif
+ }
+
+protected:
+ T * mHead;
+};
+
+#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
+#include <libkern/OSAtomic.h>
+
+class CAAtomicStack {
+public:
+ CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) { /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/ mHead.opaque1 = 0; mHead.opaque2 = 0;
+ }
+ // a subset of the above
+ void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
+ void push_NA(void *p) { push_atomic(p); }
+
+ void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
+ void * pop_atomic_single_reader() { return pop_atomic(); }
+ void * pop_NA() { return pop_atomic(); }
+
+private:
+ OSQueueHead mHead;
+ size_t mNextPtrOffset;
+};
+
+// syntactic sugar
+template <class T>
+class TAtomicStack2 : public CAAtomicStack {
+public:
+ TAtomicStack2(size_t nextPtrOffset) : CAAtomicStack(nextPtrOffset) { }
+
+ T * pop_atomic() { return (T *)CAAtomicStack::pop_atomic(); }
+ T * pop_atomic_single_reader() { return pop_atomic(); }
+ T * pop_NA() { return pop_atomic(); }
+};
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
+
+#endif // __TStack_h__