diff options
author | Justin Dickow <jjdickow@gmail.com> | 2014-03-18 13:46:46 -0400 |
---|---|---|
committer | Justin Dickow <jjdickow@gmail.com> | 2014-03-18 13:46:46 -0400 |
commit | ba492fb83c258bc60ca68120ce964a95b41133b5 (patch) | |
tree | af99c087941d65a19831397c1ec5eb34850cfc7f /SDL_Core/src/components/Utils | |
parent | 8504605b01177da2e55bee6abe4c3f20c82da379 (diff) | |
download | smartdevicelink-ba492fb83c258bc60ca68120ce964a95b41133b5.tar.gz |
initial commit for API 3.0 (replaced all)
Diffstat (limited to 'SDL_Core/src/components/Utils')
39 files changed, 4711 insertions, 383 deletions
diff --git a/SDL_Core/src/components/Utils/CMakeLists.txt b/SDL_Core/src/components/Utils/CMakeLists.txt index dca9f3d2d..e456a51ff 100644 --- a/SDL_Core/src/components/Utils/CMakeLists.txt +++ b/SDL_Core/src/components/Utils/CMakeLists.txt @@ -1,12 +1,32 @@ include_directories ( ./include - ../../thirdPartyLibs/logger/include/ - ../../thirdPartyLibs/logger/log4cplus-1.1.0/include/ - ${CMAKE_BINARY_DIR}/src/thirdPartyLibs/logger/log4cplus-1.1.0/include + ../config_profile/include + ../media_manager/include/ + ../protocol_handler/include/ ) set (SOURCES - ./src/WorkWithOS.cpp + ./src/bitstream.cc + ./src/conditional_variable_posix.cc + ./src/file_system.cc + ./src/threads/posix_thread.cc + ./src/threads/thread_manager.cc + ./src/threads/thread_validator.cc + ./src/lock_posix.cc + ./src/date_time.cc + ./src/signals_linux.cc ) +if (BUILD_BACKTRACE_SUPPORT) + list(APPEND SOURCES + ./src/back_trace.cc + ) +endif() + add_library("Utils" ${SOURCES}) + +IF(${CMAKE_SYSTEM_NAME} MATCHES "QNX") + target_link_libraries ("Utils" log4cxx apr-1 aprutil-1) +else() + target_link_libraries ("Utils" log4cxx apr-1 aprutil-1 rt) +endif() diff --git a/SDL_Core/src/components/Utils/include/Utils/MessageQueue.h b/SDL_Core/src/components/Utils/include/Utils/MessageQueue.h deleted file mode 100644 index 3adb03e7f..000000000 --- a/SDL_Core/src/components/Utils/include/Utils/MessageQueue.h +++ /dev/null @@ -1,164 +0,0 @@ -/** -* \file MessageQueue.hpp -* \brief Template MessageQueue class header. -*/ - - -#ifndef MESSAGE_QUEUE_CLASS -#define MESSAGE_QUEUE_CLASS - - -#include <pthread.h> -#include <queue> - -/** - * \class MessageQueue - * \brief Wrapper for multithreading queue. -*/ -template <typename T> class MessageQueue -{ -public: - /** - * \brief Default constructor - */ - MessageQueue(); - - /** - * \brief Constructor - * \param queue Existing queue. - */ - explicit MessageQueue( std::queue<T> queue ); - - /** - * \brief Destructor - */ - ~MessageQueue(); - - /** - * \brief Returns size of the queue. - * \return Size of the queue. - */ - int size() const; - - /** - * \brief If queue is empty. - * \return Is queue empty. - */ - bool empty() const; - - /** - * \brief Adds element to the queue. - * \param element Element to be added to the queue.n - */ - void push( const T & element ); - - /** - * \brief Removes element from the queue and returns it. - * \return To element of the queue. - */ - T pop(); - - /** - * \brief Conditional wait. - */ - void wait(); - -private: - /** - *\brief Queue - */ - std::queue<T> mQueue; - /** - *\brief Mutex for queue locking. - */ - mutable pthread_mutex_t mMutex; - /** - *\brief Condition for waiting. - */ - pthread_cond_t mCond; - /** - *\brief Bool condition for waiting. - */ - bool mIsUp; -}; - -template <typename T> MessageQueue<T>::MessageQueue() -:mMutex( PTHREAD_MUTEX_INITIALIZER ) -,mCond( PTHREAD_COND_INITIALIZER ) -,mIsUp( false ) -{ - pthread_mutex_init( &mMutex, NULL ); - pthread_cond_init( &mCond, NULL ); -} - -template <typename T> MessageQueue<T>::MessageQueue( std::queue<T> queue ) -{ - pthread_mutex_init( &mMutex, NULL ); - pthread_cond_init( &mCond, NULL ); - pthread_mutex_lock( &mMutex ); - mQueue = std::queue<T>( queue ); - pthread_mutex_unlock( &mMutex ); -} - -template <typename T> MessageQueue<T>::~MessageQueue() -{ - pthread_cond_destroy( &mCond ); - pthread_mutex_destroy( &mMutex ); -} - -template<typename T> void MessageQueue<T>::wait() -{ - pthread_mutex_lock( &mMutex ); - while ( !mIsUp ) - { - pthread_cond_wait( &mCond, &mMutex ); - } - mIsUp = false; - pthread_mutex_unlock( &mMutex ); -} - -template <typename T> int MessageQueue<T>::size() const -{ - int result = 0; - pthread_mutex_lock( &mMutex ); - result = mQueue.size(); - pthread_mutex_unlock( &mMutex ); - return result; -} - -template <typename T> bool MessageQueue<T>::empty() const -{ - bool result = true; - pthread_mutex_lock( &mMutex ); - result = mQueue.empty(); - pthread_mutex_unlock( &mMutex ); - return result; -} - -template <typename T> void MessageQueue<T>::push( const T & element ) -{ - pthread_mutex_lock( &mMutex ); - mQueue.push( element ); - - pthread_cond_signal( &mCond ); - mIsUp = true; - - pthread_mutex_unlock( &mMutex ); -} - -template <typename T> T MessageQueue<T>::pop( ) -{ - pthread_mutex_lock( &mMutex ); - if ( mQueue.empty() ) - { - //error, TRACE - } - - T result = mQueue.front(); - mQueue.pop(); - - pthread_mutex_unlock( &mMutex ); - return result; -} - -#endif // MESSAGE_QUEUE_CLASS diff --git a/SDL_Core/src/components/Utils/include/Utils/MultithreadingMap.h b/SDL_Core/src/components/Utils/include/Utils/MultithreadingMap.h deleted file mode 100644 index 5a0f76a66..000000000 --- a/SDL_Core/src/components/Utils/include/Utils/MultithreadingMap.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MULTITHREADED_MAP_CLASS -#define MULTITHREADED_MAP_CLASS - -#include <map> - -template <typename T, typename K> class MultithreadingMap -{ -public: - MultithreadingMap(); - ~MultithreadingMap(); - - int size() const; - - bool empty() const; - - void insert( const std::pair<const T,K> & element ); - - K & find( const T & key ); - -private: - std::multimap<T,K> mMap; - - /** - *\brief Mutex for queue locking. - */ - mutable pthread_mutex_t mMutex; - -}; - -template <typename T, typename K> MultithreadingMap<T,K>::MultithreadingMap() : -mMutex( PTHREAD_MUTEX_INITIALIZER ) -{ - pthread_mutex_init( &mMutex, NULL ); -} - -template <typename T, typename K> MultithreadingMap<T,K>::~MultithreadingMap() -{ - pthread_mutex_destroy( &mMutex ); -} - - - -#endif // MULTITHREADED_MAP_CLASS
\ No newline at end of file diff --git a/SDL_Core/src/components/Utils/include/Utils/WorkWithOS.h b/SDL_Core/src/components/Utils/include/Utils/WorkWithOS.h deleted file mode 100644 index 2fbb58576..000000000 --- a/SDL_Core/src/components/Utils/include/Utils/WorkWithOS.h +++ /dev/null @@ -1,25 +0,0 @@ -/** -* \file WorkWithOS.h -* \brief class source file. -*/ - -#ifndef WORKWITHSYSTEM_INCLUDE -#define WORKWITHSYSTEM_INCLUDE - -#include <string.h> -#include <vector> - -namespace WorkWithOS -{ - unsigned long int getAvailableSpace(); - std::string createDirectory(const std::string & directoryName); - bool checkIfDirectoryExists(const std::string & directoryName); - bool checkIfFileExists(const std::string & fileName); - bool createFileAndWrite(const std::string & fileName, const std::vector<unsigned char>& fileData); - std::string getFullPath(const std::string & fileName); - bool deleteFile(const std::string & fileName); - std::vector<std::string> listFilesInDirectory(const std::string & directoryName); - bool readFileAsBinary(const std::string& fileName, std::vector<unsigned char>& v); -} - -#endif // WORKWITHSYSTEM_INCLUDE diff --git a/SDL_Core/src/components/Utils/include/Utils/back_trace.h b/SDL_Core/src/components/Utils/include/Utils/back_trace.h new file mode 100644 index 000000000..7f8912faf --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/back_trace.h @@ -0,0 +1,75 @@ +/** + * 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_BACK_TRACE_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_BACK_TRACE_H_ + +#include <ostream> +#include <vector> +#include <string> +#include "utils/threads/thread.h" + +namespace utils { + +/* + * Class that captures stack trace in place where it was created. + * Can be stored and passed for further processing + * ostream output operator is available for these objects so stacktrace + * here and now can be easily printed as + * + * std::cout<<utils::Backtrace()<<std::endl; + */ +class Backtrace { + public: + // Inspect stack up to 128 calls back + static const int32_t kDefaultDepth = 128; + static const int32_t kSkipTop = 0; + /* Capture backtrace and store. Limit captured stack length to + * count symbols and remove first skip_top elements from it + * (to avoid polluting stack trace with debugging function names) + */ + Backtrace(int32_t count = kDefaultDepth, int32_t skip_top = kSkipTop); + ~Backtrace(); + + // Captured symbols in order from topmost stack frame to last captured + std::vector<std::string> CallStack() const; + threads::Thread::Id ThreadId() const; + + private: + threads::Thread::Id thread_id_; + std::vector<void*> backtrace_; +}; + +std::ostream& operator<< (std::ostream& os, const Backtrace& bt); + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_BACK_TRACE_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/bitstream.h b/SDL_Core/src/components/Utils/include/Utils/bitstream.h new file mode 100644 index 000000000..cba15abd8 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/bitstream.h @@ -0,0 +1,170 @@ +/** + * 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_BITSTREAM_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_BITSTREAM_H_ + +#include "stdint.h" + +#include <climits> +#include <cstring> +#include <string> +#include <vector> + +#include "utils/macro.h" + +namespace utils { + +// Big endian input bitstream class +// Tool to read and parse incoming data in a recursive way +// Has sublte similarity to standard stream classes in a way +// it handles stream parsing errors: +// If error while parsing stream occurs, whole stream is marked as +// "bad" and all subsequent parsing is stopped. +class BitStream { + public: + BitStream(uint8_t* bytes, size_t bytes_count); + ~BitStream(); + + // Mark stream as badly-formed. + // Should be called by Extract* family of procedures if they decide + // that stream is invalid + void MarkBad() { bad_ = true; } + // Predicates to check whether there were errors while parsing + // Stream is good when it is created + bool IsGood() { return !bad_; } + bool IsBad() { return bad_; } + operator bool() { return IsGood(); } + private: + // These two functions are used for internal stream checks only + // Stream parser procedures must not define their logic depending on + // amount of data left in particular bit stream + + // Amount of full bytes left in stream + size_t FullBytesLeft(); + // Amount of total bits left in stream + size_t BitsLeft(); + + // These stream extractors are helpers for direct friend extractors + // of this class. + + // Extract single value, amount of bits read from stream depends on T size + // If there is not enough data in the stream, stream is marked bad + template<typename T> + void Extract(T& val); + + // Read single value, amount of bits read from stream is signaled by |bits| + // parameter. T must be wide enough to hold this amount of bits. + // If there is not enough data in the stream, stream is marked bad + template<typename T> + void ExtractBits(T& val, size_t bits); + + // Extract |length| bytes from the stream. Stream read position + // must be byte aligned when it is called, stream is marked bad otherwise. + // If there is not enough data in the stream, it is marked bad. + void ExtractBytes(void* buffer, size_t length); + + private: + const uint8_t* bytes_; + const size_t bytes_count_; + size_t byte_offset_; + size_t bit_offset_; + bool bad_; + private: + friend void Extract(BitStream*, uint8_t*); + friend void Extract(BitStream*, uint8_t*, size_t); + friend void Extract(BitStream*, uint32_t*); + friend void Extract(BitStream*, uint32_t*, size_t); + friend void Extract(BitStream*, std::string*, size_t); + friend void Extract(BitStream*, std::vector<uint8_t>*, size_t); + +}; + +// Extract single byte from stream +// If there is not enough data in the stream it is marked bad. +void Extract(BitStream* bs, uint8_t* val); + +// Extract defined amount of |bits| from stream and store them +// in a byte size |val|. Hence |bits| must be less than 8. +void Extract(BitStream* bs, uint8_t* val, size_t bits); + +// Extract 32 bit word from stream. +// If there is not enough data in the stream it is marked bad. +void Extract(BitStream* bs, uint32_t* val); + +// Extract up to 32 |bits| from stream and store them in a |val| +// If there is not enough data in the stream it is marked bad. +void Extract(BitStream* bs, uint32_t* val, size_t bits); + +// Extract |length| bytes from stream and store them to the +// string |str|. If stream is too short it is marked bad. +// String must not contain zero bytes. +void Extract(BitStream* bs, std::string* str, size_t length); + +// Extract |length| bytes from stream and store them to the +// vector |data|. If stream is too short it is marked bad. +void Extract(BitStream* bs, std::vector<uint8_t>* data, size_t length); + + +// Template member definitions +template<typename T> +void BitStream::Extract(T& val) { + // Slow but simple implementation + // It's a space for bit stream reading optimization + ExtractBits(val, sizeof(val) * CHAR_BIT); +} + +template<typename T> +void BitStream::ExtractBits(T& val, size_t bits) { + DCHECK(sizeof(val) * CHAR_BIT >= bits); + if (IsGood()) { + if (bits > BitsLeft()) { + MarkBad(); + return; + } + val = T(); // Clear value + for (size_t i = 0; i < bits; ++i) { + size_t next_bit_number = CHAR_BIT - 1 - bit_offset_; + uint8_t nextbit = (bytes_[byte_offset_] >> next_bit_number) & 1; + val = (val << 1) | nextbit; + ++bit_offset_; + if (bit_offset_ == CHAR_BIT) { + ++byte_offset_; + bit_offset_ = 0; + } + } + } +} + +} // namespace utils + + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_BITSTREAM_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/conditional_variable.h b/SDL_Core/src/components/Utils/include/Utils/conditional_variable.h new file mode 100644 index 000000000..433f8d7c0 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/conditional_variable.h @@ -0,0 +1,94 @@ +/** + * 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_CONDITIONAL_VARIABLE_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_CONDITIONAL_VARIABLE_H_ + +#if defined(OS_POSIX) +#include <pthread.h> +#else +#error Please implement conditional variable for your OS +#endif +#include <stdint.h> + +#include "utils/macro.h" + +namespace sync_primitives { +class AutoLock; + +namespace impl { +#if defined(OS_POSIX) +typedef pthread_cond_t PlatformConditionalVariable; +#endif +} // namespace impl + +/* + * Conditional variable wrapper + * Conditional variable is a thing that can be waited on + * Wait is finished when other thread puts that thing in a signaled state + * (or when timeout is over). + * Data that is conditionally accessed should be protected by + * a Lock and that lock must be taken before starting to Wait. + * When wait is performed, Lock is temporarly released. + * When wait is finished, Lock is captured back. + * WARNING: Beware of Spurious wakeups + * http://en.wikipedia.org/wiki/Spurious_wakeup + * Thread can wake up from wait spuriously, without conditional + * variable being actually set by other thread. This means + * additional check should be made right after thread awakening + * and if check fails thread should continue waiting. + * + * while(!DataReady()) cond_var.Wait(auto_lock); + * + */ +class ConditionalVariable { + public: + enum WaitStatus { kNoTimeout, kTimeout }; + ConditionalVariable(); + ~ConditionalVariable(); + // Wakes up single thread that is waiting on this conditional variable + void NotifyOne(); + // Wakes up all waiting threads + void Broadcast(); + + // Wait forever or up to milliseconds time limit + void Wait(AutoLock& auto_lock); + WaitStatus WaitFor(AutoLock& auto_lock, int32_t milliseconds ); + private: + impl::PlatformConditionalVariable cond_var_; + + private: + DISALLOW_COPY_AND_ASSIGN(ConditionalVariable); +}; + +} // namespace sync_primitives + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_CONDITIONAL_VARIABLE_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/date_time.h b/SDL_Core/src/components/Utils/include/Utils/date_time.h new file mode 100644 index 000000000..df2d067ac --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/date_time.h @@ -0,0 +1,56 @@ +/** +* \file request_watchdog.h +* \brief DateTime class header file. +* +* 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_DATE_TIME_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_DATE_TIME_H_ + +#if defined(OS_POSIX) +#include <sys/time.h> +typedef struct timeval TimevalStruct; +#endif + +namespace date_time { + +class DateTime { + public: + static const int32_t MILLISECONDS_IN_SECOND = 1000; + static const int32_t MICROSECONDS_IN_MILLISECONDS = 1000; + + static TimevalStruct getCurrentTime(); + static int32_t calculateTimeSpan(TimevalStruct sinceTime); +}; + +} // namespace date_time + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_DATE_TIME_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/dict.h b/SDL_Core/src/components/Utils/include/Utils/dict.h new file mode 100644 index 000000000..bb60390d1 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/dict.h @@ -0,0 +1,225 @@ +/** + * 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_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_H_ + +#include <map> + +namespace utils { + +template<typename Key, typename Record> +class Dictionary { + private: + typedef std::map<Key, Record> ItemContainer; + typedef std::map<Key, Dictionary> SubitemContainer; + + public: +/** + * @brief Typedef for subitems iterator + */ + typedef typename SubitemContainer::iterator iterator; +/** + * @brief Typedef for subitems const iterator + */ + typedef typename SubitemContainer::const_iterator const_iterator; + +/** + * @brief Typedef for items iterator + */ + typedef typename ItemContainer::iterator rec_iterator; +/** + * @brief Typedef for items const iterator + */ + typedef typename ItemContainer::const_iterator rec_const_iterator; + +/** + * @brief add an item to the dictionary + * @param key - item key + * @param record - item value + */ + void AddItem(const Key& key, const Record& record); +/** + * @brief add a subitem to the dictionary + * @param key - subitem key + * @param subitem - subitem dictionary + */ + void AddSubitem(const Key& key, const Dictionary& subitem); +/** + * @brief item under specified key + * @param key - item key + * @return item with specified key of default-constructed item + */ + Record& ItemAt(const Key& key); +/** + * @brief item under specified key + * @param key - item key + * @return item with specified key of default-constructed item + */ + const Record& ItemAt(const Key& key) const; +/** + * @brief subitem under specified key + * @param key - subitem key + * @return subitem with specified key of default-constructed dictionary + */ + Dictionary& SubitemAt(const Key& key); +/** + * @brief subitem under specified key + * @param key - subitem key + * @return subitem with specified key of default-constructed dictionary + */ + const Dictionary& SubitemAt(const Key& key) const; +/** + * @brief first subitem + * @return iterator pointing to the first subitem + */ + iterator begin(); + +/** + * @brief first subitem + * @return const iterator pointing to the first subitem + */ + const_iterator begin() const; + +/** + * @brief first item + * @return iterator pointing to the first item + */ + rec_iterator rec_begin(); + +/** + * @brief first item + * @return iterator pointing to the first item + */ + rec_const_iterator rec_begin() const; + +/** + * @brief end of subitem list + * @return iterator pointing to the end of subitem list + */ + iterator end(); +/** + * @brief end of subitem list + * @return const iterator pointing to the end of subitem list + */ + const_iterator end() const; + + /** + * @brief end of item list + * @return iterator pointing to the end of item list + */ + rec_iterator rec_end(); + + /** + * @brief end of item list + * @return const iterator pointing to the end of item list + */ + rec_const_iterator rec_end() const; + +private: + ItemContainer items_; + SubitemContainer subitems_; +}; + +template<typename Key, typename Record> +void Dictionary<Key, Record>::AddItem(const Key& key, const Record& record) { + items_.insert(std::make_pair(key, record)); +} + +template<typename Key, typename Record> +void Dictionary<Key, Record>::AddSubitem(const Key& key, const Dictionary& subitem) { + subitems_.insert(std::make_pair(key, subitem)); +} + +template<typename Key, typename Record> +Record& Dictionary<Key, Record>::ItemAt(const Key& key) { + return items_.at(key); +} + +template<typename Key, typename Record> +const Record& Dictionary<Key, Record>::ItemAt(const Key& key) const { + return items_.at(key); +} + +template<typename Key, typename Record> +Dictionary<Key, Record>& Dictionary<Key, Record>::SubitemAt(const Key& key) { + return subitems_.at(key); +} + +template<typename Key, typename Record> +const Dictionary<Key, Record>& Dictionary<Key, Record>::SubitemAt(const Key& key) const { + return subitems_.at(key); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::iterator Dictionary<Key, Record>::begin() { + return subitems_.begin(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::const_iterator Dictionary<Key, Record>::begin() const { + return subitems_.begin(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::rec_iterator Dictionary<Key, Record>::rec_begin() { + return items_.begin(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::rec_const_iterator Dictionary<Key, Record>::rec_begin() const { + return items_.begin(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::iterator Dictionary<Key, Record>::end() { + return subitems_.end(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::const_iterator Dictionary<Key, Record>::end() const { + return subitems_.end(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::rec_iterator Dictionary<Key, Record>::rec_end() { + return items_.end(); +} + +template<typename Key, typename Record> +typename Dictionary<Key, Record>::rec_const_iterator Dictionary<Key, Record>::rec_end() const { + return items_.end(); +} + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/file_system.h b/SDL_Core/src/components/Utils/include/Utils/file_system.h new file mode 100644 index 000000000..c40c15f39 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/file_system.h @@ -0,0 +1,207 @@ +/** + * 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_FILE_SYSTEM_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_FILE_SYSTEM_H_ + +#include <string.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <iostream> +#include "utils/logger.h" + +namespace file_system { + + +/** + * @brief Get available disc space. + * + * @return free disc space. + */ +uint64_t GetAvailableDiskSpace(); + +/* + * @brief Get size of current directory + * + * @param path to directory + */ +uint32_t DirectorySize(const std::string& path); + +/* + * @brief Get size of current file + * + * @param path to file + * @return size of file, return 0 if file not exist + */ +uint32_t FileSize(const std::string& path); + + +/** + * @brief Get available app space + * @param name of app + * @return free app space. + */ +uint32_t GetAvailableSpaceForApp(const std::string& name); + +/** + * @brief Creates directory + * @param name path to directory + * @return path to created directory. + */ +std::string CreateDirectory(const std::string& name); + +/** + * @brief Checks the file to see whether the file is a directory + * @param name path to file + * @return returns true if file is directory. + */ +bool IsDirectory(const std::string& name); + +/** + * @brief Is directory exist + * @param name path to directory + * @return returns true if directory is exists. + */ +bool DirectoryExists(const std::string& name); + +/** + * @brief Is file exist + * @param name path to file + * @return returns true if file is exists. + */ +bool FileExists(const std::string& name); + +/** + * @brief Writes to file + * + * @remark - create file if it doesn't exist + * @param name path to file + * @param data data to write + * @return returns true if the operation is successfully. + */ +bool Write(const std::string& file_name, + const std::vector<uint8_t>& data, + std::ios_base::openmode mode = std::ios_base::out); + +/** + * @brief Opens file stream for writing + * @param file_name path to file to write data to + * @return returns pointer to opened stream in case of success; + * otherwise returns NULL + */ +std::ofstream* Open(const std::string& file_name, + std::ios_base::openmode mode = std::ios_base::out); + +/** + * @brief Writes to file stream + * @param file_stream file stream to be written to + * @param data data to be written to file + * @param data_size size of data to be written to file + * @return returns true if the operation is successfully. + */ +bool Write(std::ofstream* const file_stream, + const uint8_t* data, + uint32_t data_size); + +/** + * @brief Closes file stream + * @param file_stream file stream to be closed + */ +void Close(std::ofstream* file_stream); + +/** + * @brief Returns full file path + * + * @param name file name + * @return returns full file path. + */ +std::string FullPath(const std::string& name); + +/** + * @brief Removes file + * + * @param name path to file + * @return returns true if the file is successfully deleted. + */ +bool DeleteFile(const std::string& name); + +/** + * @brief Removes directory. + * + * @param name path to directory. + * @param is_recursively true if you need delete directory recursively, otherwise false. + * @return returns true if the directory is successfully deleted. + */ +bool RemoveDirectory(const std::string& directory_name, + bool is_recursively = true); + +/** + * @brief Check access rights + * + * @param name path to file. + * @param how Read/write attribute. + * @return returns true if file has the given mode. + */ +bool IsAccessible(const std::string& name, int32_t how); + +/** + * @brief Lists all files in given directory + * + * @param name path to directory. + * @return returns list of files. + */ +std::vector<std::string> ListFiles(const std::string& directory_name); + +/** + * @brief Reads from file + * + * @param name path to file + * @param result read data + * @return returns true if the operation is successfully. + */ +bool ReadBinaryFile(const std::string& name, + std::vector<uint8_t>& result); + +bool ReadFile(const std::string& name, std::string& result); + +/** + * @brief Convert special symbols in system path to percent-encoded + * + * @param name path to file + * @return returns converted path. +*/ +const std::string ConvertPathForURL(const std::string& path); + +} // namespace file_system + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_FILE_SYSTEM_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/lock.h b/SDL_Core/src/components/Utils/include/Utils/lock.h new file mode 100644 index 000000000..2aaddbbc6 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/lock.h @@ -0,0 +1,132 @@ +/** + * 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_LOCK_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_LOCK_H_ + +#if defined(OS_POSIX) +#include <pthread.h> +#else +#error Please implement lock for your OS +#endif + +#include "utils/macro.h" + +namespace sync_primitives { + +namespace impl { +#if defined(OS_POSIX) +typedef pthread_mutex_t PlatformMutex; +#endif +} // namespace impl + +/* Platform-indepenednt NON-RECURSIVE lock (mutex) wrapper + Please use AutoLock to ackquire and (automatically) release it + It eases balancing of multple lock taking/releasing and makes it + Impossible to forget to release the lock: + ... + ConcurentlyAccessedData data_; + sync_primitives::Lock data_lock_; + ... + { + sync_primitives::AutoLock auto_lock(data_lock_); + data_.ReadOrWriteData(); + } // lock is automatically released here +*/ +class Lock { + public: + Lock(); + ~Lock(); + + // Ackquire the lock. Must be called only once on a thread. + // Please consider using AutoLock to capture it. + void Ackquire(); + // Release the lock. Must be called only once on a thread after lock. + // was acquired. Please consider using AutoLock to automatically release + // the lock + void Release(); + // Try if lock can be captured and lock it if it was possible. + // If it captured, lock must be manually released calling to Release + // when protected resource access was finished. + // @returns wether lock was captured. + bool Try(); + + private: + impl::PlatformMutex mutex_; + +#ifndef NDEBUG + // Basic debugging aid, a flag that signals wether this lock is currently taken + // Allows detection of abandoned and recursively captured mutexes + bool lock_taken_; + void AssertFreeAndMarkTaken(); + void AssertTakenAndMarkFree(); +#else + void AssertFreeAndMarkTaken() {} + void AssertTakenAndMarkFree() {} +#endif + + private: + friend class ConditionalVariable; + DISALLOW_COPY_AND_ASSIGN(Lock); +}; + +// This class is used to automatically acquire and release the a lock +class AutoLock { + public: + explicit AutoLock(Lock& lock) + : lock_(lock) { lock_.Ackquire(); } + ~AutoLock() { lock_.Release(); } + private: + Lock& GetLock(){ return lock_; } + Lock& lock_; + + private: + friend class AutoUnlock; + friend class ConditionalVariable; + DISALLOW_COPY_AND_ASSIGN(AutoLock); +}; + +// This class is used to temporarly unlock autolocked lock +class AutoUnlock { + public: + explicit AutoUnlock(AutoLock& lock) + : lock_(lock.GetLock()) { lock_.Release(); } + ~AutoUnlock() { lock_.Ackquire(); } + private: + Lock& lock_; + + private: + DISALLOW_COPY_AND_ASSIGN(AutoUnlock); +}; + +} // sync_primitives + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_LOCK_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/logger.h b/SDL_Core/src/components/Utils/include/Utils/logger.h new file mode 100644 index 000000000..a88c6aa16 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/logger.h @@ -0,0 +1,72 @@ +/** + * \file LOG4CXXLogger.hpp + * \brief Definitions required by logger. + * Stores device information + * + * 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 LOG4CXXLOGGER_HPP_ + #include <errno.h> + #include <string.h> + #include <log4cxx/logger.h> + #include <log4cxx/propertyconfigurator.h> + +namespace log4cxx +{ + #define LOG4CXX_INFO_EXT(logger, logEvent) LOG4CXX_INFO(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + #define LOG4CXX_INFO_STR_EXT(logger, logEvent) LOG4CXX_INFO_STR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + + #define LOG4CXX_TRACE_EXT(logger, logEvent) LOG4CXX_TRACE(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + #define LOG4CXX_TRACE_STR_EXT(logger, logEvent) LOG4CXX_TRACE_STR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + + #define LOG4CXX_DEBUG_EXT(logger, logEvent) LOG4CXX_DEBUG(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + #define LOG4CXX_DEBUG_STR_EXT(logger, logEvent) LOG4CXX_DEBUG_STR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + + #define LOG4CXX_WARN_EXT(logger, logEvent) LOG4CXX_WARN(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + #define LOG4CXX_WARN_STR_EXT(logger, logEvent) LOG4CXX_WARN_STR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + + #define LOG4CXX_ERROR_EXT(logger, logEvent) LOG4CXX_ERROR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + #define LOG4CXX_ERROR_STR_EXT(logger, logEvent) LOG4CXX_ERROR_STR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + + #define LOG4CXX_FATAL_EXT(logger, logEvent) LOG4CXX_FATAL(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + #define LOG4CXX_FATAL_STR_EXT(logger, logEvent) LOG4CXX_FATAL_STR(logger, __PRETTY_FUNCTION__ << ": " << logEvent) + + #define LOG4CXX_TRACE_ENTER(logger) LOG4CXX_TRACE(logger, "ENTER: " << __PRETTY_FUNCTION__ ) + #define LOG4CXX_TRACE_EXIT(logger) LOG4CXX_TRACE(logger, "EXIT: " << __PRETTY_FUNCTION__ ) + + #define LOG4CXX_ERROR_WITH_ERRNO(logger, message) LOG4CXX_ERROR(logger, message << ", error code " << errno << " (" << strerror(errno) << ")") +} + +#define LOG4CXXLOGGER_HPP_ + + +#endif /* LOG4CXXLOGGER_HPP_ */ diff --git a/SDL_Core/src/components/Utils/include/Utils/macro.h b/SDL_Core/src/components/Utils/include/Utils/macro.h new file mode 100644 index 000000000..738f5f4eb --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/macro.h @@ -0,0 +1,77 @@ +// +// 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_MACRO_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_MACRO_H_ + +#include <assert.h> +#include <stdio.h> + +// A macro to disallow the copy constructor and operator= functions +// This should be used in the private: declarations for a class +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// A macro to allow utils::Singleton call derivative constructor and destructor +#define FRIEND_BASE_SINGLETON_CLASS(TypeName) \ + friend class utils::Singleton<TypeName> + +// A macro to allow utils::deleters::Deleter::~Deleter() call class destructor +#define FRIEND_DELETER_DESTRUCTOR(TypeName) \ + friend utils::deleters::Deleter<TypeName>::~Deleter() + +#define DCHECK(condition) \ + if (!(condition)) { \ + printf("\nDCHECK [%s:%d][%s]", __FILE__, __LINE__, __FUNCTION__); \ + printf("[Check failed: " #condition); \ + printf("]\n\n"); \ + assert(false); \ + } + +#define NOTREACHED() DCHECK(false) + +// Allows to perform static check that virtual function from base class is +// actually being overriden if compiler support is available +#if __cplusplus >= 201103L +#define OVERRIDE override +#else +#define OVERRIDE +#endif + +/* +* @brief Calculate size of na array +* @param arr array, which size need to calculate +*/ +#define ARRAYSIZE(arr) sizeof (arr) / sizeof(*arr) + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_MACRO_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/memory_barrier.h b/SDL_Core/src/components/Utils/include/Utils/memory_barrier.h new file mode 100644 index 000000000..9ac935a21 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/memory_barrier.h @@ -0,0 +1,54 @@ +/** + * 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_MEMORY_BARRIER_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_MEMORY_BARRIER_H_ + +#ifdef __QNXNTO__ +#include <sys/cpuinline.h> +#endif + +namespace utils { + +inline void memory_barrier() { +#if defined(__QNXNTO__) + __cpu_membarrier(); +#elif defined(__GNUG__) + __sync_synchronize(); +#else +#warning "memory_barrier() implementation does nothing" +#endif +} + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_MEMORY_BARRIER_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/message_queue.h b/SDL_Core/src/components/Utils/include/Utils/message_queue.h new file mode 100644 index 000000000..e043440d6 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/message_queue.h @@ -0,0 +1,181 @@ +/** + * 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 MESSAGE_QUEUE_CLASS +#define MESSAGE_QUEUE_CLASS + +#include <queue> + +#include "utils/conditional_variable.h" +#include "utils/lock.h" +#include "utils/logger.h" +#include "utils/prioritized_queue.h" + +/** + * \class MessageQueue + * \brief Wrapper for multithreading queue. + */ + +template<typename T, class Q = std::queue<T> > class MessageQueue { + public: + typedef Q Queue; + /** + * \brief Default constructor + */ + MessageQueue(); + + /** + * \brief Destructor + */ + ~MessageQueue(); + + /** + * \brief Returns size of the queue. + * \return Size of the queue. + */ + int32_t size() const; + + /** + * \brief If queue is empty. + * \return Is queue empty. + */ + bool empty() const; + + /** + * \brief Tells if queue is being shut down + */ + bool IsShuttingDown() const; + + /** + * \brief Adds element to the queue. + * \param element Element to be added to the queue.n + */ + void push(const T& element); + + /** + * \brief Removes element from the queue and returns it. + * \return To element of the queue. + */ + T pop(); + + /** + * \brief Conditional wait. + */ + void wait(); + + /** + * \brief Shutdown the queue. + * This leads to waking up everyone waiting on the queue + * Queue being shut down can be drained ( with pop() ) + * But nothing must be added to the queue after it began + * shutting down + */ + void Shutdown(); + private: + + /** + *\brief Queue + */ + Queue queue_; + volatile bool shutting_down_; + /** + *\brief Platform specific syncronisation variable + */ + mutable sync_primitives::Lock queue_lock_; + mutable sync_primitives::ConditionalVariable queue_new_items_; +}; + +template<typename T, class Q> MessageQueue<T, Q>::MessageQueue() + : shutting_down_(false) { +} + +template<typename T, class Q> MessageQueue<T, Q>::~MessageQueue() { + if (!queue_.empty()) { + log4cxx::LoggerPtr logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); + LOG4CXX_ERROR(logger, "Destruction of non-drained queue"); + } +} + +template<typename T, class Q> void MessageQueue<T, Q>::wait() { + sync_primitives::AutoLock auto_lock(queue_lock_); + while (!shutting_down_ && queue_.empty()) { + queue_new_items_.Wait(auto_lock); + } +} + +template<typename T, class Q> int32_t MessageQueue<T, Q>::size() const { + sync_primitives::AutoLock auto_lock(queue_lock_); + return queue_.size(); +} + +template<typename T, class Q> bool MessageQueue<T, Q>::empty() const { + sync_primitives::AutoLock auto_lock(queue_lock_); + return queue_.empty(); +} + +template<typename T, class Q> bool MessageQueue<T, Q>::IsShuttingDown() const { + sync_primitives::AutoLock auto_lock(queue_lock_); + return shutting_down_; +} + +template<typename T, class Q> void MessageQueue<T, Q>::push(const T& element) { + sync_primitives::AutoLock auto_lock(queue_lock_); + if (shutting_down_) { + log4cxx::LoggerPtr logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); + LOG4CXX_ERROR(logger, "Runtime error, pushing into queue" + " that is being shut down"); + } + queue_.push(element); + queue_new_items_.Broadcast(); +} + +template<typename T, class Q> T MessageQueue<T, Q>::pop() { + sync_primitives::AutoLock auto_lock(queue_lock_); + if (queue_.empty()) { + log4cxx::LoggerPtr logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); + LOG4CXX_ERROR(logger, "Runtime error, popping out of empty que"); + } + T result = queue_.front(); + queue_.pop(); + return result; +} + +template<typename T, class Q> void MessageQueue<T, Q>::Shutdown() { + sync_primitives::AutoLock auto_lock(queue_lock_); + shutting_down_ = true; + queue_new_items_.Broadcast(); +} + +#endif // MESSAGE_QUEUE_CLASS diff --git a/SDL_Core/src/components/Utils/include/Utils/prioritized_queue.h b/SDL_Core/src/components/Utils/include/Utils/prioritized_queue.h new file mode 100644 index 000000000..0023c2bdb --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/prioritized_queue.h @@ -0,0 +1,89 @@ +/** + * 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_PRIORITIZED_QUEUE_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_PRIORITIZED_QUEUE_H_ + +#include <queue> +#include <map> +#include <iostream> + +#include "utils/macro.h" + +namespace utils { + +/* + * Template queue class that gives out messages respecting their priority + * Message class must have size_t PriorityOrder() method implemented + */ +template < typename M > +class PrioritizedQueue { + public: + typedef M value_type; + // std::map guarantees it's contents is sorted by key + typedef std::map<size_t, std::queue<value_type> > QueuesMap; + PrioritizedQueue() + : total_size_(0) { + } + // All api mimics usual std queue interface + void push(const value_type& message) { + size_t message_priority = message.PriorityOrder(); + queues_[message_priority].push(message); + ++total_size_; + } + size_t size() const { + return total_size_; + } + bool empty() const { + return queues_.empty(); + } + value_type front() { + DCHECK(!queues_.empty() && !queues_.rbegin()->second.empty()); + return queues_.rbegin()->second.front(); + } + void pop() { + DCHECK(!queues_.empty() && !queues_.rbegin()->second.empty()); + typename QueuesMap::iterator last = --queues_.end(); + last->second.pop(); + --total_size_; + if (last->second.empty()) { + queues_.erase(last); + } + } + private: + QueuesMap queues_; + size_t total_size_; +}; + +} + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_ diff --git a/SDL_Core/src/components/Utils/include/Utils/shared_ptr.h b/SDL_Core/src/components/Utils/include/Utils/shared_ptr.h new file mode 100644 index 000000000..0e06d62c6 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/shared_ptr.h @@ -0,0 +1,342 @@ +/** + * 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_SHARED_PTR_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SHARED_PTR_H_ + +#include <assert.h> +#include <stddef.h> +#include <stdint.h> + +#include "macro.h" +#include "atomic.h" + +namespace utils { +/** + * @brief Shared pointer. + * + * Pointer to an object with reference counting. + * Object will be automatically deallocated when last shared + * pointer is destroyed. + * + * @tparam ObjectType Type of wrapped object. + **/ +template<typename ObjectType> +class SharedPtr { + public: + /** + * @brief Constructor. + * + * Initialize shared pointer with wrapped object. + * Reference counter will be initialized to 1. + * + * @param Object Wrapped object. + **/ + SharedPtr(ObjectType* Object); + + SharedPtr(); + + /** + * @brief Copy constructor. + * + * Initialize shared pointer with another shared pointer. + * Reference counter will be incremented. + * + * @param Other Other shared pointer. + **/ + SharedPtr(const SharedPtr<ObjectType>& Other); + + /** + * @brief Copy constructor. + * + * Initialize shared pointer with another shared pointer. + * Reference counter will be incremented. + * + * @tparam OtherObjectType Type of other object pointer. This + * allows creating a shared pointer to an + * intstance of a base class from a shared + * pointer to an instance of a class + * inherited from this base class. + * If OtherObjectType is not implicitly + * convertible to ObjectType it will + * cause a compile error. + * + * @param Other Other shared pointer. + **/ + template<typename OtherObjectType> + SharedPtr(const SharedPtr<OtherObjectType>& Other); + + /** + * @brief Destructor. + * + * Decrement reference counter and destroy wrapped object + * if reference counter reaches zero. + **/ + ~SharedPtr(void); + + /** + * @brief Assignment operator. + * + * Drop reference to currently referenced object and add + * reference to assigned object. + * + * @param Other Shared pointer to an object + * that must be referenced. + * + * @return Reference to this shared pointer. + **/ + SharedPtr<ObjectType>& operator =(const SharedPtr<ObjectType>& Other); + + bool operator ==(const SharedPtr<ObjectType>& Other) const; + + bool operator< (const SharedPtr<ObjectType>& other) const; + + /** + * @brief Assignment operator. + * + * Drop reference to currently referenced object and add + * reference to assigned object. + * + * @tparam OtherObjectType Type of other object pointer. This + * allows creating a shared pointer to an + * intstance of a base class from a shared + * pointer to an instance of a class + * inherited from this base class. + * If OtherObjectType is not implicitly + * convertible to ObjectType it will + * cause a compile error. + * + * @param Other Shared pointer to an object + * that must be referenced. + * + * @return Reference to this shared pointer. + **/ + template<typename OtherObjectType> + SharedPtr<ObjectType>& operator =(const SharedPtr<OtherObjectType>& Other); + + template<typename OtherObjectType> + static SharedPtr<OtherObjectType> static_pointer_cast( + const SharedPtr<ObjectType>& pointer); + + /** + * @brief Member access operator. + * + * @return Wrapped object. + **/ + ObjectType* operator->(void) const; + + ObjectType& operator*() const; + operator bool() const; + void reset(); + void reset(ObjectType* other); + ObjectType* get() const; + + /** + * @return true if mObject not NULL + */ + bool valid() const; + + private: + void reset_impl(ObjectType* other); + + // TSharedPtr needs access to other TSharedPtr private members + // for shared pointers type casts. + template<typename OtherObjectType> + friend class SharedPtr; + + /** + * @brief Drop reference to wrapped object. + * + * If reference counter reaches zero object and its reference + * counter will be deallocated. + **/ + void dropReference(void); + + /** + * @brief Wrapped object. + **/ + ObjectType* mObject; + + /** + * @brief Pointer to reference counter. + **/ + uint32_t* mReferenceCounter; +}; + +template<typename ObjectType> +inline utils::SharedPtr<ObjectType>::SharedPtr(ObjectType* Object) + : mObject(NULL), + mReferenceCounter(new uint32_t(1)) { + DCHECK(Object != NULL); + mObject = Object; +} + +template<typename ObjectType> +inline utils::SharedPtr<ObjectType>::SharedPtr() + : mObject(0), + mReferenceCounter(0) { +} + +template<typename ObjectType> +inline utils::SharedPtr<ObjectType>::SharedPtr( + const SharedPtr<ObjectType>& Other) + : mObject(0), + mReferenceCounter(0) { + *this = Other; +} + +template<typename ObjectType> +template<typename OtherObjectType> +inline utils::SharedPtr<ObjectType>::SharedPtr( + const SharedPtr<OtherObjectType>& Other) + : mObject(0), + mReferenceCounter(0) { + *this = Other; +} + +template<typename ObjectType> +inline utils::SharedPtr<ObjectType>::~SharedPtr(void) { + dropReference(); +} + +template<typename ObjectType> +inline utils::SharedPtr<ObjectType>& +utils::SharedPtr<ObjectType>::operator=(const SharedPtr<ObjectType>& Other) { + return operator=<ObjectType>(Other); +} + +template<typename ObjectType> +inline bool utils::SharedPtr<ObjectType>::operator ==( + const SharedPtr<ObjectType>& Other) const { + return (mObject == Other.mObject); +} + +template<typename ObjectType> +inline bool utils::SharedPtr<ObjectType>::operator< ( + const SharedPtr<ObjectType>& other) const { + return (mObject < other.mObject); +} + +template<typename ObjectType> +template<typename OtherObjectType> +inline utils::SharedPtr<ObjectType>& +utils::SharedPtr<ObjectType>::operator=( + const SharedPtr<OtherObjectType>& Other) { + dropReference(); + + mObject = Other.mObject; + mReferenceCounter = Other.mReferenceCounter; + + if (0 != mReferenceCounter) { + atomic_post_inc(mReferenceCounter); + } + + return *this; +} + +template<typename ObjectType> +template<typename OtherObjectType> +utils::SharedPtr<OtherObjectType> utils::SharedPtr<ObjectType>::static_pointer_cast(const SharedPtr<ObjectType>& pointer) { + SharedPtr<OtherObjectType> casted_pointer; + casted_pointer.mObject = static_cast<OtherObjectType*>(pointer.mObject); + casted_pointer.mReferenceCounter = pointer.mReferenceCounter; + + if (0 != casted_pointer.mReferenceCounter) { + atomic_post_inc(casted_pointer.mReferenceCounter); + } + + return casted_pointer; +} + +template<typename ObjectType> ObjectType* +utils::SharedPtr<ObjectType>::operator->(void) const { + return mObject; +} + +template<typename ObjectType> ObjectType& +utils::SharedPtr<ObjectType>::operator*() const { + DCHECK(mObject); + return *mObject; +} + +template<typename ObjectType> +utils::SharedPtr<ObjectType>::operator bool() const { + return 0 != mObject; +} + +template<typename ObjectType> void +utils::SharedPtr<ObjectType>::reset() { + reset_impl(0); +} + +template<typename ObjectType> void +utils::SharedPtr<ObjectType>::reset(ObjectType* other) { + DCHECK(other != NULL); + reset_impl(other); +} + +template<typename ObjectType> void +utils::SharedPtr<ObjectType>::reset_impl(ObjectType* other) { + dropReference(); + mObject = other; + mReferenceCounter = new uint32_t(1); +} + +template<typename ObjectType> +inline void SharedPtr<ObjectType>::dropReference(void) { + if (0 != mReferenceCounter) { + if (1 == atomic_post_dec(mReferenceCounter)) { + + delete mObject; + mObject = 0; + + delete mReferenceCounter; + mReferenceCounter = 0; + } + } +} + +template<typename ObjectType> +ObjectType* SharedPtr<ObjectType>::get() const { + return mObject; +} + +template<typename ObjectType> +inline bool SharedPtr<ObjectType>::valid() const { + return (mObject != NULL); +} + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SHARED_PTR_H_ + +// vim: set ts=2 sw=2 et: diff --git a/SDL_Core/src/components/Utils/include/Utils/signals.h b/SDL_Core/src/components/Utils/include/Utils/signals.h new file mode 100644 index 000000000..ad2a2d183 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/signals.h @@ -0,0 +1,44 @@ +/** +* \file signals.h +* \brief Signal (i.e. SIGINT) handling. +* 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_SIGNALS_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SIGNALS_H_ + +namespace utils { +bool SubscribeToTerminateSignal(void (*func)(int32_t p)); +bool ResetSubscribeToTerminateSignal(); +void ForwardSignal(); +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SIGNALS_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/singleton.h b/SDL_Core/src/components/Utils/include/Utils/singleton.h new file mode 100644 index 000000000..35ad50393 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/singleton.h @@ -0,0 +1,179 @@ +/** + * 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_SINGLETON_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SINGLETON_H_ + +#include "lock.h" +#include "memory_barrier.h" +#include "atomic.h" + +namespace utils { + +namespace deleters { + +class DummyDeleter { + public: + void grab(void* pointer) { + } +}; + +template<typename T> +class Deleter { + public: + Deleter() : pointer_(0) { + } + ~Deleter() { + if (pointer_) { + delete pointer_; + } + } + void grab(T* pointer) { + pointer_ = pointer; + } + private: + T* pointer_; +}; + +} // namespace deleters + +template<typename T, class Deleter = deleters::DummyDeleter> +class Singleton { +/** + * @brief Singleton template + * Singleton classes must derive from this template specialized with class itself: + * + * class MySingleton : public Singleton<MySingleton> {...}; + * + * All such classes must declare instance() method as friend + * by adding FRIEND_BASE_SINGLETON_CLASS macro from macro.h to class definition: + * + * FRIEND_BASE_SINGLETON_CLASS(MySingleton); + * + * Instance of this class (if created) can be deleted by Deleter destructor + * which is called after main() (or from exit()) + * This requires T destructor to be accessible for Deleter (e.g. public) + * Deleter template parameter can be specified with any class + * with public default constructor, destructor and method + * void grab(T*); + * However, default Deleter specification does nothing + * + * Also instance can be deleted explicitly by calling destroy() method + * + * Both instance() and destroy() methods are thread safe + * but not thread safety between simultaneous calls + * of instance() and destroy() is cared about + */ + public: +/** + * @brief Returns the singleton of class + */ + static T* instance(); +/** + * @brief Destroys the singleton (if it had been created) + */ + static void destroy(); +/** + * @brief Checks whether the singleton exists + */ + static bool exists(); + + private: + + static T** instance_pointer(); + static Deleter* deleter(); +}; + +template<typename T, class Deleter> +T* Singleton<T, Deleter>::instance() { + static sync_primitives::Lock lock; + + T* local_instance; + atomic_pointer_assign(local_instance, *instance_pointer()); + memory_barrier(); + + if (!local_instance) { + lock.Ackquire(); + local_instance = *instance_pointer(); + if (!local_instance) { + local_instance = new T(); + memory_barrier(); + atomic_pointer_assign(*instance_pointer(), local_instance); + deleter()->grab(local_instance); + } + lock.Release(); + } + + return local_instance; +} + +template<typename T, class Deleter> +void Singleton<T, Deleter>::destroy() { + static sync_primitives::Lock lock; + + T* local_instance; + atomic_pointer_assign(local_instance, *instance_pointer()); + memory_barrier(); + + if (local_instance) { + lock.Ackquire(); + local_instance = *instance_pointer(); + if (local_instance) { + atomic_pointer_assign(*instance_pointer(), 0); + memory_barrier(); + delete local_instance; + deleter()->grab(0); + } + lock.Release(); + } +} + +template<typename T, class Deleter> +bool Singleton<T, Deleter>::exists() { + return *instance_pointer() != 0; +} + +template<typename T, class Deleter> +T** Singleton<T, Deleter>::instance_pointer() { + static T* instance = 0; + return &instance; +} + +template<typename T, class Deleter> +Deleter* Singleton<T, Deleter>::deleter() { + static Deleter deleter; + return &deleter; +} + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SINGLETON_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/stl_utils.h b/SDL_Core/src/components/Utils/include/Utils/stl_utils.h new file mode 100644 index 000000000..f525c6429 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/stl_utils.h @@ -0,0 +1,81 @@ +/** + * 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_STL_UTILS_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_STL_UTILS_H_ + +#include "utils/macro.h" + +namespace utils { + +/* + * Utility class that automatically deletes STL collection of + * freestore objects + */ +template<class T> +class StlCollectionDeleter { + public: + typedef T Collection; + StlCollectionDeleter(T* collection): collection_(collection) { + DCHECK(collection_); + } + ~StlCollectionDeleter() { + for (typename Collection::iterator i = collection_->begin(), + end = collection_->end(); + i != end; ++i) { + delete *i; + } + } + private: + Collection* collection_; +}; + +template<class T> +class StlMapDeleter { + public: + typedef T Collection; + StlMapDeleter(T* collection): collection_(collection) { + DCHECK(collection_); + } + ~StlMapDeleter() { + for (typename Collection::iterator i = collection_->begin(), + end = collection_->end(); + i != end; ++i) { + delete i->second; + } + } + private: + Collection* collection_; +}; + +} // namespace utils + +#endif /* SRC_COMPONENTS_UTILS_INCLUDE_UTILS_STL_UTILS_H_ */ diff --git a/SDL_Core/src/components/Utils/include/Utils/threads/message_loop_thread.h b/SDL_Core/src/components/Utils/include/Utils/threads/message_loop_thread.h new file mode 100644 index 000000000..b2ff91f7b --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/threads/message_loop_thread.h @@ -0,0 +1,136 @@ +#ifndef SRC_COMPONENTS_UTILS_INCLUDE_MESSAGE_LOOP_THREAD_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_MESSAGE_LOOP_THREAD_H_ + +#include <string> +#include <queue> + +#include "utils/logger.h" +#include "utils/macro.h" +#include "utils/message_queue.h" +#include "utils/threads/thread.h" + +namespace threads { + +/* + * Class that handles a thread which sole purpose is to pump messages pushed + * to it's queue. To handle messages someone, Handler must be implemented and + * passed to MessageLoopThread constructor. + */ +template < class Q > +class MessageLoopThread { + public: + typedef Q Queue; + typedef typename Queue::value_type Message; + /* + * Handler interface. It is called from a thread that is + * owned by MessageLoopThread so make sure is only accesses + * thread-safe data + */ + struct Handler { + /* + * Method called by MessageLoopThread to process single message + * from it's queue. After calling this method message is discarded. + */ + virtual void Handle(const Message& message) = 0; + }; + + /* + * Constructs new MessageLoopThread. Must be named to aid debugging. + */ + MessageLoopThread(const std::string& name, + Handler* handler, + const ThreadOptions& thread_opts = ThreadOptions()); + ~MessageLoopThread(); + + // Places a message to the therad's queue. Thread-safe. + void PostMessage(const Message& message); + private: + + /* + * Implementation of ThreadDelegate that actually pumps the queue and is + * able to correctly shut it down + */ + struct LoopThreadDelegate : public threads::ThreadDelegate { + LoopThreadDelegate(MessageQueue<Message, Queue>* message_queue, + Handler* handler); + + // threads::ThreadDelegate overrides + virtual void threadMain() OVERRIDE; + virtual bool exitThreadMain() OVERRIDE; + private: + // Handle all messages that are in the queue until it is empty + void DrainQue(); + private: + // Handler that processes messages + Handler& handler_; + // Message queue that is actually owned by MessageLoopThread + MessageQueue<Message, Queue>& message_queue_; + }; + private: + MessageQueue<Message, Queue> message_queue_; + threads::Thread thread_; +}; + +///////// Implementation + +template<class Q> +MessageLoopThread<Q>::MessageLoopThread(const std::string& name, + Handler* handler, + const ThreadOptions& thread_opts) + : thread_(name.c_str(), new LoopThreadDelegate(&message_queue_, handler)) { + bool started = thread_.startWithOptions(thread_opts); + if (!started) { + log4cxx::LoggerPtr logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); + LOG4CXX_ERROR(logger, "Failed to start thread " << name); + } +} + +template<class Q> +MessageLoopThread<Q>::~MessageLoopThread() { + // this will join us with the thread while it drains message queue + thread_.stop(); +} + +template <class Q> +void MessageLoopThread<Q>::PostMessage(const Message& message) { + message_queue_.push(message); +} + +////////// +template<class Q> +MessageLoopThread<Q>::LoopThreadDelegate::LoopThreadDelegate( + MessageQueue<Message, Queue>* message_queue, Handler* handler) + : handler_(*handler), + message_queue_(*message_queue) { + DCHECK(handler != NULL); + DCHECK(message_queue != NULL); +} + +template<class Q> +void MessageLoopThread<Q>::LoopThreadDelegate::threadMain() { + while(!message_queue_.IsShuttingDown()){ + DrainQue(); + message_queue_.wait(); + } + // Process leftover messages + DrainQue(); +} + +template<class Q> +bool MessageLoopThread<Q>::LoopThreadDelegate::exitThreadMain() { + message_queue_.Shutdown(); + // Prevent canceling thread until queue is drained + return true; +} + +template<class Q> +void MessageLoopThread<Q>::LoopThreadDelegate::DrainQue() { + while(!message_queue_.empty()) { + handler_.Handle(message_queue_.pop()); + } +} + +} // namespace utils + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_MESSAGE_LOOP_THREAD_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/threads/thread.h b/SDL_Core/src/components/Utils/include/Utils/threads/thread.h new file mode 100644 index 000000000..bbe0acde3 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/threads/thread.h @@ -0,0 +1,237 @@ +/** + * \file thread.h + * \brief + * + * 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_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_H_ + +#if defined(OS_POSIX) +#include <pthread.h> +#endif + +#include <ostream> +#include <string> + +#include "utils/macro.h" +#include "utils/logger.h" +#include "utils/threads/thread_delegate.h" +#include "utils/threads/thread_options.h" + +namespace threads { + +namespace impl { +#if defined(OS_POSIX) +typedef pthread_t PlatformThreadHandle; +#else +#error Please implement thread for your OS +#endif +} + +/** + * Non platform specific thread abstraction that establishes a + * threads::ThreadDelegate on a new thread. + * + * ThreadDelegate example: + * class TestThread : public threads::ThreadDelegate { + * public: + * void threadMain() { + * printf("Hello, thread!\n"); + * sleep(2); + * } + * }; + * + * Example usage: + * threads::Thread thread("test thread", new TestThread()); + * thread.startWithOptions( + * threads::ThreadOptions(threads::Thread::kMinStackSize)); + * printf("join!\n"); + * thread.join(); + * printf("ok!\n"); + */ +class Thread { + public: + + /* + * Class that represents unique in-process thread identifier + * due to restriction of pthread API it only allows checks + * for equality to different thread id and no ordering. + * + * ostream<< operator is provided for this class which + * outputs thread name associated to an identifier. + */ + class Id { + public: + explicit Id(const impl::PlatformThreadHandle& id): id_(id) {} + bool operator==(const Id that) const; + private: + impl::PlatformThreadHandle id_; + friend class Thread; + }; + + // Get unique ID of currently executing thread + static Id CurrentId(); + + // Get name associated with thread identified by thread_id + static std::string NameFromId(Id thread_id); + + // Give thread thread_id a name, helpful for debugging + static void SetNameForId(Id thread_id, const std::string& name); + + /** + * Ctor. + * @param name - display string to identify the thread. + * @param delegate - thread procedure delegate. Look for + * 'threads/thread_delegate.h' for details. + * NOTE: delegate will be deleted by destructor. + */ + Thread(const char* name, ThreadDelegate* delegate); + + /** + * Dtor. + */ + virtual ~Thread(); + + /** + * Starts the thread. + * @return true if the thread was successfully started. + */ + bool start(); + + /** + * Starts the thread. Behaves exactly like Start in addition to + * allow to override the default options. + * @param options - thread options. Look for 'threads/thread_options.h' + * for details. + * @return true if the thread was successfully started. + */ + bool startWithOptions(const ThreadOptions& options); + + /** + * Signals the thread to exit and returns once the thread has exited. + * After this method returns, the Thread object is completely reset and may + * be used as if it were newly constructed (i.e., Start may be called again). + * + * Stop may be called multiple times and is simply ignored if the thread is + * already stopped. + */ + void stop(); + + /** + * Joins with a thread created via the Create function. + * This function blocks the caller until the designated thread exits. + * This will invalidate |thread_handle|. + */ + void join(); + + /** + * Get thread name. + * @return thread name + */ + const std::string &thread_name() { + return name_; + } + + /** + * Returns true if the thread has been started, and not yet stopped. + * When a thread is running, the thread_id_ is non-zero. + * @return true if the thread has been started, and not yet stopped. + */ + bool is_running() const { + return isThreadRunning_; + } + + /** + * Is thread joinable? + * @return - Returns true if the thread is joinable. + */ + bool is_joinable() const { + return thread_options_.is_joinable(); + } + + /** + * Thread stack size + * @return thread stack size + */ + size_t stack_size() const { + return thread_options_.stack_size(); + } + + /** + * The native thread handle. + * @return thread handle. + */ + impl::PlatformThreadHandle thread_handle() const { + return thread_handle_; + } + + /** + * Thread id. + * @return return thread id. + */ + Id thread_id() const { + return Id(thread_handle()); + } + + /** + * Thread options. + * @return thread options. + */ + const ThreadOptions& thread_options() const { + return thread_options_; + } + + /** + * Minimum size of thread stack for specific platform. + */ + static size_t kMinStackSize; + + protected: + std::string name_; + ThreadDelegate* delegate_; + impl::PlatformThreadHandle thread_handle_; + ThreadOptions thread_options_; + bool isThreadRunning_; + + static log4cxx::LoggerPtr logger_; + + private: + DISALLOW_COPY_AND_ASSIGN(Thread); +}; + +inline bool operator!= (Thread::Id left, Thread::Id right) {return !(left == right); } +std::ostream& operator<<(std::ostream& os, Thread::Id thread_id); + +} // namespace threads + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/threads/thread_delegate.h b/SDL_Core/src/components/Utils/include/Utils/threads/thread_delegate.h new file mode 100644 index 000000000..963eb3bf8 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/threads/thread_delegate.h @@ -0,0 +1,71 @@ +/** + * \file thread_delegate.h + * \brief + * + * 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_DELEGATE_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_DELEGATE_H_ + +#include <pthread.h> + +namespace threads { + +/** + * Thread procedure interface. + * Look for "threads/thread.h" for example + */ +class ThreadDelegate { + public: + /** + * Dtor. + */ + virtual ~ThreadDelegate() { + } + + /** + * Thread procedure. + */ + virtual void threadMain() = 0; + + /** + * Should be called to free all resources allocated in threadMain + * and exiting threadMain + */ + virtual bool exitThreadMain() { + return false; + } +}; + +} // namespace threads + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_DELEGATE_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/threads/thread_manager.h b/SDL_Core/src/components/Utils/include/Utils/threads/thread_manager.h new file mode 100644 index 000000000..03330170e --- /dev/null +++ b/SDL_Core/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/SDL_Core/src/components/Utils/include/Utils/threads/thread_options.h b/SDL_Core/src/components/Utils/include/Utils/threads/thread_options.h new file mode 100644 index 000000000..bdeaa367f --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/threads/thread_options.h @@ -0,0 +1,107 @@ +/** + * \file thread_options.h + * \brief + * + * 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_OPTIONS_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_OPTIONS_H_ + +namespace threads { + +/** + * @breif Startup options for thread. + * Look for "threads/thread.h" for example + */ +class ThreadOptions { + public: + /** + * Ctor + * @param stack_size - thread stack size. If stack size less than + * threads::Thread::kMinStackSize the default value is used. + * 0 - default stack size for current platform. + * @param is_joinable - is thread joinable? + */ + explicit ThreadOptions(size_t stack_size = 0, bool is_joinable = true) + : stack_size_(stack_size), + is_joinable_(is_joinable) { + } + + /** + * Dtor. + */ + virtual ~ThreadOptions() { + } + + /** + * Copy ctor. + * @param options - new options. + */ + ThreadOptions(const ThreadOptions& options) { + *this = options; + } + + /** + * Assign operator. + * @param options - new options. + * @return new options. + */ + ThreadOptions& operator=(const ThreadOptions& options ) { + stack_size_ = options.stack_size(); + is_joinable_ = options.is_joinable(); + return *this; + } + + /** + * Stack size. + * @return Stack size for thread. + */ + size_t stack_size() const { + return stack_size_; + } + + /** + * Is thread joinable? + * @return - Returns true if the thread is joinable. + */ + bool is_joinable() const { + return is_joinable_; + } + + protected: + size_t stack_size_; + bool is_joinable_; +}; + +} // namespace threads + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_THREADS_THREAD_OPTIONS_H_ diff --git a/SDL_Core/src/components/Utils/include/Utils/threads/thread_validator.h b/SDL_Core/src/components/Utils/include/Utils/threads/thread_validator.h new file mode 100644 index 000000000..def1994b7 --- /dev/null +++ b/SDL_Core/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_ diff --git a/SDL_Core/src/components/Utils/include/Utils/timer_thread.h b/SDL_Core/src/components/Utils/include/Utils/timer_thread.h new file mode 100644 index 000000000..0da5616e7 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/Utils/timer_thread.h @@ -0,0 +1,336 @@ +/** + * 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_TIMER_THREAD +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_TIMER_THREAD + +#include <time.h> + +#include "utils/conditional_variable.h" +#include "utils/lock.h" +#include "utils/logger.h" +#include "utils/macro.h" +#include "utils/timer_thread.h" +#include "utils/threads/thread.h" +#include "utils/threads/thread_delegate.h" + +namespace timer { + +class TimerDelegate; + +/* + * The TimerThread class provide possibility to run timer in a separate thread. + * The client should specify callee and const callback function. + * Example usage: + * + * Create timer in mobile request + * + * timer::TimerThread<MobileRequest> timer(this, &MobileRequest::onTimeOut); + * timer.start(10); + * + * some actions + * + * To stop timer call timer.stop(); + * + */ +template <class T> +class TimerThread { + public: + + friend class TimerDelegate; + friend class TimerLooperDelegate; + + /* + * @brief Default constructor + * + * @param callee A class that use timer + * @param f CallBackFunction which will be called on timeout + * Atantion! "f()" will be called not in main thread but in timer thread + * Never use stop() and start() methods inside f + * @param is_looper Define this timer as looer, + * if true, TimerThread will call "f()" function every time out + * until stop() + */ + TimerThread(T* callee , void (T::*f)(),bool is_looper = false); + + /* + * @brief Destructor + */ + virtual ~TimerThread(); + + /* + * @brief Starts timer for specified timeout. + * Previously started timeout will be set to new value. + * On timeout TimerThread::onTimeOut interface will be called. + * Must not be used in callback function! + * + * @param timeout_seconds Timeout in seconds to be set + */ + virtual void start(uint32_t timeout_seconds); + + /* + * @brief Stops timer execution + * Must not be used in callback function! + */ + virtual void stop(); + + protected: + + /* + * @brief Interface called by delegator on timeout + */ + void onTimeOut() const; + + private: + + /** + * @brief Delegate release timer, will call callback function one time + */ + class TimerDelegate : public threads::ThreadDelegate { + public: + + /* + * @brief Default constructor + * + * @param timer_thread The Timer_thread pointer + * @param timeout Timeout to be set + */ + TimerDelegate(const TimerThread* timer_thread); + + /* + * @brief Destructor + */ + virtual ~TimerDelegate(); + + /* + * @brief Thread main function. + */ + virtual void threadMain(); + + /* + * @brief Called by thread::thread to free all allocated resources. + */ + virtual bool exitThreadMain(); + + /* + * @brief Restart timer + * + * @param timeout_seconds New timeout to be set + */ + virtual void setTimeOut(uint32_t timeout_seconds); + + protected: + const TimerThread* timer_thread_; + uint32_t timeout_seconds_; + sync_primitives::Lock state_lock_; + sync_primitives::ConditionalVariable termination_condition_; + volatile bool stop_flag_; + + private: + DISALLOW_COPY_AND_ASSIGN(TimerDelegate); + }; + + + /** + * @brief Delegate release looper timer. + * Will call delegate every timeot function while stop() + * won't be called + */ + class TimerLooperDelegate : public TimerDelegate { + public: + + /* + * @brief Default constructor + * + * @param timer_thread The Timer_thread pointer + * @param timeout Timeout to be set + */ + TimerLooperDelegate(const TimerThread* timer_thread); + + /* + * @brief Thread main function. + */ + virtual void threadMain(); + private: + DISALLOW_COPY_AND_ASSIGN(TimerLooperDelegate); + }; + void (T::*callback_)(); + T* callee_; + TimerDelegate* delegate_; + threads::Thread* thread_; + mutable bool is_running_; + + DISALLOW_COPY_AND_ASSIGN(TimerThread); +}; + +template <class T> +TimerThread<T>::TimerThread(T* callee, void (T::*f)(), bool is_looper) + : callback_(f), + callee_(callee), + delegate_(NULL), + thread_(NULL), + is_running_(false) { + if (is_looper) { + delegate_ = new TimerLooperDelegate(this); + } else { + delegate_ = new TimerDelegate(this); + } + + if (delegate_) { + thread_ = new threads::Thread("TimerThread", delegate_); + } +} + +template <class T> +TimerThread<T>::~TimerThread() { + if (is_running_) { + stop(); + } + callback_ = NULL; + callee_ = NULL; + delete thread_; + // delegate_ will be deleted by thread_ + thread_ = NULL; + delegate_ = NULL; +} + +template <class T> +void TimerThread<T>::start(uint32_t timeout_seconds) { + if (is_running_) { + stop(); + } + + delegate_->setTimeOut(timeout_seconds); + if (delegate_ && thread_) { + is_running_ = true; + const size_t kStackSize = 16384; + thread_->startWithOptions(threads::ThreadOptions(kStackSize)); + } +} + +template <class T> +void TimerThread<T>::stop() { + if (delegate_ && thread_) { + thread_->stop(); + is_running_ = false; + } +} + +template <class T> +void TimerThread<T>::onTimeOut() const { + if (callee_ && callback_) { + (callee_->*callback_)(); + is_running_ = false; + } +} + +template <class T> +TimerThread<T>::TimerDelegate::TimerDelegate(const TimerThread* timer_thread) + : timer_thread_(timer_thread), + timeout_seconds_(0), + stop_flag_(false) { + DCHECK(timer_thread_); +} + +template <class T> +TimerThread<T>::TimerLooperDelegate::TimerLooperDelegate(const TimerThread* timer_thread) + : TimerDelegate(timer_thread) { +} + +template <class T> +TimerThread<T>::TimerDelegate::~TimerDelegate() { + timer_thread_ = NULL; +} + +template <class T> +void TimerThread<T>::TimerDelegate::threadMain() { + using sync_primitives::ConditionalVariable; + sync_primitives::AutoLock auto_lock(state_lock_); + const time_t end_time = time(NULL) + timeout_seconds_; + int32_t wait_seconds_left = int32_t(difftime(end_time, time(NULL))); + while (!stop_flag_) { + // Sleep + ConditionalVariable::WaitStatus wait_status = + termination_condition_.WaitFor(auto_lock, wait_seconds_left * 1000); + wait_seconds_left = int32_t(difftime(end_time, time(NULL))); + // Quit sleeping or continue sleeping in case of spurious wake up + if (ConditionalVariable::kTimeout == wait_status || + wait_seconds_left <= 0) { + break; + } + } + if (!stop_flag_) { + timer_thread_->onTimeOut(); + } + stop_flag_ = false; +} + +template <class T> +void TimerThread<T>::TimerLooperDelegate::threadMain() { + using sync_primitives::ConditionalVariable; + sync_primitives::AutoLock auto_lock(TimerDelegate::state_lock_); + time_t end_time = time(NULL) + TimerDelegate::timeout_seconds_; + int32_t wait_seconds_left = int32_t(difftime(end_time, time(NULL))); + while (!TimerDelegate::stop_flag_) { + // Sleep + ConditionalVariable::WaitStatus wait_status = + TimerDelegate::termination_condition_.WaitFor(auto_lock, wait_seconds_left * 1000); + wait_seconds_left = int32_t(difftime(end_time, time(NULL))); + // Quit sleeping or continue sleeping in case of spurious wake up + if (ConditionalVariable::kTimeout == wait_status || + wait_seconds_left <= 0) { + TimerDelegate::timer_thread_->onTimeOut(); + end_time = time(NULL) + TimerDelegate::timeout_seconds_; + } + } + TimerDelegate::stop_flag_ = false; +} + + +template <class T> +bool TimerThread<T>::TimerDelegate::exitThreadMain() { + { + sync_primitives::AutoLock auto_lock(state_lock_); + stop_flag_ = true; + } + termination_condition_.NotifyOne(); + return true; +} + +template <class T> +void TimerThread<T>::TimerDelegate::setTimeOut(uint32_t timeout_seconds) { + timeout_seconds_ = timeout_seconds; +} + +} // namespace timer + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_TIMER_THREAD diff --git a/SDL_Core/src/components/Utils/include/utils/atomic.h b/SDL_Core/src/components/Utils/include/utils/atomic.h new file mode 100644 index 000000000..bf5b4baf8 --- /dev/null +++ b/SDL_Core/src/components/Utils/include/utils/atomic.h @@ -0,0 +1,69 @@ +/** + * 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. +*/ + +#ifdef __QNXNTO__ +#include <atomic.h> +#endif + +#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_ATOMIC_H_ +#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_ATOMIC_H_ + +#if defined(__QNXNTO__) +#define atomic_post_inc(ptr) atomic_add_value((ptr), 1) +#elif defined(__GNUG__) +#define atomic_post_inc(ptr) __sync_fetch_and_add((ptr), 1) +#else +#warning "atomic_post_inc() implementation is not atomic" +#define atomic_post_inc(ptr) (*(ptr))++ +#endif + +#if defined(__QNXNTO__) +#define atomic_post_dec(ptr) atomic_sub_value((ptr), 1) +#elif defined(__GNUG__) +#define atomic_post_dec(ptr) __sync_fetch_and_sub((ptr), 1) +#else +#warning "atomic_post_dec() implementation is not atomic" +#define atomic_post_dec(ptr) (*(ptr))-- +#endif + +#if defined(_QNXNTO__) +// on QNX pointer assignment is believed to be atomic +#define atomic_pointer_assign(dst, src) (dst) = (src) +#elif defined(__GNUG__) +// with g++ pointer assignment is believed to be atomic +#define atomic_pointer_assign(dst, src) (dst) = (src) +#else +#warning atomic_pointer_assign() implementation may be non-atomic +#define atomic_pointer_assign(dst, src) (dst) = (src) +#endif + +#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_ATOMIC_H_ diff --git a/SDL_Core/src/components/Utils/src/WorkWithOS.cpp b/SDL_Core/src/components/Utils/src/WorkWithOS.cpp deleted file mode 100644 index 46995fcd4..000000000 --- a/SDL_Core/src/components/Utils/src/WorkWithOS.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/** -* \file WorkWithOS.cpp -* \brief Implementation of general functions for work with OS. -*/ - -#include <iostream> -#include <fstream> -#include <cstddef> -#include <algorithm> -#include <string> -#include <sstream> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <dirent.h> -#include <unistd.h> -#include "Utils/WorkWithOS.h" - -unsigned long int WorkWithOS::getAvailableSpace() -{ - char currentAppPath[256]; - memset((void*)currentAppPath, 0, 256); - getcwd(currentAppPath, 255); - - struct statvfs fsInfo; - memset((void*)&fsInfo, 0, sizeof(fsInfo)); - statvfs(currentAppPath, &fsInfo); - return fsInfo.f_bsize * fsInfo.f_bfree; -} - -std::string WorkWithOS::getFullPath(const std::string & fileName) -{ - char currentAppPath[FILENAME_MAX]; - memset(currentAppPath, 0, FILENAME_MAX); - getcwd(currentAppPath, FILENAME_MAX); - - char path[FILENAME_MAX]; - memset(path, 0, FILENAME_MAX); - snprintf(path, FILENAME_MAX - 1, "%s/%s" - , currentAppPath, fileName.c_str()); - return std::string(path); -} - -std::string WorkWithOS::createDirectory(const std::string & directoryName) -{ - if (!checkIfDirectoryExists(directoryName)) - { - mkdir(directoryName.c_str(), S_IRWXU); - } - - return directoryName; -} - -bool WorkWithOS::checkIfDirectoryExists(const std::string & directoryName) -{ - struct stat status; - memset(&status, 0, sizeof(status)); - - if (-1 == stat(directoryName.c_str(), &status) - || !S_ISDIR(status.st_mode)) - { - return false; - } - - return true; -} - -bool WorkWithOS::checkIfFileExists(const std::string & fileName) -{ - struct stat status; - memset(&status, 0, sizeof(status)); - - if (-1 == stat(fileName.c_str(), &status)) - { - return false; - } - return true; -} - -bool WorkWithOS::createFileAndWrite(const std::string & fileName, - const std::vector<unsigned char>& fileData) -{ - std::ofstream file(fileName.c_str(), std::ios_base::binary); - if (file.is_open()) - { - for (int i = 0; i < fileData.size(); ++i) - { - file << fileData[i]; - } - file.close(); - return true; - } - return false; -} - -bool WorkWithOS::deleteFile(const std::string & fileName) -{ - if (checkIfFileExists(fileName)) - { - return !remove(fileName.c_str()); - } - return false; -} - -std::vector<std::string> WorkWithOS::listFilesInDirectory( - const std::string & directoryName) -{ - std::vector<std::string> listFiles; - if (!checkIfDirectoryExists(directoryName)) - { - return listFiles; - } - - DIR * directory = NULL; - struct dirent* dirElement = NULL; - directory = opendir(directoryName.c_str()); - if ( NULL != directory ) - { - while( dirElement = readdir(directory) ) - { - if (0 == strcmp(dirElement->d_name, "..") - || 0 == strcmp(dirElement->d_name, ".")) - { - continue; - } - listFiles.push_back(std::string(dirElement->d_name)); - } - closedir(directory); - } - - return listFiles; -} - -bool WorkWithOS::readFileAsBinary(const std::string& fileName, std::vector<unsigned char>& v) -{ - if (!checkIfFileExists(fileName)) - return false; - - std::ifstream file(fileName.c_str(), std::ios_base::binary); - std::ostringstream ss; - ss << file.rdbuf(); - const std::string& s = ss.str(); - - v.resize(s.length()); - std::copy(s.begin(), s.end(), v.begin()); - return true; -} diff --git a/SDL_Core/src/components/Utils/src/back_trace.cc b/SDL_Core/src/components/Utils/src/back_trace.cc new file mode 100644 index 000000000..23b1b4d1e --- /dev/null +++ b/SDL_Core/src/components/Utils/src/back_trace.cc @@ -0,0 +1,107 @@ +/** + * 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. + */ + +#include "utils/back_trace.h" + +#include <algorithm> +#include <vector> +#include <sstream> + +#include <cxxabi.h> +#include <execinfo.h> + +#include "utils/macro.h" + +using std::ostream; +using std::string; +using std::vector; +using threads::Thread; + +namespace utils { + +namespace { +string demangle(const char* symbol) { + char temp[2048]; + if (1 == sscanf(symbol, "%*[^(]%*[^_]%2047[^)+]", temp)) { + size_t size; + int32_t status; + char* demangled = abi::__cxa_demangle(temp, NULL, &size, &status); + if (demangled != NULL) { + string result(demangled); + free(demangled); + return result; + } + } + return symbol; +} +} + +Backtrace::Backtrace(int32_t count, int32_t skip_top) + : thread_id_(threads::Thread::CurrentId()) { + int32_t skip = skip_top + 1; // Skip this constructor + vector<void*> full_trace (count + skip); + int32_t captured = backtrace(&full_trace.front(), count + skip); + int32_t first_call = std::min(captured, skip); + int32_t last_call = std::min(first_call + count, captured); + backtrace_.assign(full_trace.begin() + first_call, full_trace.begin() + last_call); +} + +Backtrace::~Backtrace() { +} + +vector<string> Backtrace::CallStack() const { + vector<string> callstack; + callstack.reserve(backtrace_.size()); + char** mangled = backtrace_symbols(&backtrace_.front(), backtrace_.size()); + for (size_t i = 0; i != backtrace_.size(); ++i) { + callstack.push_back(demangle(mangled[i])); + } + free(mangled); + return callstack; +} + +Thread::Id Backtrace::ThreadId() const { + return thread_id_; +} + +ostream& operator<< (ostream& os, const Backtrace& bt) { + const vector<string> symbols = bt.CallStack(); + os<<"Stack trace ("<<bt.ThreadId()<<")\n"; + if (symbols.empty()) { + os<<"Not available"<<std::endl; + } else for (size_t i = 0; i < symbols.size(); ++i) { + os<<symbols[i]<<std::endl; + } + return os; +} + +} // namespace utils diff --git a/SDL_Core/src/components/Utils/src/bitstream.cc b/SDL_Core/src/components/Utils/src/bitstream.cc new file mode 100644 index 000000000..94ee5f8a1 --- /dev/null +++ b/SDL_Core/src/components/Utils/src/bitstream.cc @@ -0,0 +1,129 @@ +/** + * 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. + */ +#include "utils/bitstream.h" + +namespace utils { + +BitStream::BitStream(uint8_t* bytes, size_t bytes_count) + : bytes_(bytes), + bytes_count_(bytes_count), + byte_offset_(0), + bit_offset_(0), + bad_(false) { +} + +BitStream::~BitStream() { +} + +size_t BitStream::FullBytesLeft() { + size_t left = bytes_count_ - byte_offset_; + if (bit_offset_ != 0) + left -= 1; + return left; +} + +size_t BitStream::BitsLeft() { + return (bytes_count_ - byte_offset_) * CHAR_BIT - bit_offset_; +} + +void BitStream::ExtractBytes(void* buffer, size_t length) { + DCHECK(length == 0 || buffer != NULL); + if (IsGood()) { + if (bit_offset_ != 0 || // bytes can be extracted only when + FullBytesLeft() < length) { // stream is byte-aligned + MarkBad(); + return; + } + } + memcpy(buffer, &bytes_[byte_offset_], length); + byte_offset_ += length; +} + +void Extract(BitStream* bs, uint8_t* val) { + DCHECK(bs && val); + if (*bs) { + bs->Extract(*val); + } +} + +void Extract(BitStream* bs, uint8_t* val, size_t bits) { + DCHECK(bs && val); + if (*bs) { + bs->ExtractBits(*val, bits); + } +} + +void Extract(BitStream* bs, uint32_t* val) { + DCHECK(bs && val); + if (*bs) { + bs->Extract(*val); + } +} + +void Extract(BitStream* bs, uint32_t* val, size_t bits) { + DCHECK(bs && val); + if (*bs) { + bs->ExtractBits(*val, bits); + } +} + +void Extract(BitStream* bs, std::string* str, size_t length) { + DCHECK(bs && str); + if (*bs) { + // Prevent memory over-allocation + if (bs->FullBytesLeft() < length) { + bs->MarkBad(); + return; + } + str->resize(length+1); + void* stringdata = &(*str)[0]; + bs->ExtractBytes(stringdata, length); + str->resize(length); + } +} + +void Extract(BitStream* bs, std::vector<uint8_t>* data, size_t length) { + DCHECK(bs && data); + if (*bs) { + // Prevent memory over-allocation + if (bs->FullBytesLeft() < length) { + bs->MarkBad(); + return; + } + data->resize(length); + void* dataptr = &data->front(); + bs->ExtractBytes(dataptr, length); + } +} + +} // namespace utils + diff --git a/SDL_Core/src/components/Utils/src/conditional_variable_posix.cc b/SDL_Core/src/components/Utils/src/conditional_variable_posix.cc new file mode 100644 index 000000000..46b31ee7c --- /dev/null +++ b/SDL_Core/src/components/Utils/src/conditional_variable_posix.cc @@ -0,0 +1,134 @@ +/** + * 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. + */ +#include "utils/conditional_variable.h" + +#include <errno.h> +#include <time.h> + +#include "utils/lock.h" +#include "utils/logger.h" + +namespace { +log4cxx::LoggerPtr g_logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); + +const long kNanosecondsPerSecond = 1000000000; +const long kMillisecondsPerSecond = 1000; +const long kNanosecondsPerMillisecond = 1000000; +} + +namespace sync_primitives { + +ConditionalVariable::ConditionalVariable() { + pthread_condattr_t attrs; + int32_t initialized = pthread_condattr_init(&attrs); + if (initialized != 0) + LOG4CXX_ERROR(g_logger, "Failed to initialize " + "conditional variable attributes"); + pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC); + initialized = pthread_cond_init(&cond_var_, &attrs); + if (initialized != 0) + LOG4CXX_ERROR(g_logger, "Failed to initialize " + "conditional variable"); + int32_t rv = pthread_condattr_destroy(&attrs); + if (rv != 0) + LOG4CXX_ERROR(g_logger, "Failed to destroy " + "conditional variable attributes"); +} + +ConditionalVariable::~ConditionalVariable() { + pthread_cond_destroy(&cond_var_); + +} + +void ConditionalVariable::NotifyOne() { + int32_t signaled = pthread_cond_signal(&cond_var_); + if (signaled != 0) + LOG4CXX_ERROR(g_logger, "Failed to signal conditional variable"); + +} + +void ConditionalVariable::Broadcast() { + int32_t signaled = pthread_cond_broadcast(&cond_var_); + if (signaled != 0) + LOG4CXX_ERROR(g_logger, "Failed to broadcast conditional variable"); + +} + +void ConditionalVariable::Wait(AutoLock& auto_lock) { + Lock& lock = auto_lock.GetLock(); + lock.AssertTakenAndMarkFree(); + int32_t wait_status = pthread_cond_wait(&cond_var_, + &lock.mutex_); + lock.AssertFreeAndMarkTaken(); + if (wait_status != 0) + LOG4CXX_ERROR(g_logger, "Failed to wait for conditional variable"); +} + +ConditionalVariable::WaitStatus ConditionalVariable::WaitFor( + AutoLock& auto_lock, int32_t milliseconds){ + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + timespec wait_interval; + wait_interval.tv_sec = now.tv_sec + + (milliseconds / kMillisecondsPerSecond); + wait_interval.tv_nsec = now.tv_nsec + + (milliseconds % kMillisecondsPerSecond) * kNanosecondsPerMillisecond; + wait_interval.tv_sec += wait_interval.tv_nsec / kNanosecondsPerSecond; + wait_interval.tv_nsec %= kNanosecondsPerSecond; + + Lock& lock = auto_lock.GetLock(); + lock.AssertTakenAndMarkFree(); + int32_t timedwait_status = pthread_cond_timedwait(&cond_var_, + &lock.mutex_, + &wait_interval); + lock.AssertFreeAndMarkTaken(); + WaitStatus wait_status = kNoTimeout; + switch(timedwait_status) { + case 0: { + wait_status = kNoTimeout; + } break; + case EINTR: { + wait_status = kNoTimeout; + } break; + case ETIMEDOUT: { + wait_status = kTimeout; + } break; + default: { + LOG4CXX_ERROR(g_logger, "Failed to timewait for conditional variable"); + } + } + + return wait_status; +} + +} // namespace sync_primitives diff --git a/SDL_Core/src/components/Utils/src/date_time.cc b/SDL_Core/src/components/Utils/src/date_time.cc new file mode 100644 index 000000000..644e938a9 --- /dev/null +++ b/SDL_Core/src/components/Utils/src/date_time.cc @@ -0,0 +1,74 @@ +/** +* \file request_watchdog.h +* \brief DateTime class source file. +* +* 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. +*/ + +#include <sys/time.h> +#include <stdint.h> +#include "utils/date_time.h" + +namespace date_time { + +int32_t const DateTime::MILLISECONDS_IN_SECOND; +int32_t const DateTime::MICROSECONDS_IN_MILLISECONDS; + +struct timeval DateTime::getCurrentTime() { + struct timeval currentTime; + struct timezone timeZone; + + gettimeofday(¤tTime, &timeZone); + + return currentTime; +} + +int32_t DateTime::calculateTimeSpan(struct timeval sinceTime) { + struct timeval currentTime, timeDifference; + struct timezone timeZone; + + gettimeofday(¤tTime, &timeZone); + + timeDifference.tv_sec = currentTime.tv_sec - sinceTime.tv_sec; + + timeDifference.tv_usec = currentTime.tv_usec - sinceTime.tv_usec; + + if ( timeDifference.tv_usec < 0 ) { + timeDifference.tv_sec--; + timeDifference.tv_usec += MILLISECONDS_IN_SECOND + * MICROSECONDS_IN_MILLISECONDS; + } + + return timeDifference.tv_sec * MILLISECONDS_IN_SECOND + + timeDifference.tv_usec / MICROSECONDS_IN_MILLISECONDS; +} + +} // namespace date_time diff --git a/SDL_Core/src/components/Utils/src/file_system.cc b/SDL_Core/src/components/Utils/src/file_system.cc new file mode 100644 index 000000000..2e5b909af --- /dev/null +++ b/SDL_Core/src/components/Utils/src/file_system.cc @@ -0,0 +1,404 @@ +/** + * 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. + */ + +#include "utils/file_system.h" + +#include <sys/statvfs.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <dirent.h> +#include <unistd.h> +// TODO(VS): lint error: Streams are highly discouraged. +#include <fstream> +#include <cstddef> +#include <algorithm> +#include "config_profile/profile.h" + +uint64_t file_system::GetAvailableDiskSpace() { + char currentAppPath[FILENAME_MAX]; + memset(reinterpret_cast<void*>(currentAppPath), 0, FILENAME_MAX); + getcwd(currentAppPath, FILENAME_MAX - 1); + + struct statvfs fsInfo; + memset(reinterpret_cast<void*>(&fsInfo), 0, sizeof(fsInfo)); + if( statvfs(currentAppPath, &fsInfo) == 0) { + return fsInfo.f_bsize * fsInfo.f_bfree; + } else { + return 0; + } +} + +uint32_t file_system::FileSize(const std::string &path) { + if (file_system::FileExists(path)) { + struct stat file_info; + memset(reinterpret_cast<void*>(&file_info), 0, sizeof(file_info)); + stat(path.c_str(), &file_info); + return file_info.st_size; + } + return 0; +} + +uint32_t file_system::DirectorySize(const std::string& path) { + uint32_t size = 0; + int32_t return_code = 0; + DIR* directory = NULL; + +#ifndef __QNXNTO__ + struct dirent dir_element_; + struct dirent* dir_element = &dir_element_; +#else + char* direntbuffer = + new char[offsetof(struct dirent, d_name) + + pathconf(path.c_str(), _PC_NAME_MAX) + 1]; + struct dirent* dir_element = new(direntbuffer) dirent; +#endif + struct dirent* result = NULL; + struct stat file_info; + directory = opendir(path.c_str()); + if (NULL != directory) { + return_code = readdir_r(directory, dir_element, &result); + for (; NULL != result && 0 == return_code; + return_code = readdir_r(directory, dir_element, &result)) { + if (0 == strcmp(result->d_name, "..") + || 0 == strcmp(result->d_name, ".")) { + continue; + } + std::string full_element_path = path + "/" + result->d_name; + if (file_system::IsDirectory(full_element_path)) { + size += DirectorySize(full_element_path); + } else { + memset(reinterpret_cast<void*>(&file_info), 0, sizeof(file_info)); + stat(full_element_path.c_str(), &file_info); + size += file_info.st_size; + } + } + } + closedir(directory); +#ifdef __QNXNTO__ + delete[] direntbuffer; +#endif + return size; +} + +uint32_t file_system::GetAvailableSpaceForApp(const std::string& app_name) { + const uint32_t app_quota = profile::Profile::instance()->app_dir_quota(); + if (DirectoryExists(app_name)) { + std::string full_path = FullPath(app_name); + uint32_t size_of_directory = DirectorySize(full_path); + if (app_quota < size_of_directory) { + return 0; + } + uint32_t current_app_quota = app_quota - size_of_directory; + uint32_t available_disk_space = GetAvailableDiskSpace(); + if (current_app_quota > available_disk_space) { + return available_disk_space; + } else { + return current_app_quota; + } + } else { + return app_quota; + } +} + +std::string file_system::CreateDirectory(const std::string& name) { + if (!DirectoryExists(name)) { + mkdir(name.c_str(), S_IRWXU); + } + + return name; +} + +bool file_system::IsDirectory(const std::string& name) { + struct stat status; + memset(&status, 0, sizeof(status)); + + if (-1 == stat(name.c_str(), &status)) { + return false; + } + + return S_ISDIR(status.st_mode); +} + +bool file_system::DirectoryExists(const std::string& name) { + struct stat status; + memset(&status, 0, sizeof(status)); + + if (-1 == stat(name.c_str(), &status) || !S_ISDIR(status.st_mode)) { + return false; + } + + return true; +} + +bool file_system::FileExists(const std::string& name) { + struct stat status; + memset(&status, 0, sizeof(status)); + + if (-1 == stat(name.c_str(), &status)) { + return false; + } + return true; +} + +bool file_system::Write( + const std::string& file_name, const std::vector<uint8_t>& data, + std::ios_base::openmode mode) { + std::ofstream file(file_name.c_str(), std::ios_base::binary | mode); + if (file.is_open()) { + for (int32_t i = 0; i < data.size(); ++i) { + file << data[i]; + } + file.close(); + return true; + } + return false; +} + + + +std::ofstream* file_system::Open(const std::string& file_name, + std::ios_base::openmode mode) { + + + std::ofstream* file = new std::ofstream(); + file->open( file_name.c_str(),std::ios_base::binary | mode); + if (file->is_open()) { + + return file; + } + + return NULL; +} + +bool file_system::Write(std::ofstream* const file_stream, + const uint8_t* data, + uint32_t data_size) { + bool result = false; + if (file_stream) { + for (size_t i = 0; i < data_size; ++i) { + (*file_stream) << data[i]; + } + result = true; + } + return result; +} + +void file_system::Close(std::ofstream* file_stream) { + if (file_stream) { + file_stream->close(); + } +} + +std::string file_system::FullPath(const std::string& file) { + // FILENAME_MAX defined stdio_lim.h was replaced with less value + // since it seems, that is caused overflow in some cases + + size_t filename_max_lenght = 1024; + char currentAppPath[filename_max_lenght]; + memset(currentAppPath, 0, filename_max_lenght); + getcwd(currentAppPath, filename_max_lenght); + + char path[filename_max_lenght]; + memset(path, 0, filename_max_lenght); + snprintf(path, filename_max_lenght - 1, "%s/%s", currentAppPath, file.c_str()); + return std::string(path); +} + +bool file_system::DeleteFile(const std::string& name) { + if (FileExists(name) && IsAccessible(name, W_OK)) { + return !remove(name.c_str()); + } + return false; +} + +void remove_directory_content(const std::string& directory_name) { + int32_t return_code = 0; + DIR* directory = NULL; +#ifndef __QNXNTO__ + struct dirent dir_element_; + struct dirent* dir_element = &dir_element_; +#else + char* direntbuffer = + new char[offsetof(struct dirent, d_name) + + pathconf(directory_name.c_str(), _PC_NAME_MAX) + 1]; + struct dirent* dir_element = new(direntbuffer) dirent; +#endif + struct dirent* result = NULL; + + directory = opendir(directory_name.c_str()); + + if (NULL != directory) { + return_code = readdir_r(directory, dir_element, &result); + + for (; NULL != result && 0 == return_code; + return_code = readdir_r(directory, dir_element, &result)) { + if (0 == strcmp(result->d_name, "..") + || 0 == strcmp(result->d_name, ".")) { + continue; + } + + std::string full_element_path = directory_name + "/" + result->d_name; + + if (file_system::IsDirectory(full_element_path)) { + remove_directory_content(full_element_path); + rmdir(full_element_path.c_str()); + } else { + remove(full_element_path.c_str()); + } + } + } + + closedir(directory); +#ifdef __QNXNTO__ + delete[] direntbuffer; +#endif +} + +bool file_system::RemoveDirectory(const std::string& directory_name, + bool is_recursively) { + if (DirectoryExists(directory_name) + && IsAccessible(directory_name, W_OK)) { + if (is_recursively) { + remove_directory_content(directory_name); + } + + return !rmdir(directory_name.c_str()); + } + return false; +} + +bool file_system::IsAccessible(const std::string& name, int32_t how) { + return !access(name.c_str(), how); +} + +std::vector<std::string> file_system::ListFiles( + const std::string& directory_name) { + std::vector<std::string> listFiles; + if (!DirectoryExists(directory_name)) { + return listFiles; + } + + int32_t return_code = 0; + DIR* directory = NULL; +#ifndef __QNXNTO__ + struct dirent dir_element_; + struct dirent* dir_element = &dir_element_; +#else + char* direntbuffer = + new char[offsetof(struct dirent, d_name) + + pathconf(directory_name.c_str(), _PC_NAME_MAX) + 1]; + struct dirent* dir_element = new(direntbuffer) dirent; +#endif + struct dirent* result = NULL; + + directory = opendir(directory_name.c_str()); + if (NULL != directory) { + return_code = readdir_r(directory, dir_element, &result); + + for (; NULL != result && 0 == return_code; + return_code = readdir_r(directory, dir_element, &result)) { + if (0 == strcmp(result->d_name, "..") + || 0 == strcmp(result->d_name, ".")) { + continue; + } + + listFiles.push_back(std::string(result->d_name)); + } + + closedir(directory); +#ifdef __QNXNTO__ + delete[] direntbuffer; +#endif + } + + return listFiles; +} + +bool file_system::ReadBinaryFile(const std::string& name, + std::vector<uint8_t>& result) { + if (!FileExists(name) || !IsAccessible(name, R_OK)) { + return false; + } + + std::ifstream file(name.c_str(), std::ios_base::binary); + std::ostringstream ss; + ss << file.rdbuf(); + const std::string& s = ss.str(); + + result.resize(s.length()); + std::copy(s.begin(), s.end(), result.begin()); + return true; +} + +bool file_system::ReadFile(const std::string& name, std::string& result) { + if (!FileExists(name) || !IsAccessible(name, R_OK)) { + return false; + } + + std::ifstream file(name.c_str()); + std::ostringstream ss; + ss << file.rdbuf(); + result = ss.str(); + return true; +} + +const std::string file_system::ConvertPathForURL(const std::string& path) { + std::string::const_iterator it_path = path.begin(); + std::string::const_iterator it_path_end = path.end(); + + const std::string reserved_symbols = "!#$&'()*+,:;=?@[] "; + std::string::const_iterator it_sym = reserved_symbols.begin(); + std::string::const_iterator it_sym_end = reserved_symbols.end(); + + std::string converted_path; + while (it_path != it_path_end) { + + it_sym = reserved_symbols.begin(); + for (; it_sym != it_sym_end; ++it_sym) { + + if (*it_path == *it_sym) { + size_t size = 100; + char percent_value[size]; + snprintf(percent_value, size, "%%%x", *it_path); + converted_path += percent_value; + ++it_path; + continue; + } + } + + converted_path += *it_path; + ++it_path; + } + + return converted_path; +} diff --git a/SDL_Core/src/components/Utils/src/lock_posix.cc b/SDL_Core/src/components/Utils/src/lock_posix.cc new file mode 100644 index 000000000..be292f3e6 --- /dev/null +++ b/SDL_Core/src/components/Utils/src/lock_posix.cc @@ -0,0 +1,126 @@ +/** + * 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. + */ + +#include "utils/lock.h" + +#include <errno.h> + +#include "utils/logger.h" + +namespace { +log4cxx::LoggerPtr g_logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); +} + +namespace sync_primitives { + +Lock::Lock() +#ifndef NDEBUG + : lock_taken_(false) +#endif // NDEBUG +{ + int32_t status = pthread_mutex_init(&mutex_, NULL); + if (status != 0) { + LOG4CXX_ERROR(g_logger, "Failed to initialize mutex"); + } +} + +Lock::~Lock() { +#ifndef NDEBUG + if (lock_taken_) { + LOG4CXX_ERROR(g_logger, "Destroying non-released mutex"); + } +#endif + int32_t status = pthread_mutex_destroy(&mutex_); + if (status != 0) { + LOG4CXX_ERROR(g_logger, "Failed to destroy mutex"); + } +} + +void Lock::Ackquire() { + int32_t status = pthread_mutex_lock(&mutex_); + if (status != 0) { + LOG4CXX_ERROR(g_logger, "Failed to acquire mutex"); + } + AssertFreeAndMarkTaken(); +} + +void Lock::Release() { + AssertTakenAndMarkFree(); + int32_t status = pthread_mutex_unlock(&mutex_); + if (status != 0) { + LOG4CXX_ERROR(g_logger, "Failed to unlock mutex"); + } +} + +bool Lock::Try() { + bool ackquired = false; +#ifndef NDEBUG + if (lock_taken_) { + LOG4CXX_ERROR(g_logger, "Trying to lock already taken mutex"); + } +#endif + switch(pthread_mutex_trylock(&mutex_)) { + case 0: { + ackquired = true; +#ifndef NDEBUG + lock_taken_ = true; +#endif + } break; + case EBUSY: { + ackquired = false; + } break; + default: { + ackquired = false; + LOG4CXX_ERROR(g_logger, "Failed to try lock the mutex"); + } + } + return ackquired; +} + +#ifndef NDEBUG +void Lock::AssertFreeAndMarkTaken() { + if (lock_taken_) { + LOG4CXX_ERROR(g_logger, "Locking already taken mutex"); + } + lock_taken_ = true; +} +void Lock::AssertTakenAndMarkFree() { + if (!lock_taken_) { + LOG4CXX_ERROR(g_logger, "Unlocking a mutex that is not taken"); + } + lock_taken_ = false; +} +#endif + + +} // namespace sync_primitives diff --git a/SDL_Core/src/components/Utils/src/signals_linux.cc b/SDL_Core/src/components/Utils/src/signals_linux.cc new file mode 100644 index 000000000..1821f6fbe --- /dev/null +++ b/SDL_Core/src/components/Utils/src/signals_linux.cc @@ -0,0 +1,57 @@ +/** +* \file signals.cc +* \brief Signal (i.e. SIGINT) handling. +* 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. +*/ +#include <csignal> +#include <stdint.h> + +namespace utils { + +bool SubscribeToTerminateSignal(void (*func)(int32_t p)) { + void (*prev_func)(int32_t p); + + prev_func = signal(SIGINT, func); + return (SIG_ERR != prev_func); +} + +bool ResetSubscribeToTerminateSignal() { + void (*prev_func)(int32_t p); + prev_func = signal(SIGINT, SIG_DFL); + return (SIG_ERR != prev_func); +} + +void ForwardSignal() { + int32_t signal_id = SIGINT; + raise(signal_id); +} + +} // namespace utils diff --git a/SDL_Core/src/components/Utils/src/threads/posix_thread.cc b/SDL_Core/src/components/Utils/src/threads/posix_thread.cc new file mode 100644 index 000000000..e59fedc2a --- /dev/null +++ b/SDL_Core/src/components/Utils/src/threads/posix_thread.cc @@ -0,0 +1,185 @@ +/** + * 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. + */ + +#include <limits.h> +#include <stddef.h> + +#include "utils/threads/thread.h" +#include "utils/threads/thread_manager.h" + +using namespace std; +using namespace threads::impl; + +namespace { +static void* threadFunc(void* closure) { + threads::ThreadDelegate* delegate = + static_cast<threads::ThreadDelegate*>(closure); + delegate->threadMain(); + return NULL; +} +} + +namespace threads { +size_t Thread::kMinStackSize = PTHREAD_STACK_MIN; /* Ubuntu : 16384 ; QNX : 256; */ +log4cxx::LoggerPtr Thread::logger_ = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("threads::Thread")); + +bool Thread::Id::operator==(const Thread::Id other) const { + return pthread_equal(id_, other.id_) != 0; +} + +// static +Thread::Id Thread::CurrentId() { + return Id(pthread_self()); +} + +//static +std::string Thread::NameFromId(Id thread_id) { + return ThreadManager::instance()->GetName(thread_id.id_); +} + +//static +void Thread::SetNameForId(Id thread_id, const std::string& name) { + ThreadManager::instance()->RegisterName(thread_id.id_, name); +} + + +Thread::Thread(const char* name, ThreadDelegate* delegate) + : name_("undefined"), + delegate_(delegate), + thread_handle_(0), + thread_options_(), + isThreadRunning_(false) { + if (name) { + name_ = name; + } +} + +Thread::~Thread() { + ThreadManager::instance()->Unregister(thread_handle_); + if (delegate_) { + delete delegate_; + } +} + +bool Thread::start() { + return startWithOptions(thread_options_); +} + +bool Thread::startWithOptions(const ThreadOptions& options) { + if (!delegate_) { + NOTREACHED(); + return false; + } + + thread_options_ = options; + + bool success = false; + pthread_attr_t attributes; + int pthread_result = pthread_attr_init(&attributes); + if (pthread_result != 0) { + LOG4CXX_INFO(logger_,"Couldn't init pthread attributes." + " Error code = " << pthread_result); + } + if (!thread_options_.is_joinable()) { + pthread_result = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); + if (pthread_result != 0) { + LOG4CXX_INFO(logger_,"Couldn't set detach state attribute. Error code = " << pthread_result); + } + } + + // 0 - default value + if (thread_options_.stack_size() > 0 + && thread_options_.stack_size() >= Thread::kMinStackSize) { + pthread_result = pthread_attr_setstacksize(&attributes, thread_options_.stack_size()); + if (pthread_result != 0) { + LOG4CXX_INFO(logger_,"Couldn't set stacksize = " << thread_options_.stack_size() << + "Error code = " << pthread_result); + } + } + success = !pthread_create(&thread_handle_, &attributes, threadFunc, + delegate_); + if (success) { + pthread_result = pthread_setname_np(thread_handle_, name_.c_str()); +# ifdef __QNXNTO__ + if (pthread_result != EOK) { + LOG4CXX_INFO(logger_,"Couldn't set pthread name" + " Error code = " << pthread_result); + } +# endif + LOG4CXX_INFO(logger_,"Created thread: " << name_); + ThreadManager::instance()->RegisterName(thread_handle_, name_); + } + + isThreadRunning_ = success; + + pthread_result = pthread_attr_destroy(&attributes); + if (pthread_result != 0) { + LOG4CXX_INFO(logger_,"Couldn't destroy pthread attributes." + " Error code = " << pthread_result); + } + return success; +} + +void Thread::stop() { + if (!is_running()) { + return; + } + + if (NULL != delegate_) { + if (!delegate_->exitThreadMain()) { + if (thread_handle_ != pthread_self()) { + pthread_cancel(thread_handle_); + } + } + } + + // Wait for the thread to exit. It should already have terminated but make + // sure this assumption is valid. + + join(); +} + +void Thread::join() { + int pthread_result = pthread_join(thread_handle_, NULL); + if (pthread_result != 0) { + LOG4CXX_INFO(logger_,"Couldn't join thread " + " Error code = " << pthread_result); + } + isThreadRunning_ = false; +} + +std::ostream& operator<<(std::ostream& os, Thread::Id thread_id) { + return os<<Thread::NameFromId(thread_id); +} + +} // namespace threads diff --git a/SDL_Core/src/components/Utils/src/threads/thread_manager.cc b/SDL_Core/src/components/Utils/src/threads/thread_manager.cc new file mode 100644 index 000000000..e4b96aa51 --- /dev/null +++ b/SDL_Core/src/components/Utils/src/threads/thread_manager.cc @@ -0,0 +1,120 @@ +/** + * 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. + */ + +#include "utils/threads/thread_manager.h" + +#include <sstream> + +#if defined(OS_LINUX) +#include <sys/syscall.h> +#include <unistd.h> +#endif + +namespace threads { +namespace impl { +using namespace std; +using namespace sync_primitives; + +namespace { + +const char* kUnknownName = "UnnamedThread"; + +log4cxx::LoggerPtr g_logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); + +} // namespace + +UnnamedThreadRegistry::UnnamedThreadRegistry() { + +} + +UnnamedThreadRegistry::~UnnamedThreadRegistry() { + +} + +std::string UnnamedThreadRegistry::GetUniqueName(PlatformThreadHandle id) { + AutoLock auto_lock(state_lock_); + IdNameMap::iterator found = id_number_.find(id); + if (found != id_number_.end()) { + return found->second; + } else { + ++last_thread_number_; + std::stringstream namestream; + namestream<<kUnknownName<<last_thread_number_; + return id_number_[id] = namestream.str(); + } +} + +ThreadManager::ThreadManager() { + names_.insert(kUnknownName); +} + +ThreadManager::~ThreadManager() { +} + +void ThreadManager::RegisterName(PlatformThreadHandle id, const string& name) { + AutoLock auto_lock(state_lock_); + if (names_.count(name) == 0) { + names_.insert(name); + pair<IdNamesMap::iterator, bool> inserted = + id_names_.insert(make_pair(id, name)); + if (!inserted.second) { + LOG4CXX_ERROR(g_logger, "Trying to register thread name " << name + <<", but it is already registered with name " + <<inserted.first->second); + } + } else { + LOG4CXX_ERROR(g_logger, "Ignoring duplicate thread name: " + name); + } +} + +string ThreadManager::GetName(PlatformThreadHandle id) const { + AutoLock auto_lock(state_lock_); + IdNamesMap::const_iterator found = id_names_.find(id); + if (found != id_names_.end()) { + return found->second; + } else { + LOG4CXX_WARN(g_logger, "Thread doesn't have associated name"); + return unnamed_thread_namer_.GetUniqueName(id); + } +} + +void ThreadManager::Unregister(PlatformThreadHandle id) { + AutoLock auto_lock(state_lock_); + string name = id_names_[id]; + names_.erase(name); + id_names_.erase(id); +} + + +} // namespace impl +} // namespace threads diff --git a/SDL_Core/src/components/Utils/src/threads/thread_validator.cc b/SDL_Core/src/components/Utils/src/threads/thread_validator.cc new file mode 100644 index 000000000..5bc66f138 --- /dev/null +++ b/SDL_Core/src/components/Utils/src/threads/thread_validator.cc @@ -0,0 +1,95 @@ +/** + * 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. + */ +#include "utils/threads/thread_validator.h" + +#include "utils/logger.h" +#include "utils/back_trace.h" + +namespace threads { + +namespace { +log4cxx::LoggerPtr g_logger = + log4cxx::LoggerPtr(log4cxx::Logger::getLogger("Utils")); +} + +SingleThreadSimpleValidator::SingleThreadSimpleValidator() + : creation_thread_id_(Thread::CurrentId()) { +} + +SingleThreadSimpleValidator::~SingleThreadSimpleValidator() { +} + +void SingleThreadSimpleValidator::AssertRunningOnCreationThread() const { + Thread::Id current_id = Thread::CurrentId(); + if (creation_thread_id_ != current_id) { + LOG4CXX_ERROR(g_logger, "Single-threaded object created at thread " + << creation_thread_id_ + <<" is accessed from thread " + << current_id +#ifdef BACKTRACE_SUPPORT + << "\n" + << utils::Backtrace() +#endif + ); + } +} + + +SingleThreadValidator::SingleThreadValidator() + : owning_thread_id_(Thread::CurrentId()){ +} + +SingleThreadValidator::~SingleThreadValidator() { +} + +void SingleThreadValidator::PassToThread(Thread::Id thread_id) const { + owning_thread_id_ = thread_id; +} + +void SingleThreadValidator::AssertRunningOnValidThread() const { + Thread::Id current_id = Thread::CurrentId(); + if (owning_thread_id_ != current_id) { + LOG4CXX_ERROR(g_logger, "Single-threaded object owned by thread " + << owning_thread_id_ + << " is accessed from thread " + << current_id << "\n" +#ifdef BACKTRACE_SUPPORT + << utils::Backtrace() +#endif + ); + } +} + + +} // namespace threads + +// vim: set ts=2 sw=2 et: |