X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Futil%2FThreads.h;h=191cb154cd0303b48d93c48ffe7e026b33bfca4c;hb=2d795c731e6729309044607154978696a87fd900;hp=f6fe5ff7ae8c4f6a70834db8e5e0657bfc91350e;hpb=aff64904d1663ea3770daa633a80f64d205fbb2f;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/util/Threads.h b/xmltooling/util/Threads.h index f6fe5ff..191cb15 100644 --- a/xmltooling/util/Threads.h +++ b/xmltooling/util/Threads.h @@ -1,99 +1,108 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * UCAID licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the + * License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. */ /** * @file xmltooling/util/Threads.h - * - * Thread and locking wrappers + * + * Thread and locking wrappers. */ #ifndef _xmltooling_threads_h #define _xmltooling_threads_h -#include #include +#include +#include +#include + namespace xmltooling { DECL_XMLTOOLING_EXCEPTION(ThreadingException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during threading/locking operations); - + /** * A class for manual thread creation and synchronization. */ class XMLTOOL_API Thread { MAKE_NONCOPYABLE(Thread); - public: + protected: Thread() {} + public: virtual ~Thread() {} /** * Disassociate from the thread. - * + * * @return 0 for success, non-zero for failure */ virtual int detach()=0; - + /** * Join with the thread and wait for its completion. - * + * * @param thread_return holds the return value of the thread routine * @return 0 for success, non-zero for failure */ virtual int join(void** thread_return)=0; - + /** * Kill the thread. - * + * * @param signo the signal to send to the thread * @return 0 for success, non-zero for failure */ virtual int kill(int signo)=0; - + /** * Creates a new thread object to run the supplied start routine. - * + * * @param start_routine the function to execute on the thread * @param arg a parameter for the start routine - * @return the created and running thread object + * @param stacksize size of stack to use, or 0 for default + * @return the created and running thread object */ - static Thread* create(void* (*start_routine)(void*), void* arg); - + static Thread* create(void* (*start_routine)(void*), void* arg, size_t stacksize=0); + /** * Exits a thread gracefully. - * + * * @param return_val the return value for the thread */ static void exit(void* return_val); /** * Sleeps the current thread for the specified amount of time. - * + * * @param seconds time to sleep */ - static void sleep(int seconds); + static void sleep(int seconds); #ifndef WIN32 /** - * Masks all signals from a thread. + * Masks all signals from a thread. */ static void mask_all_signals(void); - + /** * Masks specific signals from a thread. - * + * * @param how * @param newmask the new signal mask * @param oldmask the old signal mask @@ -109,13 +118,14 @@ namespace xmltooling class XMLTOOL_API ThreadKey { MAKE_NONCOPYABLE(ThreadKey); - public: + protected: ThreadKey() {} + public: virtual ~ThreadKey() {} /** * Sets the value for a TLS key. - * + * * @param data the value to set * @return 0 for success, non-zero for failure */ @@ -123,18 +133,28 @@ namespace xmltooling /** * Returns the value for a TLS key. - * - * @return the value or NULL - */ + * + * @return the value or nullptr + */ virtual void* getData() const=0; /** * Creates a new TLS key. - * + * * @param destroy_fn a functon to cleanup key values * @return the new key */ static ThreadKey* create(void (*destroy_fn)(void*)); + +#ifdef WIN32 + /** + * Allows system to notify TLS implementation when a thread completes. + * + *

Windows doesn't support TLS destructors, so only the DllMain detach + * notification can be used to trigger per-thread cleanup. + */ + static void onDetach(); +#endif }; /** @@ -143,121 +163,124 @@ namespace xmltooling class XMLTOOL_API Mutex { MAKE_NONCOPYABLE(Mutex); - public: + protected: Mutex() {} + public: virtual ~Mutex() {} /** * Locks the mutex for exclusive access. - * + * * @return 0 for success, non-zero for failure */ virtual int lock()=0; - + /** * Unlocks the mutex for exclusive access. - * + * * @return 0 for success, non-zero for failure */ virtual int unlock()=0; /** * Creates a new mutex object. - * + * * @return the new mutex */ static Mutex* create(); }; - + /** * A class for managing shared and exclusive access to resources. */ class XMLTOOL_API RWLock { MAKE_NONCOPYABLE(RWLock); - public: + protected: RWLock() {} + public: virtual ~RWLock() {} /** * Obtains a shared lock. - * + * * @return 0 for success, non-zero for failure */ virtual int rdlock()=0; - + /** * Obtains an exclusive lock. - * + * * @return 0 for success, non-zero for failure */ virtual int wrlock()=0; /** * Unlocks the lock. - * + * * @return 0 for success, non-zero for failure */ virtual int unlock()=0; /** * Creates a new read/write lock. - * + * * @return the new lock */ static RWLock* create(); }; - + /** * A class for establishing queues on a mutex based on a periodic condition. */ class XMLTOOL_API CondWait { MAKE_NONCOPYABLE(CondWait); - public: + protected: CondWait() {} + public: virtual ~CondWait() {} - + /** * Waits for a condition variable using the supplied mutex as a queue. - * + * * @param lock mutex to queue on * @return 0 for success, non-zero for failure */ virtual int wait(Mutex* lock)=0; - + /** * Waits for a condition variable using the supplied mutex as a queue, * but only for a certain time limit. - * + * * @param lock mutex to queue on * @param delay_seconds maximum time to wait before waking up * @return 0 for success, non-zero for failure */ virtual int timedwait(Mutex* lock, int delay_seconds)=0; - + /** * Signal a single thread to wake up if a condition changes. - * + * * @return 0 for success, non-zero for failure */ virtual int signal()=0; - + /** * Signal all threads to wake up if a condition changes. - * + * * @return 0 for success, non-zero for failure */ virtual int broadcast()=0; /** * Creates a new condition variable. - * + * * @return the new condition variable */ static CondWait* create(); }; - + /** * RAII wrapper for a mutex lock. */ @@ -266,24 +289,66 @@ namespace xmltooling public: /** * Locks and wraps the designated mutex. - * - * @param mtx mutex to lock + * + * @param mtx mutex to lock */ Lock(Mutex* mtx) : mutex(mtx) { - mutex->lock(); + if (mutex) + mutex->lock(); + } + + /** + * Locks and wraps the designated mutex. + * + * @param mtx mutex to lock + */ + Lock(Mutex& mtx) : mutex(&mtx) { + mtx.lock(); + } + + /** + * Locks and wraps the designated mutex. + * + * @param mtx mutex to lock + */ + Lock(const std::auto_ptr& mtx) : mutex(mtx.get()) { + if (mutex) + mutex->lock(); } - + /** - * Unlocks the wrapped mutex. + * Locks and wraps the designated mutex. + * + * @param mtx mutex to lock + */ + Lock(const boost::scoped_ptr& mtx) : mutex(mtx.get()) { + if (mutex) + mutex->lock(); + } + + /** + * Unlocks the wrapped mutex, if any. */ ~Lock() { - mutex->unlock(); + if (mutex) + mutex->unlock(); } - + + /** + * Releases control of the original Mutex and returns it without unlocking it. + * + * @return the original, locked Mutex + */ + Mutex* release() { + Mutex* ret = mutex; + mutex = nullptr; + return ret; + } + private: Mutex* mutex; }; - + /** * RAII wrapper for a shared lock. */ @@ -292,22 +357,56 @@ namespace xmltooling public: /** * Locks and wraps the designated shared lock. - * - * @param lock lock to acquire + * + * @param lock lock to acquire * @param lockit true if the lock should be acquired here, false if already acquired */ SharedLock(RWLock* lock, bool lockit=true) : rwlock(lock) { - if (lockit) + if (rwlock && lockit) + rwlock->rdlock(); + } + + /** + * Locks and wraps the designated shared lock. + * + * @param lock lock to acquire + * @param lockit true if the lock should be acquired here, false if already acquired + */ + SharedLock(const std::auto_ptr& lock, bool lockit=true) : rwlock(lock.get()) { + if (rwlock && lockit) rwlock->rdlock(); } - + /** - * Unlocks the wrapped shared lock. + * Locks and wraps the designated shared lock. + * + * @param lock lock to acquire + * @param lockit true if the lock should be acquired here, false if already acquired + */ + SharedLock(const boost::scoped_ptr& lock, bool lockit=true) : rwlock(lock.get()) { + if (rwlock && lockit) + rwlock->rdlock(); + } + + /** + * Unlocks the wrapped shared lock, if any. */ ~SharedLock() { - rwlock->unlock(); + if (rwlock) + rwlock->unlock(); } - + + /** + * Releases control of the original shared lock and returns it without unlocking it. + * + * @return the original shared lock + */ + RWLock* release() { + RWLock* ret = rwlock; + rwlock = nullptr; + return ret; + } + private: RWLock* rwlock; };