]> git.saurik.com Git - apple/security.git/blobdiff - cdsa/cdsa_utilities/threading.h
Security-222.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / threading.h
diff --git a/cdsa/cdsa_utilities/threading.h b/cdsa/cdsa_utilities/threading.h
deleted file mode 100644 (file)
index e1f4afb..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- * 
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- * 
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-//
-// threading - generic thread support
-//
-#ifndef _H_THREADING
-#define _H_THREADING
-
-#include <Security/utilities.h>
-#include <Security/debugging.h>
-
-#if _USE_THREADS == _USE_PTHREADS
-# include <pthread.h>
-#endif
-
-#include <Security/threading_internal.h>
-
-
-namespace Security {
-
-
-//
-// Potentially, debug-logging all Mutex activity can really ruin your
-// performance day. We take some measures to reduce the impact, but if
-// you really can't stomach any overhead, define THREAD_NDEBUG to turn
-// (only) thread debug-logging off. NDEBUG will turn this on automatically.
-// On the other hand, throwing out all debug code will change the ABI of
-// Mutexi in incompatible ways. Thus, we still generate the debug-style out-of-line
-// code even with THREAD_NDEBUG, so that debug-style code will work with us.
-// If you want to ditch it completely, #define THREAD_CLEAN_NDEBUG.
-//
-#if defined(NDEBUG) || defined(THREAD_CLEAN_NDEBUG)
-# if !defined(THREAD_NDEBUG)
-#  define THREAD_NDEBUG
-# endif
-#endif
-
-
-//
-// An abstraction of a per-thread untyped storage slot of pointer size.
-// Do not use this in ordinary code; this is for implementing other primitives only.
-// Use a PerThreadPointer or ThreadNexus.
-//
-#if _USE_THREADS == _USE_PTHREADS
-
-class ThreadStoreSlot {
-public:
-       typedef void Destructor(void *);
-    ThreadStoreSlot(Destructor *destructor = NULL);
-    ~ThreadStoreSlot();
-
-    void *get() const                  { return pthread_getspecific(mKey); }
-    operator void * () const   { return get(); }
-    void operator = (void *value) const
-    {
-        if (int err = pthread_setspecific(mKey, value))
-            UnixError::throwMe(err);
-    }
-
-private:
-    pthread_key_t mKey;
-};
-
-#endif //_USE_PTHREADS
-
-
-//
-// Per-thread pointers are patterned after the pthread TLS (thread local storage)
-// facility.
-// Let's be clear on what gets destroyed when, here. Following the pthread lead,
-// when a thread dies its PerThreadPointer object(s) are properly destroyed.
-// However, if a PerThreadPointer itself is destroyed, NOTHING HAPPENS. Yes, there are
-// reasons for this. This is not (on its face) a bug, so don't yell. But be aware...
-//
-#if _USE_THREADS == _USE_PTHREADS
-
-template <class T>
-class PerThreadPointer : public ThreadStoreSlot {
-public:
-       PerThreadPointer(bool cleanup = true) : ThreadStoreSlot(cleanup ? destructor : NULL) { }
-       operator bool() const           { return get() != NULL; }
-       operator T * () const           { return reinterpret_cast<T *>(get()); }
-    T *operator -> () const            { return static_cast<T *>(*this); }
-    T &operator * () const             { return *static_cast<T *>(get()); }
-    void operator = (T *t)             { ThreadStoreSlot::operator = (t); }
-       
-private:
-       static void destructor(void *element)
-       { delete reinterpret_cast<T *>(element); }
-};
-
-#elif _USE_THREADS == _USE_NO_THREADS
-
-template <class T>
-class PerThreadPointer {
-public:
-       PerThreadPointer(bool cleanup = true) : mCleanup(cleanup) { }
-    ~PerThreadPointer()                        { /* no cleanup - see comment above */ }
-       operator bool() const           { return mValue != NULL; }
-       operator T * () const           { return mValue; }
-    T *operator -> () const            { return mValue; }
-    T &operator * () const             { assert(mValue); return *mValue; }
-    void operator = (T *t)             { mValue = t; }
-
-private:
-    T *mValue;
-    bool mCleanup;
-};
-
-#else
-# error Unsupported threading model
-#endif //_USE_THREADS
-
-
-//
-// Basic Mutex operations.
-// This will be some as-cheap-as-feasible locking primitive that only
-// controls one bit (locked/unlocked), plus whatever you contractually
-// put under its control.
-//
-#if _USE_THREADS == _USE_PTHREADS
-
-class Mutex {
-    NOCOPY(Mutex)
-    
-    void check(int err)        { if (err) UnixError::throwMe(err); }
-
-public:
-       enum Type {
-        normal,
-               recursive
-       };
-    
-    Mutex(bool log = true);
-    Mutex(Type type, bool log = true);
-       ~Mutex();
-    void lock();
-       bool tryLock();
-    void unlock();
-
-private:
-    pthread_mutex_t me;
-       
-       bool debugLog;                                          // log *this* mutex
-       unsigned long useCount;                         // number of locks succeeded
-       unsigned long contentionCount;          // number of contentions (valid only if debugLog)
-       static bool debugHasInitialized;        // global: debug state set up
-       static bool loggingMutexi;                      // global: we are debug-logging mutexi
-    
-    void init(Type type, bool log);
-};
-
-#elif _USE_THREADS == _USE_NO_THREADS
-
-class Mutex {
-public:
-    void lock(bool = true) { }
-    void unlock() { }
-    bool tryLock() { return true; }
-};
-
-#else
-# error Unsupported threading model
-#endif //_USE_THREADS
-
-
-//
-// A CountingMutex adds a counter to a Mutex.
-// NOTE: This is not officially a semaphore, even if it happens to be implemented with
-//  one on some platforms.
-//
-class CountingMutex : public Mutex {
-    // note that this implementation works for any system implementing Mutex *somehow*
-public:
-    CountingMutex() : mCount(0) { }
-    ~CountingMutex() { assert(mCount == 0); }
-
-    void enter();
-    bool tryEnter();
-    void exit();
-
-    // these methods do not lock - use only while you hold the lock
-    unsigned int count() const { return mCount; }
-    bool isIdle() const { return mCount == 0; }
-
-    // convert Mutex lock to CountingMutex enter/exit. Expert use only
-    void finishEnter();
-       void finishExit();
-   
-private:
-    unsigned int mCount;
-};
-
-//
-// A guaranteed-unlocker stack-based class.
-// By default, this will use lock/unlock methods, but you can provide your own
-// alternates (to, e.g., use enter/exit, or some more specialized pair of operations).
-//
-// NOTE: StLock itself is not thread-safe. It is intended for use (usually on the stack)
-// by a single thread.
-//
-template <class Lock,
-       void (Lock::*_lock)() = &Lock::lock,
-       void (Lock::*_unlock)() = &Lock::unlock>
-class StLock {
-public:
-       StLock(Lock &lck) : me(lck)                     { (me.*_lock)(); mActive = true; }
-       StLock(Lock &lck, bool option) : me(lck), mActive(option) { }
-       ~StLock()                                                       { if (mActive) (me.*_unlock)(); }
-
-       bool isActive() const                           { return mActive; }
-       void lock()                                                     { if(!mActive) { (me.*_lock)(); mActive = true; }}
-       void unlock()                                           { if(mActive) { (me.*_unlock)(); mActive = false; }}
-       void release()                                          { assert(mActive); mActive = false; }
-
-       operator const Lock &() const           { return me; }
-       
-protected:
-       Lock &me;
-       bool mActive;
-};
-
-
-//
-// Atomic increment/decrement operations.
-// The default implementation uses a Mutex. However, many architectures can do
-// much better than that.
-// Be very clear on the nature of AtomicCounter. It implies no memory barriers of
-// any kind. This means that (1) you cannot protect any other memory region with it
-// (use a Mutex for that), and (2) it may not enforce cross-processor ordering, which
-// means that you have no guarantee that you'll see modifications by other processors
-// made earlier (unless another mechanism provides the memory barrier).
-// On the other hand, if your compiler has brains, this is blindingly fast...
-//
-template <class Integer = int>
-class StaticAtomicCounter {
-protected:
-
-#if defined(_HAVE_ATOMIC_OPERATIONS)
-    AtomicWord mValue;
-public:
-    operator Integer() const   { return mValue; }
-
-    // infix versions (primary)
-    Integer operator ++ ()             { return atomicIncrement(mValue); }
-    Integer operator -- ()             { return atomicDecrement(mValue); }
-    
-    // postfix versions
-    Integer operator ++ (int)  { return atomicIncrement(mValue) - 1; }
-    Integer operator -- (int)  { return atomicDecrement(mValue) + 1; }
-
-    // generic offset
-    Integer operator += (int delta) { return atomicOffset(mValue, delta); }
-
-#else // no atomic integers, use locks
-
-    Integer mValue;
-    mutable Mutex mLock;
-public:
-    StaticAtomicCounter(Integer init = 0) : mValue(init), mLock(false) { }
-    operator Integer() const   { StLock<Mutex> _(mLock); return mValue; }
-    Integer operator ++ ()             { StLock<Mutex> _(mLock); return ++mValue; }
-    Integer operator -- ()             { StLock<Mutex> _(mLock); return --mValue; }
-    Integer operator ++ (int)  { StLock<Mutex> _(mLock); return mValue++; }
-    Integer operator -- (int)  { StLock<Mutex> _(mLock); return mValue--; }
-    Integer operator += (int delta) { StLock<Mutex> _(mLock); return mValue += delta; }
-#endif
-};
-
-
-template <class Integer = int>
-class AtomicCounter : public StaticAtomicCounter<Integer> {
-public:
-    AtomicCounter(Integer init = 0)    { mValue = 0; }
-};
-
-
-//
-// A class implementing a separate thread of execution.
-// Do not expect many high-level semantics to be portable. If you can,
-// restrict yourself to expect parallel execution and little else.
-//
-#if _USE_THREADS == _USE_PTHREADS
-
-class Thread {
-    NOCOPY(Thread)
-public:
-    class Identity {
-        friend class Thread;
-        
-        Identity(pthread_t id) : mIdent(id) { }
-    public:
-        Identity() { }
-        
-        static Identity current()      { return pthread_self(); }
-
-        bool operator == (const Identity &other) const
-        { return pthread_equal(mIdent, other.mIdent); }
-        
-        bool operator != (const Identity &other) const
-        { return !(*this == other); }
-        
-               // visible thread identifiers are FOR DEBUGGING ONLY
-               // if you use this for production code, your code will rot after shipment :-)
-        static const int idLength = 10;
-        static void getIdString(char id[idLength]);
-    
-    private:
-        pthread_t mIdent;
-    };
-
-public:
-    Thread() { }                               // constructor
-    virtual ~Thread();                 // virtual destructor
-    void run();                                        // begin running the thread
-    
-public:
-       static void yield();            // unstructured short-term processor yield
-    
-protected:
-    virtual void action() = 0;         // the action to be performed
-
-private:
-    Identity self;                             // my own identity (instance constant)
-
-    static void *runner(void *); // argument to pthread_create
-};
-
-#elif _USE_THREADS == _USE_NO_THREADS
-
-class Thread {
-    NOCOPY(Thread)
-public:
-       Thread() { }                            // constructor
-    virtual ~Thread() { }              // virtual destructor
-    void run() { action(); }   // just synchronously run the action
-    
-public:
-    class Identity {
-    public:
-        static Identity current() { return Identity(); }
-       
-        bool operator == (const Identity &) const              { return true; }        // all the same
-        bool operator != (const Identity &) const              { return false; }
-
-#if !defined(NDEBUG)
-        static const idLength = 9;
-        static void getIdString(char id[idLength]) { memcpy(id, "nothread", idLength); }
-#endif
-        
-    private:
-        Identity() { }
-    };
-       
-public:
-       void yield() { assert(false); }
-
-protected:
-    virtual void action() = 0; // implement action of thread
-};
-
-#else
-# error Unsupported threading model
-#endif
-
-
-//
-// A "just run this function in a thread" variant of Thread
-//
-class ThreadRunner : public Thread {
-    typedef void Action();
-public:
-    ThreadRunner(Action *todo);
-
-private:
-    void action();
-    Action *mAction;
-};
-
-
-//
-// A NestingMutex allows recursive re-entry by the same thread.
-// Some pthread implementations support this through a mutex attribute.
-// OSX's doesn't, naturally. This implementation works on all pthread platforms.
-//
-class NestingMutex {
-public:
-    NestingMutex();
-    
-    void lock();
-    bool tryLock();
-    void unlock();
-
-private:
-    Mutex mLock;
-    Mutex mWait;
-    Thread::Identity mIdent;
-    uint32 mCount;
-};
-
-} // end namespace Security
-
-#endif //_H_THREADING