diff options
Diffstat (limited to 'src/components/utils/include/utils/threads')
3 files changed, 318 insertions, 0 deletions
diff --git a/src/components/utils/include/utils/threads/pulse_thread_delegate.h b/src/components/utils/include/utils/threads/pulse_thread_delegate.h new file mode 100644 index 0000000000..bb109bde94 --- /dev/null +++ b/src/components/utils/include/utils/threads/pulse_thread_delegate.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * 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 the Ford Motor Company 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 SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_PULSE_THREAD_DELEGATE_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_PULSE_THREAD_DELEGATE_H_ + +#include <sys/neutrino.h> + +#include "utils/threads/thread_delegate.h" + +namespace threads { + +/** + * @brief This ThreadDelegate derivative is designed + * to implement threads waiting for QNX Pulse messages + * When constucted, an instance of this class creates QNX channel and connects to it + * In exitThreadMain() channel is disconnected and destroyed + * In threadMain() endless loop event is armed via pure virtual method ArmEvent() + * and thread blocks on MsgReceivePulse() waiting for Pulse + * When Pulse comes, OnPulse() pure virtual method is invoked + * Subclassed must implement ArmEvent() for events of interest + * and OnPulse() for reaction on such events + */ +class PulseThreadDelegate : public ThreadDelegate { + public: +/** + * @brief default constructor + */ + PulseThreadDelegate(); + virtual void threadMain(); + virtual bool exitThreadMain(); + + protected: +/** + * @brief This method is to be implemented to arm events of interest + * @param event pointer to structure sigevent + * @return If this method returns true, thread is blocked on MsgReceivePulse() waiting for Pulse + */ + virtual bool ArmEvent(struct sigevent* event) = 0; +/** + * @brief This method is invoked from threadMain() when Pulse comes + */ + virtual void OnPulse() = 0; + + /** + * This method is to be initialize child class + * @return If this method returns false, thread will be stopped + */ + virtual bool Init() { return true; } + +/** + * Finalizes thread + * Can free resources + */ + virtual void Finalize() {} + + private: + enum {PULSE_CODE = _PULSE_CODE_MINAVAIL + 1}; + + bool run_; + int chid_; + int coid_; +}; + +} // namespace threads + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_PULSE_THREAD_DELEGATE_H_ diff --git a/src/components/utils/include/utils/threads/thread_manager.h b/src/components/utils/include/utils/threads/thread_manager.h new file mode 100644 index 0000000000..03330170e1 --- /dev/null +++ b/src/components/utils/include/utils/threads/thread_manager.h @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2013, Ford Motor Company + * 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 the Ford Motor Company 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 SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_MANAGER_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_MANAGER_H_ + +#include "utils/threads/thread.h" +#include "utils/lock.h" + +#include <map> +#include <string> +#include <set> + +#include "utils/macro.h" +#include "utils/singleton.h" + +namespace threads { +namespace impl { + +/* + * Generates short and unique names for unnamed threads + * and remembers association between thread handle and that short name + */ +class UnnamedThreadRegistry { + public: + UnnamedThreadRegistry(); + ~UnnamedThreadRegistry(); + /* + * Returns a name for given unnamed thread id. + * If id is first seen, new name is generated and memorized + * If id is already known, previously generated name is returned + */ + std::string GetUniqueName(PlatformThreadHandle id); + private: + typedef std::map<PlatformThreadHandle, std::string> IdNameMap; + IdNameMap id_number_; + int32_t last_thread_number_; + sync_primitives::Lock state_lock_; +}; + +/* + * This class is here currently to remember names associated to threads. + * It manages raw impl::PlatformHandles because Thread::Id's do not provide + * comparison operator. Current linux implementation relies on fact that + * pthread_t is just an integer and every thread has single unique value + * associated with it. + * OS provides it's own facilities to name threads but + */ +class ThreadManager : public utils::Singleton<ThreadManager> { + public: + // Name a thread. Should be called only once for every thread. + // Threads can't be renamed + void RegisterName(PlatformThreadHandle id, const std::string& name); + + // Get a name for previously registered thread + std::string GetName(PlatformThreadHandle id) const; + + // Forget a name of (possibly destroyed) thread + // Make sure to call it after thread is finished + // Because thread id's can be recycled + void Unregister(PlatformThreadHandle id); + private: + ThreadManager(); + ~ThreadManager(); + + private: + typedef std::set<std::string> NamesSet; + typedef std::map<PlatformThreadHandle, std::string> IdNamesMap; + // Set of thread names for fast checking if name is unique + NamesSet names_; + // Map from system handle to the thread name + IdNamesMap id_names_; + mutable sync_primitives::Lock state_lock_; + + // Generator of shorter sequental names for unnamed threads + // Has to memorize every generated name this is why it is mutable + mutable UnnamedThreadRegistry unnamed_thread_namer_; + + private: + DISALLOW_COPY_AND_ASSIGN(ThreadManager); + + FRIEND_BASE_SINGLETON_CLASS(ThreadManager); +}; + +} // namespace impl +} // namespace threads + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_MANAGER_H_ diff --git a/src/components/utils/include/utils/threads/thread_validator.h b/src/components/utils/include/utils/threads/thread_validator.h new file mode 100644 index 0000000000..def1994b76 --- /dev/null +++ b/src/components/utils/include/utils/threads/thread_validator.h @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2013, Ford Motor Company + * 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 the Ford Motor Company 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 SRC_COMPONENTS_UTILS_INCLUDE_THREADS_THREAD_VALIDATOR_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_THREADS_THREAD_VALIDATOR_H_ + +#include "utils/threads/thread.h" + +namespace threads { +/* + * Use objects of this class to validate (in run-time) access + * to single-threaded objects. It remembers the thread it was + * created on and then allows to easily check whether an object is + * being accessed from different thread and log an error in that case + * + * Put a member of type SingleThreadValidator in your class and call + * AssertRunningOnCreationThread in it's every public method + * + * class MySingleThreadedThing { + * ..... + * public: + * void DoSomeWork(); + * ..... + * private: + * SingleThreadValidator thread_validator_; + * ..... + * }; + * + * void MySingleThreadedThing::DoSomeWork() { + * thread_validator_.AssertRunningOnCreationThread(); + * ..... + * } + */ +class SingleThreadSimpleValidator { + public: + SingleThreadSimpleValidator(); + ~SingleThreadSimpleValidator(); + + // This method should be called in every public method + // of classes being checked for absence of concurrent access + void AssertRunningOnCreationThread() const; + private: + const Thread::Id creation_thread_id_; +}; + + +/* + * This is bit more sophisticated debug helper which allows + * objects being checked to be transferred between threads. + * Make sure to pass ownership calling PassToThread before + * object is accessed from that thread! + * + * It's better to virtually inherit it to make PassToThread publicly + * available to code that uses objects of your classes and make sure + * that if your object consists of different thread-validated + * parts you'll need not to call PassToThread proxy method for + * every part of your composite object + */ +class SingleThreadValidator { + public: + SingleThreadValidator(); + ~SingleThreadValidator(); + + // Must be called prior to transferring object being validated to + // another thread or when passing it back + void PassToThread(Thread::Id thread_id) const; + // This method should be called in every public method + // of classes being checked for absence of unintended concurrent + // access + void AssertRunningOnValidThread() const; + private: + mutable Thread::Id owning_thread_id_; +}; + +} // namespace threads + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_THREADS_THREAD_VALIDATOR_H_ |