summaryrefslogtreecommitdiff
path: root/src/components/utils/include/utils/threads
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/utils/include/utils/threads')
-rw-r--r--src/components/utils/include/utils/threads/pulse_thread_delegate.h96
-rw-r--r--src/components/utils/include/utils/threads/thread_manager.h117
-rw-r--r--src/components/utils/include/utils/threads/thread_validator.h105
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_