summaryrefslogtreecommitdiff
path: root/src/components/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/include')
-rw-r--r--src/components/include/protocol/common.h13
-rw-r--r--src/components/include/protocol/raw_message.h2
-rw-r--r--src/components/include/protocol/service_type.h2
-rw-r--r--src/components/include/protocol_handler/protocol_handler.h4
-rw-r--r--src/components/include/protocol_handler/session_observer.h25
-rw-r--r--src/components/include/security_manager/crypto_manager.h2
-rw-r--r--src/components/include/transport_manager/transport_adapter/device.h2
-rw-r--r--src/components/include/transport_manager/transport_adapter/transport_adapter.h8
-rw-r--r--src/components/include/transport_manager/transport_manager.h6
-rw-r--r--src/components/include/transport_manager/transport_manager_listener.h2
-rw-r--r--src/components/include/utils/atomic.h8
-rw-r--r--src/components/include/utils/conditional_variable.h6
-rw-r--r--src/components/include/utils/data_accessor.h38
-rw-r--r--src/components/include/utils/date_time.h64
-rw-r--r--src/components/include/utils/lock.h28
-rw-r--r--src/components/include/utils/logger.h24
-rw-r--r--src/components/include/utils/logger_status.h2
-rw-r--r--src/components/include/utils/macro.h56
-rw-r--r--src/components/include/utils/memory_barrier.h2
-rw-r--r--src/components/include/utils/message_queue.h15
-rw-r--r--src/components/include/utils/prioritized_queue.h2
-rw-r--r--src/components/include/utils/rwlock.h95
-rw-r--r--src/components/include/utils/shared_ptr.h5
-rw-r--r--src/components/include/utils/threads/CMakeLists.txt5
-rw-r--r--src/components/include/utils/threads/message_loop_thread.h54
-rw-r--r--src/components/include/utils/threads/thread.h146
-rw-r--r--src/components/include/utils/threads/thread_delegate.h64
-rw-r--r--src/components/include/utils/threads/thread_options.h4
-rw-r--r--src/components/include/utils/timer_thread.h450
29 files changed, 718 insertions, 416 deletions
diff --git a/src/components/include/protocol/common.h b/src/components/include/protocol/common.h
index f9fdd08fae..6970bc8af4 100644
--- a/src/components/include/protocol/common.h
+++ b/src/components/include/protocol/common.h
@@ -57,6 +57,7 @@ const uint8_t PROTOCOL_HEADER_V2_SIZE = 12;
* First 4-bit field of AppLink protocol packet
*/
enum {
+
/**
*\brief Constant: number of protocol version (1).
*/
@@ -71,10 +72,18 @@ enum {
*\brief Constant: number of protocol version (3).
* Has no difference with v.2 in Mobile_API.xml and frame Header difference
* Support SSL with Encryption, Video and Audio services
- * Suuport ControlFrame, End Service to/from mobile support, HeartBeat future
+ * Support ControlFrame, End Service to/from mobile support, HeartBeat feature
*/
PROTOCOL_VERSION_3 = 0x03,
/**
+ *@brief Constant: number of protocol version (4).
+ * This protocol is compatibility with version 3
+ * Support SSL with Encryption, Video and Audio services
+ * Support ControlFrame, End Service to/from mobile support, HeartBeat feature,
+ * SDL4.0 feature.
+ */
+ PROTOCOL_VERSION_4 = 0x04,
+ /**
*\brief Maximum value of packet version field (size 4-bit) specified AppLink Protocol v.7
*/
PROTOCOL_VERSION_MAX = 0x0F
@@ -216,7 +225,7 @@ enum RESULT_CODE {
RESULT_REASSIGN = 12,
RESULT_XML_PARSING = 13,
RESULT_RESEND_ACK = 14,
- RESULT_DEFRERRED = 15,
+ RESULT_DEFERRED = 15,
RESULT_ENCRYPTION_FAILED = 16,
RESULT_HEARTBEAT_IS_NOT_SUPPORTED = 17,
RESULT_UNKNOWN = 255
diff --git a/src/components/include/protocol/raw_message.h b/src/components/include/protocol/raw_message.h
index 09b5eafb7e..f9a035e174 100644
--- a/src/components/include/protocol/raw_message.h
+++ b/src/components/include/protocol/raw_message.h
@@ -78,7 +78,7 @@ class RawMessage {
/**
* \brief Getter for message size
*/
- size_t data_size() const;
+ size_t data_size() const;
/**
* \brief Getter for actual data size
*/
diff --git a/src/components/include/protocol/service_type.h b/src/components/include/protocol/service_type.h
index ab049be9b7..b5870e0af1 100644
--- a/src/components/include/protocol/service_type.h
+++ b/src/components/include/protocol/service_type.h
@@ -61,7 +61,6 @@ const uint8_t SERVICE_TYPE_NAVI = 0x0B;
*/
const uint8_t SERVICE_TYPE_BULK = 0x0F;
-
/**
* \brief Enum describing possible types of sessions: RPC for API messages,
Navi for video streaming, bulk for PutFile.
@@ -83,5 +82,4 @@ ServiceType ServiceTypeFromByte(uint8_t type);
uint8_t ServiceTypeToByte(ServiceType type);
} // namespace protocol_handler
-
#endif // SRC_COMPONENTS_INCLUDE_PROTOCOL_SERVICE_TYPE_H_
diff --git a/src/components/include/protocol_handler/protocol_handler.h b/src/components/include/protocol_handler/protocol_handler.h
index e0d4fde8cd..9bb77ae483 100644
--- a/src/components/include/protocol_handler/protocol_handler.h
+++ b/src/components/include/protocol_handler/protocol_handler.h
@@ -97,6 +97,10 @@ class ProtocolHandler {
*/
virtual void SendEndSession(int32_t connection_id, uint8_t session_id) = 0;
+ virtual void SendEndService(int32_t connection_id,
+ uint8_t session_id,
+ uint8_t service_type) = 0;
+
protected:
/**
* \brief Destructor
diff --git a/src/components/include/protocol_handler/session_observer.h b/src/components/include/protocol_handler/session_observer.h
index 9a958f6fa7..355c62e646 100644
--- a/src/components/include/protocol_handler/session_observer.h
+++ b/src/components/include/protocol_handler/session_observer.h
@@ -96,6 +96,20 @@ class SessionObserver {
const protocol_handler::ServiceType &service_type) = 0;
/**
+ * \brief Callback function used by ProtocolHandler
+ * when Mobile Application start message flood
+ * \param connection_key used by other components as application identifier
+ */
+ virtual void OnApplicationFloodCallBack(const uint32_t &connection_key) = 0;
+
+ /**
+ * \brief Callback function used by ProtocolHandler
+ * when Mobile Application sends malformed message
+ * \param connection_key used by other components as application identifier
+ */
+ virtual void OnMalformedMessageCallback(const uint32_t &connection_key) = 0;
+
+ /**
* \brief Creates unique identifier of session (can be used as hash)
* from given connection identifier
* within which session exists and session number.
@@ -157,6 +171,17 @@ class SessionObserver {
transport_manager::ConnectionUID connection_handle,
uint8_t session_id) = 0;
+ /**
+ * @brief returns protocol version which application supports
+ * @param connection_id id of connection
+ * @param session_id id of session
+ * @param method writes value protocol version to protocol_version
+ * @return TRUE if session and connection exist otherwise returns FALSE
+ */
+ virtual bool ProtocolVersionUsed(uint32_t connection_id,
+ uint8_t session_id, uint8_t& protocol_version) = 0;
+
+
#ifdef ENABLE_SECURITY
/**
* \brief Sets crypto context of connection
diff --git a/src/components/include/security_manager/crypto_manager.h b/src/components/include/security_manager/crypto_manager.h
index 87cfc1397f..00c3833e62 100644
--- a/src/components/include/security_manager/crypto_manager.h
+++ b/src/components/include/security_manager/crypto_manager.h
@@ -50,7 +50,7 @@ namespace security_manager {
class SSLContext;
enum Mode { CLIENT, SERVER };
-enum Protocol { SSLv3, TLSv1, TLSv1_1, TLSv1_2 };
+enum Protocol { SSLv3, TLSv1, TLSv1_1, TLSv1_2};
class CryptoManager {
public:
diff --git a/src/components/include/transport_manager/transport_adapter/device.h b/src/components/include/transport_manager/transport_adapter/device.h
index 78d3b44958..e7bca5a46b 100644
--- a/src/components/include/transport_manager/transport_adapter/device.h
+++ b/src/components/include/transport_manager/transport_adapter/device.h
@@ -76,6 +76,8 @@ class Device {
virtual ApplicationList GetApplicationList() const = 0;
+ virtual void Stop() { }
+
inline const DeviceUID& unique_device_id() const {
return unique_device_id_;
}
diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter.h b/src/components/include/transport_manager/transport_adapter/transport_adapter.h
index 2edf173110..b73333e535 100644
--- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h
+++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h
@@ -1,4 +1,4 @@
-/**
+/*
* \file transport_adapter.h
* \brief TransportAdapter class header file.
*
@@ -123,6 +123,12 @@ class TransportAdapter {
virtual Error Init() = 0;
/**
+ * @brief Stops device adapter
+ * Called from transport manager to stop device adapter
+ */
+ virtual void Terminate() = 0;
+
+ /**
* @brief Add listener to the container(list) of device adapter listeners.
*
* @param listener Pointer to the device adapter listener.
diff --git a/src/components/include/transport_manager/transport_manager.h b/src/components/include/transport_manager/transport_manager.h
index 40790ac0ab..25745e7485 100644
--- a/src/components/include/transport_manager/transport_manager.h
+++ b/src/components/include/transport_manager/transport_manager.h
@@ -59,6 +59,12 @@ class TransportManager {
virtual int Init() = 0;
/**
+ * @brief Reinitializes transport manager
+ * @return Error code
+ */
+ virtual int Reinit() = 0;
+
+ /**
* @brief Start scanning for new devices.
*
* @return Code error.
diff --git a/src/components/include/transport_manager/transport_manager_listener.h b/src/components/include/transport_manager/transport_manager_listener.h
index 5033a95d17..0684e8f22f 100644
--- a/src/components/include/transport_manager/transport_manager_listener.h
+++ b/src/components/include/transport_manager/transport_manager_listener.h
@@ -143,7 +143,7 @@ class TransportManagerListener {
/**
* @brief Notifies about recieving message from TM.
*
- * @param message Recieved message
+ * @param message Received message
**/
virtual void OnTMMessageReceived(const ::protocol_handler::RawMessagePtr message) = 0;
diff --git a/src/components/include/utils/atomic.h b/src/components/include/utils/atomic.h
index bfbcff9dc9..f80455b748 100644
--- a/src/components/include/utils/atomic.h
+++ b/src/components/include/utils/atomic.h
@@ -28,15 +28,15 @@
* 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_INCLUDE_UTILS_ATOMIC_H_
+#define SRC_COMPONENTS_INCLUDE_UTILS_ATOMIC_H_
#ifdef __QNXNTO__
#include <atomic.h>
#endif
-#ifndef SRC_COMPONENTS_INCLUDE_UTILS_ATOMIC_H_
-#define SRC_COMPONENTS_INCLUDE_UTILS_ATOMIC_H_
-
#if defined(__QNXNTO__)
#define atomic_post_inc(ptr) atomic_add_value((ptr), 1)
#elif defined(__GNUG__)
diff --git a/src/components/include/utils/conditional_variable.h b/src/components/include/utils/conditional_variable.h
index 58119a0cfd..1f0a7e62de 100644
--- a/src/components/include/utils/conditional_variable.h
+++ b/src/components/include/utils/conditional_variable.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -43,6 +43,7 @@
namespace sync_primitives {
class AutoLock;
+class Lock;
namespace impl {
#if defined(OS_POSIX)
@@ -80,7 +81,8 @@ class ConditionalVariable {
void Broadcast();
// Wait forever or up to milliseconds time limit
- void Wait(AutoLock& auto_lock);
+ bool Wait(AutoLock& auto_lock);
+ bool Wait(Lock& lock);
WaitStatus WaitFor(AutoLock& auto_lock, int32_t milliseconds);
private:
impl::PlatformConditionalVariable cond_var_;
diff --git a/src/components/include/utils/data_accessor.h b/src/components/include/utils/data_accessor.h
index f5e99797ba..344d6e34a8 100644
--- a/src/components/include/utils/data_accessor.h
+++ b/src/components/include/utils/data_accessor.h
@@ -33,40 +33,42 @@
#define SRC_COMPONENTS_INCLUDE_UTILS_DATA_ACCESSOR_H_
#include "utils/lock.h"
+#include "utils/shared_ptr.h"
// This class is for thread-safe access to data
template<class T>
class DataAccessor {
public:
DataAccessor(const T& data, const sync_primitives::Lock& lock)
- : data_(data)
- , lock_(const_cast<sync_primitives::Lock&>(lock))
- , counter_(0) {
- lock_.Acquire();
+ : data_(data),
+ lock_(const_cast<sync_primitives::Lock&>(lock)),
+ counter_( new uint32_t(0)) {
+ lock_.Acquire();
}
- template<class O> DataAccessor(const DataAccessor<O>& other)
- : data_(other.data_)
- , lock_(other.lock_)
- , counter_(other.counter_) {
- ++counter_;
+
+ DataAccessor(const DataAccessor<T>& other)
+ : data_(other.data_),
+ lock_(other.lock_),
+ counter_(other.counter_) {
+ ++(*counter_);
}
+
~DataAccessor() {
- if (counter_ > 0) {
- --counter_;
- }
- if (0 == counter_) {
- lock_.Release();
+ if (0 == *counter_) {
+ lock_.Release();
+ } else {
+ --(*counter_);
}
}
const T& GetData() const {
return data_;
}
private:
- template <class O> const DataAccessor<T>& operator=(const DataAccessor<O>& other);
- const T& data_;
- sync_primitives::Lock& lock_;
- uint32_t counter_;
+ void *operator new(size_t size);
+ const T& data_;
+ sync_primitives::Lock& lock_;
+ utils::SharedPtr<uint32_t> counter_;
};
#endif // SRC_COMPONENTS_INCLUDE_UTILS_DATA_ACCESSOR_H_
diff --git a/src/components/include/utils/date_time.h b/src/components/include/utils/date_time.h
index 766932652d..c8cef32ef4 100644
--- a/src/components/include/utils/date_time.h
+++ b/src/components/include/utils/date_time.h
@@ -1,34 +1,34 @@
/*
-* Copyright (c) 2014, Ford Motor Company
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following disclaimer.
-*
-* Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided with the
-* distribution.
-*
-* Neither the name of the Ford Motor Company nor the names of its contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
#ifndef SRC_COMPONENTS_INCLUDE_UTILS_DATE_TIME_H_
#define SRC_COMPONENTS_INCLUDE_UTILS_DATE_TIME_H_
@@ -50,6 +50,7 @@ class DateTime {
public:
static const int32_t MILLISECONDS_IN_SECOND = 1000;
static const int32_t MICROSECONDS_IN_MILLISECONDS = 1000;
+ static const int32_t MICROSECONDS_IN_SECOND = 1000 * 1000;
static TimevalStruct getCurrentTime();
@@ -80,5 +81,6 @@ class DateTime {
};
} // namespace date_time
-
+bool operator<(const TimevalStruct& time1, const TimevalStruct& time2);
+bool operator==(const TimevalStruct& time1, const TimevalStruct& time2);
#endif // SRC_COMPONENTS_INCLUDE_UTILS_DATE_TIME_H_
diff --git a/src/components/include/utils/lock.h b/src/components/include/utils/lock.h
index 910a88052f..29bd467143 100644
--- a/src/components/include/utils/lock.h
+++ b/src/components/include/utils/lock.h
@@ -34,11 +34,14 @@
#if defined(OS_POSIX)
#include <pthread.h>
+#include <sched.h>
#else
#error Please implement lock for your OS
#endif
#include <stdint.h>
#include "utils/macro.h"
+#include "utils/atomic.h"
+#include "utils/memory_barrier.h"
namespace sync_primitives {
@@ -48,6 +51,31 @@ typedef pthread_mutex_t PlatformMutex;
#endif
} // namespace impl
+
+class SpinMutex {
+ public:
+ SpinMutex()
+ : state_(0) { }
+ void Lock() {
+ if (atomic_post_set(&state_) == 0) {
+ return;
+ }
+ for(;;) {
+ sched_yield();
+ if (state_ == 0 && atomic_post_set(&state_) == 0) {
+ return;
+ }
+ }
+ }
+ void Unlock() {
+ state_ = 0;
+ }
+ ~SpinMutex() {
+ }
+ private:
+ volatile unsigned int state_;
+};
+
/* 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
diff --git a/src/components/include/utils/logger.h b/src/components/include/utils/logger.h
index 7c00c5d3aa..50d194245c 100644
--- a/src/components/include/utils/logger.h
+++ b/src/components/include/utils/logger.h
@@ -30,6 +30,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+
+
#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_LOGGER_H_
#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_LOGGER_H_
@@ -37,11 +39,11 @@
#include <errno.h>
#include <string.h>
#include <sstream>
- #include <apr_time.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/spi/loggingevent.h>
#include "utils/push_log.h"
#include "utils/logger_status.h"
+ #include "utils/auto_trace.h"
#endif // ENABLE_LOG
#ifdef ENABLE_LOG
@@ -57,19 +59,23 @@
#define INIT_LOGGER(file_name) \
log4cxx::PropertyConfigurator::configure(file_name);
- // without this line log4cxx threads continue using some instances destroyed by exit()
- #define DEINIT_LOGGER() \
- log4cxx::Logger::getRootLogger()->closeNestedAppenders();
+ // Logger deinitilization function and macro, need to stop log4cxx writing
+ // without this deinitilization log4cxx threads continue using some instances destroyed by exit()
+ void deinit_logger ();
+ #define DEINIT_LOGGER() deinit_logger()
#define LOG4CXX_IS_TRACE_ENABLED(logger) logger->isTraceEnabled()
+ log4cxx_time_t time_now();
+
#define LOG_WITH_LEVEL(loggerPtr, logLevel, logEvent) \
do { \
if (logger::logger_status != logger::DeletingLoggerThread) { \
if (loggerPtr->isEnabledFor(logLevel)) { \
std::stringstream accumulator; \
accumulator << logEvent; \
- logger::push_log(loggerPtr, logLevel, accumulator.str(), apr_time_now(), LOG4CXX_LOCATION, ::log4cxx::spi::LoggingEvent::getCurrentThreadName()); \
+ logger::push_log(loggerPtr, logLevel, accumulator.str(), time_now(), \
+ LOG4CXX_LOCATION, ::log4cxx::spi::LoggingEvent::getCurrentThreadName()); \
} \
} \
} while (false)
@@ -110,8 +116,8 @@
#undef LOG4CXX_TRACE
#define LOG4CXX_TRACE(loggerPtr, logEvent) LOG_WITH_LEVEL(loggerPtr, ::log4cxx::Level::getTrace(), 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_AUTO_TRACE_WITH_NAME_SPECIFIED(loggerPtr, auto_trace) logger::AutoTrace auto_trace(loggerPtr, LOG4CXX_LOCATION)
+ #define LOG4CXX_AUTO_TRACE(loggerPtr) LOG4CXX_AUTO_TRACE_WITH_NAME_SPECIFIED(loggerPtr, SDL_local_auto_trace_object)
#define LOG4CXX_ERROR_WITH_ERRNO(logger, message) \
LOG4CXX_ERROR(logger, message << ", error code " << errno << " (" << strerror(errno) << ")")
@@ -173,8 +179,8 @@
#define LOG4CXX_FATAL_EXT(logger, logEvent)
#define LOG4CXX_FATAL_STR_EXT(logger, logEvent)
- #define LOG4CXX_TRACE_ENTER(logger)
- #define LOG4CXX_TRACE_EXIT(logger)
+ #define LOG4CXX_AUTO_TRACE_WITH_NAME_SPECIFIED(loggerPtr, auto_trace)
+ #define LOG4CXX_AUTO_TRACE(loggerPtr)
#endif // ENABLE_LOG
#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_LOGGER_H_
diff --git a/src/components/include/utils/logger_status.h b/src/components/include/utils/logger_status.h
index e28fa6f839..17fa0562c2 100644
--- a/src/components/include/utils/logger_status.h
+++ b/src/components/include/utils/logger_status.h
@@ -45,7 +45,7 @@ typedef enum {
// this variable is only changed when creating and deleting logger thread
// its reads and writes are believed to be atomic
// thus it shall be considered thread safe
-extern LoggerStatus logger_status;
+extern volatile LoggerStatus logger_status;
} // namespace logger
diff --git a/src/components/include/utils/macro.h b/src/components/include/utils/macro.h
index bf34b199b5..bfd13411f4 100644
--- a/src/components/include/utils/macro.h
+++ b/src/components/include/utils/macro.h
@@ -32,8 +32,12 @@
#ifndef SRC_COMPONENTS_INCLUDE_UTILS_MACRO_H_
#define SRC_COMPONENTS_INCLUDE_UTILS_MACRO_H_
+#ifdef DEBUG
#include <assert.h>
+#else // RELEASE
#include <stdio.h>
+#endif
+#include "logger.h"
@@ -54,14 +58,53 @@
#define FRIEND_DELETER_DESTRUCTOR(TypeName) \
friend utils::deleters::Deleter<TypeName>::~Deleter()
+#ifdef DEBUG
+ #define ASSERT(condition) \
+ do { \
+ DEINIT_LOGGER(); \
+ assert(condition); \
+ } while (false)
+#else // RELEASE
+ #define ASSERT(condition) \
+ fprintf(stderr, "Failed condition \"" #condition "\" [%s:%d][%s]\n\n", \
+ __FILE__, __LINE__, __FUNCTION__)
+#endif
+
#define DCHECK(condition) \
if (!(condition)) { \
- printf("\nDCHECK [%s:%d][%s]", __FILE__, __LINE__, __FUNCTION__); \
- printf("[Check failed: " #condition "]\n\n"); \
- assert(false); \
+ CREATE_LOGGERPTR_LOCAL(logger_, "assert"); \
+ LOG4CXX_FATAL(logger_, "DCHECK failed with \"" << #condition \
+ << "\" [" << __FUNCTION__ << "][" << __FILE__ << ':' << __LINE__ << ']'); \
+ ASSERT((condition)); \
+ }
+
+/*
+ * Will cauch assert on debug version,
+ * Will return return_value in release build
+ */
+#define DCHECK_OR_RETURN(condition, return_value) \
+ if (!(condition)) { \
+ CREATE_LOGGERPTR_LOCAL(logger_, "assert"); \
+ LOG4CXX_FATAL(logger_, "DCHECK failed with \"" << #condition \
+ << "\" [" << __FUNCTION__ << "][" << __FILE__ << ':' << __LINE__ << ']' ); \
+ ASSERT((condition)); \
+ return (return_value); \
+ }
+/*
+ * Will cauch assert on debug version,
+ * Will return return_value in release build
+ */
+#define DCHECK_OR_RETURN_VOID(condition) \
+ if (!(condition)) { \
+ CREATE_LOGGERPTR_LOCAL(logger_, "assert"); \
+ LOG4CXX_FATAL(logger_, "DCHECK failed with \"" << #condition \
+ << "\" [" << __FUNCTION__ << "][" << __FILE__ << ':' << __LINE__ << ']' ); \
+ ASSERT((condition)); \
+ return ; \
}
-#define NOTREACHED() DCHECK(false)
+
+#define NOTREACHED() DCHECK(!"Unreachable code")
// Allows to perform static check that virtual function from base class is
// actually being overriden if compiler support is available
@@ -79,4 +122,9 @@
*/
#define ARRAYSIZE(arr) sizeof (arr) / sizeof(*arr)
+#ifdef BUILD_TESTS
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+#endif
+
#endif // SRC_COMPONENTS_INCLUDE_UTILS_MACRO_H_
diff --git a/src/components/include/utils/memory_barrier.h b/src/components/include/utils/memory_barrier.h
index 312894e034..43c7c9df14 100644
--- a/src/components/include/utils/memory_barrier.h
+++ b/src/components/include/utils/memory_barrier.h
@@ -28,7 +28,7 @@
* 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_
diff --git a/src/components/include/utils/message_queue.h b/src/components/include/utils/message_queue.h
index 9d998cc698..a187328e13 100644
--- a/src/components/include/utils/message_queue.h
+++ b/src/components/include/utils/message_queue.h
@@ -28,10 +28,10 @@
* 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
+#ifndef SRC_COMPONENTS_INCLUDE_UTILS_MESSAGE_QUEUE_H_
+#define SRC_COMPONENTS_INCLUDE_UTILS_MESSAGE_QUEUE_H_
#include <queue>
@@ -44,7 +44,9 @@
* \class MessageQueue
* \brief Wrapper for multithreading queue.
*/
- //TODO(Ezamakhov): move to utils namespace
+
+namespace utils {
+
template<typename T, class Q = std::queue<T> > class MessageQueue {
public:
typedef Q Queue;
@@ -107,7 +109,6 @@ template<typename T, class Q = std::queue<T> > class MessageQueue {
void Reset();
private:
-
/**
*\brief Queue
*/
@@ -193,4 +194,6 @@ template<typename T, class Q> void MessageQueue<T, Q>::Reset() {
}
}
-#endif // MESSAGE_QUEUE_CLASS
+} // namespace utils
+
+#endif // SRC_COMPONENTS_INCLUDE_UTILS_MESSAGE_QUEUE_H_
diff --git a/src/components/include/utils/prioritized_queue.h b/src/components/include/utils/prioritized_queue.h
index 4bec901f59..2a8ebf0a7b 100644
--- a/src/components/include/utils/prioritized_queue.h
+++ b/src/components/include/utils/prioritized_queue.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
diff --git a/src/components/include/utils/rwlock.h b/src/components/include/utils/rwlock.h
index b5042acbfe..1083dbd63f 100644
--- a/src/components/include/utils/rwlock.h
+++ b/src/components/include/utils/rwlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,8 +30,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_RWLOCK_H_
-#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_RWLOCK_H_
+#ifndef SRC_COMPONENTS_INCLUDE_UTILS_RWLOCK_H_
+#define SRC_COMPONENTS_INCLUDE_UTILS_RWLOCK_H_
#if defined(OS_POSIX)
#include <pthread.h>
@@ -49,21 +49,91 @@ typedef pthread_rwlock_t PlatformRWLock;
#endif
} // namespace impl
+/**
+ * RW locks wrapper
+ * Read-write locks permit concurrent reads and exclusive writes to a protected shared resource.
+ * The read-write lock is a single entity that can be locked in read or write mode.
+ * To modify a resource, a thread must first acquire the exclusive write lock.
+ * An exclusive write lock is not permitted until all read locks have been released.
+ */
+
class RWLock {
public:
RWLock();
~RWLock();
- void AcquireForReading();
- void AcquireForWriting();
- void Release();
+
+ /**
+ * @brief Acqure read-write lock for reading.
+ * The calling thread acquires the read lock if a writer does not
+ * hold the lock and there are no writers blocked on the lock.
+ * It is unspecified whether the calling thread acquires the lock
+ * when a writer does not hold the lock and there are writers waiting for the lock.
+ * If a writer holds the lock, the calling thread will not acquire the read lock.
+ * If the read lock is not acquired, the calling thread blocks
+ * (that is, it does not return from the AcquireForReading()) until it can acquire the lock.
+ * Results are undefined if the calling thread holds a write lock on rwlock at the time the call is made.
+ * A thread can hold multiple concurrent read locks on rwlock
+ * (that is, successfully call AcquireForReading() n times)
+ * If so, the thread must perform matching unlocks (that is, it must call Release() n times).
+ * @returns true if lock was acquired and false if was not
+ */
+ bool AcquireForReading();
+
+ /**
+ * @brief try to Acqure read-write lock for reading.
+ * Applies a read lock as in AcquireForReading()
+ * with the exception that the function fails if any thread
+ * holds a write lock on rwlock or there are writers blocked on rwlock.
+ * But not blocks calling thread.
+ * @returns true if lock was acquired and false if was not
+ */
+ bool TryAcquireForReading();
+
+ /**
+ * @brief Try to Acqure read-write lock for writing.
+ * Applies a write lock like AcquireForWriting(), with the exception that the
+ * function fails if any thread currently holds rwlock (for reading or writing)
+ * Invoke of TryAcquireForWriting will not block calling thread and returns "false"
+ * @returns true if lock was acquired and false if was not
+ */
+ bool TryAcquireForWriting();
+
+ /**
+ * @brief Acqure read-write lock for writing.
+ * Applies a write lock to the read-write lock.
+ * The calling thread acquires the write lock if no other thread (reader or writer)
+ * holds the read-write lock rwlock. Otherwise, the thread blocks
+ * (that is, does not return from the AcquireForWriting() call)
+ * until it can acquire the lock.
+ * Results are undefined if the calling thread holds the read-write lock (whether a read or write lock)
+ * at the time the call is made.
+ * The thread must perform matching unlock (that is, it must call Release()).
+ * @returns true if lock was acquired and false if was not
+ */
+ bool AcquireForWriting();
+
+ /**
+ * @brief Release read-write lock.
+ * Releases a lock held on the read-write lock object.
+ * Results are undefined if the read-write lock rwlock
+ * is not held by the calling thread.
+ * @returns true if lock was released and false if was not
+ */
+ bool Release();
private:
impl::PlatformRWLock rwlock_;
};
+/**
+ * @brief Makes auto lock read-write locks for reading
+ * Please use AutoReadLock to acquire for reading and (automatically) release it
+ */
+
class AutoReadLock {
public:
- explicit AutoReadLock(RWLock& rwlock) : rwlock_(rwlock) {
+ explicit AutoReadLock(RWLock& rwlock)
+ : rwlock_(rwlock) {
rwlock_.AcquireForReading();
}
~AutoReadLock() {
@@ -72,13 +142,17 @@ class AutoReadLock {
private:
RWLock& rwlock_;
-
DISALLOW_COPY_AND_ASSIGN(AutoReadLock);
};
+/**
+ * @brief Makes auto lock read-write locks for writing
+ * Please use AutoWriteLock to acquire for writing and (automatically) release it
+ */
class AutoWriteLock {
public:
- explicit AutoWriteLock(RWLock& rwlock) : rwlock_(rwlock) {
+ explicit AutoWriteLock(RWLock& rwlock)
+ : rwlock_(rwlock) {
rwlock_.AcquireForWriting();
}
~AutoWriteLock() {
@@ -87,10 +161,9 @@ class AutoWriteLock {
private:
RWLock& rwlock_;
-
DISALLOW_COPY_AND_ASSIGN(AutoWriteLock);
};
} // namespace sync_primitives
-#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_RWLOCK_H_
+#endif // SRC_COMPONENTS_INCLUDE_UTILS_RWLOCK_H_
diff --git a/src/components/include/utils/shared_ptr.h b/src/components/include/utils/shared_ptr.h
index 604bee998b..f506c6018e 100644
--- a/src/components/include/utils/shared_ptr.h
+++ b/src/components/include/utils/shared_ptr.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -164,7 +164,6 @@ class SharedPtr {
operator bool() const;
void reset();
void reset(ObjectType* other);
- void release();
ObjectType* get() const;
/**
@@ -197,6 +196,8 @@ class SharedPtr {
* @brief Pointer to reference counter.
**/
uint32_t* mReferenceCounter;
+
+ void release();
};
template<typename ObjectType>
diff --git a/src/components/include/utils/threads/CMakeLists.txt b/src/components/include/utils/threads/CMakeLists.txt
new file mode 100644
index 0000000000..f97039c21b
--- /dev/null
+++ b/src/components/include/utils/threads/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(UtilsIncludeDir ${COMPONENTS_DIR/utils/include)
+
+include_directories (
+ ${UtilsIncludeDir}
+) \ No newline at end of file
diff --git a/src/components/include/utils/threads/message_loop_thread.h b/src/components/include/utils/threads/message_loop_thread.h
index e051c48904..6f90df209c 100644
--- a/src/components/include/utils/threads/message_loop_thread.h
+++ b/src/components/include/utils/threads/message_loop_thread.h
@@ -39,13 +39,16 @@
#include "utils/logger.h"
#include "utils/macro.h"
#include "utils/message_queue.h"
-#include "utils/threads/thread_manager.h"
-#include "utils/lock.h"
+#include "utils/threads/thread.h"
+#include "utils/shared_ptr.h"
namespace threads {
-/*
- * Class that handles a thread which sole purpose is to pump messages pushed
+using ::utils::MessageQueue;
+
+/**
+ * \class MessageLoopThread
+ * \brief 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.
*/
@@ -79,6 +82,10 @@ class MessageLoopThread {
// Places a message to the therad's queue. Thread-safe.
void PostMessage(const Message& message);
+
+ // Process already posted messages and stop thread processing. Thread-safe.
+ void Shutdown();
+
private:
/*
* Implementation of ThreadDelegate that actually pumps the queue and is
@@ -90,19 +97,20 @@ class MessageLoopThread {
// threads::ThreadDelegate overrides
virtual void threadMain() OVERRIDE;
- virtual bool exitThreadMain() OVERRIDE;
+ virtual void 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_;
- sync_primitives::Lock active_lock;
};
+
private:
MessageQueue<Message, Queue> message_queue_;
+ LoopThreadDelegate* thread_delegate_;
threads::Thread* thread_;
};
@@ -112,8 +120,10 @@ template<class Q>
MessageLoopThread<Q>::MessageLoopThread(const std::string& name,
Handler* handler,
const ThreadOptions& thread_opts)
- : thread_(threads::CreateThread(name.c_str(), new LoopThreadDelegate(&message_queue_, handler))) {
- bool started = thread_->startWithOptions(thread_opts);
+ : thread_delegate_(new LoopThreadDelegate(&message_queue_, handler)),
+ thread_(threads::CreateThread(name.c_str(),
+ thread_delegate_)) {
+ const bool started = thread_->start(thread_opts);
if (!started) {
CREATE_LOGGERPTR_LOCAL(logger_, "Utils")
LOG4CXX_ERROR(logger_, "Failed to start thread " << name);
@@ -122,7 +132,10 @@ MessageLoopThread<Q>::MessageLoopThread(const std::string& name,
template<class Q>
MessageLoopThread<Q>::~MessageLoopThread() {
- thread_->stop();
+ Shutdown();
+ thread_->join();
+ delete thread_delegate_;
+ threads::DeleteThread(thread_);
}
template <class Q>
@@ -130,6 +143,11 @@ void MessageLoopThread<Q>::PostMessage(const Message& message) {
message_queue_.push(message);
}
+template <class Q>
+void MessageLoopThread<Q>::Shutdown() {
+ thread_->stop();
+}
+
//////////
template<class Q>
MessageLoopThread<Q>::LoopThreadDelegate::LoopThreadDelegate(
@@ -142,8 +160,9 @@ MessageLoopThread<Q>::LoopThreadDelegate::LoopThreadDelegate(
template<class Q>
void MessageLoopThread<Q>::LoopThreadDelegate::threadMain() {
- sync_primitives::AutoLock auto_lock(active_lock);
- while(!message_queue_.IsShuttingDown()){
+ CREATE_LOGGERPTR_LOCAL(logger_, "Utils")
+ LOG4CXX_AUTO_TRACE(logger_);
+ while (!message_queue_.IsShuttingDown()) {
DrainQue();
message_queue_.wait();
}
@@ -152,18 +171,15 @@ void MessageLoopThread<Q>::LoopThreadDelegate::threadMain() {
}
template<class Q>
-bool MessageLoopThread<Q>::LoopThreadDelegate::exitThreadMain() {
+void MessageLoopThread<Q>::LoopThreadDelegate::exitThreadMain() {
+ CREATE_LOGGERPTR_LOCAL(logger_, "Utils")
+ LOG4CXX_AUTO_TRACE(logger_);
message_queue_.Shutdown();
- {
- sync_primitives::AutoLock auto_lock(active_lock);
- // Prevent canceling thread until queue is drained
- }
- return true;
}
template<class Q>
void MessageLoopThread<Q>::LoopThreadDelegate::DrainQue() {
- while(!message_queue_.empty()) {
+ while (!message_queue_.empty()) {
handler_.Handle(message_queue_.pop());
}
}
diff --git a/src/components/include/utils/threads/thread.h b/src/components/include/utils/threads/thread.h
index 3b81cf3454..fd2b5e9fd9 100644
--- a/src/components/include/utils/threads/thread.h
+++ b/src/components/include/utils/threads/thread.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,19 +43,19 @@
#include "utils/macro.h"
#include "utils/threads/thread_delegate.h"
#include "utils/threads/thread_options.h"
+#include "utils/conditional_variable.h"
+#include "utils/lock.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
+ * @brief Non platform specific thread abstraction that establishes a
* threads::ThreadDelegate on a new thread.
*
* ThreadDelegate example:
@@ -75,60 +75,72 @@ typedef pthread_t PlatformThreadHandle;
* thread.join();
* printf("ok!\n");
*/
+
class Thread;
+void enqueue_to_join(Thread* thread);
+
Thread* CreateThread(const char* name, ThreadDelegate* delegate);
-void DeleteThread(Thread*);
+void DeleteThread(Thread* thread);
class Thread {
- friend Thread* CreateThread(const char*, ThreadDelegate*);
- friend void DeleteThread(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;
- impl::PlatformThreadHandle Handle() const { return id_; }
- 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(const Id& thread_id);
-
- // Give thread thread_id a name, helpful for debugging
- static void SetNameForId(const Id& thread_id, const std::string& name);
+ private:
+ const std::string name_;
+ // Should be locked to protect delegate_ value
+ sync_primitives::Lock delegate_lock_;
+ ThreadDelegate* delegate_;
+ PlatformThreadHandle handle_;
+ ThreadOptions thread_options_;
+ // Should be locked to protect isThreadRunning_ and thread_created_ values
+ sync_primitives::Lock state_lock_;
+ volatile unsigned int isThreadRunning_;
+ volatile bool stopped_;
+ volatile bool finalized_;
+ bool thread_created_;
+ // Signalled when Thread::start() is called
+ sync_primitives::ConditionalVariable run_cond_;
+ public:
/**
- * Starts the thread.
+ * @brief Starts the thread.
* @return true if the thread was successfully started.
*/
bool start();
- ThreadDelegate* delegate() const;
-
/**
- * Starts the thread. Behaves exactly like Start in addition to
+ * @brief Starts the thread. Behaves exactly like \ref start() in addition to
* allow to override the default options.
- * @param options - thread options. Look for 'threads/thread_options.h'
+ * @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);
+ bool start(const ThreadOptions& options);
+
+ sync_primitives::Lock& delegate_lock() {
+ return delegate_lock_;
+ }
+
+ ThreadDelegate *delegate() const {
+ return delegate_;
+ }
+
+ void set_delegate(ThreadDelegate *delegate) {
+ DCHECK(!isThreadRunning_);
+ delegate_ = delegate;
+ }
+
+ friend Thread* CreateThread(const char* name, ThreadDelegate* delegate);
+ friend void DeleteThread(Thread* thread);
+
+ public:
+ // Get unique ID of currently executing thread
+ static PlatformThreadHandle CurrentId();
+
+ // Give thread thread_id a name, helpful for debugging
+ static void SetNameForId(const PlatformThreadHandle& thread_id,
+ std::string name);
/**
- * Signals the thread to exit and returns once the thread has exited.
+ * @brief 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).
*
@@ -137,16 +149,18 @@ class Thread {
*/
void stop();
+ void join();
+
/**
- * Get thread name.
+ * @brief Get thread name.
* @return thread name
*/
- const std::string& thread_name() {
+ const std::string& name() {
return name_;
}
/**
- * Returns true if the thread has been started, and not yet stopped.
+ * @brief 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.
*/
@@ -154,12 +168,10 @@ class Thread {
return isThreadRunning_;
}
- void set_running(bool running) {
- isThreadRunning_ = running;
- }
+ void set_running(bool running);
/**
- * Is thread joinable?
+ * @brief Is thread joinable?
* @return - Returns true if the thread is joinable.
*/
bool is_joinable() const {
@@ -167,7 +179,7 @@ class Thread {
}
/**
- * Thread stack size
+ * @brief Thread stack size
* @return thread stack size
*/
size_t stack_size() const {
@@ -175,23 +187,15 @@ class Thread {
}
/**
- * The native thread handle.
+ * @brief 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());
+ PlatformThreadHandle thread_handle() const {
+ return handle_;
}
/**
- * Thread options.
+ * @brief Thread options.
* @return thread options.
*/
const ThreadOptions& thread_options() const {
@@ -199,16 +203,12 @@ class Thread {
}
/**
- * Minimum size of thread stack for specific platform.
+ * @brief Minimum size of thread stack for specific platform.
*/
static size_t kMinStackSize;
protected:
- const std::string name_;
- ThreadDelegate* delegate_;
- impl::PlatformThreadHandle thread_handle_;
- ThreadOptions thread_options_;
- volatile unsigned int isThreadRunning_;
+ sync_primitives::ConditionalVariable state_cond_;
private:
/**
@@ -216,19 +216,17 @@ class Thread {
* @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.
+ * LifeCycle thread , otherwise it will be joined in stop method
+ * NOTE: delegate will be deleted after thread will be joined
* This constructor made private to prevent
* Thread object to be created on stack
*/
Thread(const char* name, ThreadDelegate* delegate);
-
+ virtual ~Thread();
+ static void* threadFunc(void* arg);
+ static void cleanup(void* arg);
DISALLOW_COPY_AND_ASSIGN(Thread);
- virtual ~Thread() { }
};
-inline bool operator!= (const Thread::Id& left, const Thread::Id& right) {
- return !(left == right);
-}
-std::ostream& operator<<(std::ostream& os, const Thread::Id& thread_id);
} // namespace threads
#endif // SRC_COMPONENTS_INCLUDE_UTILS_THREADS_THREAD_H_
diff --git a/src/components/include/utils/threads/thread_delegate.h b/src/components/include/utils/threads/thread_delegate.h
index 47e68f1e83..66ad30241c 100644
--- a/src/components/include/utils/threads/thread_delegate.h
+++ b/src/components/include/utils/threads/thread_delegate.h
@@ -35,30 +35,66 @@
#include <pthread.h>
+#include "utils/lock.h"
+
namespace threads {
+enum ThreadState {
+ kInit = 0,
+ kStarted = 1,
+ kStopReq = 2
+};
+
+class Thread;
+
/**
* Thread procedure interface.
* Look for "threads/thread.h" for example
*/
class ThreadDelegate {
- public:
+ public:
+ ThreadDelegate()
+ : state_(kInit),
+ thread_(NULL) {
+ }
+ /**
+ * \brief Thread procedure.
+ */
+ virtual void threadMain() = 0;
+
+ /**
+ * Should be called to free all resources allocated in threadMain
+ * and exiting threadMain
+ * This function should be blocking and return only when threadMain() will be
+ * finished in other case segmantation failes are possible
+ */
+ virtual void exitThreadMain();
- /**
- * Thread procedure.
- */
- virtual void threadMain() = 0;
+ virtual ~ThreadDelegate();
- /**
- * Should be called to free all resources allocated in threadMain
- * and exiting threadMain
- * This function should be blocking and return only when threadMain() will be
- * finished in other case segmantation failes are possible
- */
- virtual bool exitThreadMain() {
- return false;
+ Thread* thread() const {
+ return thread_;
+ }
+
+ void set_thread(Thread *thread);
+
+ bool ImproveState(unsigned int to) {
+ state_lock_.Lock();
+ if ((state_ + 1 == to) || (to == kInit && state_ == kStopReq)) {
+ state_ = to;
}
- virtual ~ThreadDelegate() { }
+ state_lock_.Unlock();
+ return state_ == to;
+ }
+
+ unsigned int state() const {
+ return state_;
+ }
+
+ private:
+ volatile unsigned int state_;
+ sync_primitives::SpinMutex state_lock_;
+ Thread* thread_;
};
} // namespace threads
diff --git a/src/components/include/utils/threads/thread_options.h b/src/components/include/utils/threads/thread_options.h
index 217f0815a9..797ee0693b 100644
--- a/src/components/include/utils/threads/thread_options.h
+++ b/src/components/include/utils/threads/thread_options.h
@@ -38,7 +38,7 @@
namespace threads {
/**
- * @breif Startup options for thread.
+ * @brief Startup options for thread.
* Look for "threads/thread.h" for example
*/
class ThreadOptions {
@@ -74,7 +74,7 @@ class ThreadOptions {
* @param options - new options.
* @return new options.
*/
- ThreadOptions& operator=(const ThreadOptions& options ) {
+ ThreadOptions& operator=(const ThreadOptions& options) {
stack_size_ = options.stack_size();
is_joinable_ = options.is_joinable();
return *this;
diff --git a/src/components/include/utils/timer_thread.h b/src/components/include/utils/timer_thread.h
index a3481e4b4b..eaa67effe2 100644
--- a/src/components/include/utils/timer_thread.h
+++ b/src/components/include/utils/timer_thread.h
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2013, Ford Motor Company
+/*
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,15 +28,16 @@
* 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
+#ifndef SRC_COMPONENTS_INCLUDE_UTILS_TIMER_THREAD_H_
+#define SRC_COMPONENTS_INCLUDE_UTILS_TIMER_THREAD_H_
#include <time.h>
#include <inttypes.h>
#include <cstdint>
#include <limits>
+#include <string>
#include "utils/conditional_variable.h"
#include "utils/lock.h"
@@ -52,8 +53,9 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
class TimerDelegate;
-/*
- * The TimerThread class provide possibility to run timer in a separate thread.
+/**
+ * \class TimerThread
+ * \brief TimerThread class provide possibility to run timer in a separate thread.
* The client should specify callee and const callback function.
* Example usage:
*
@@ -67,315 +69,345 @@ class TimerDelegate;
* To stop timer call timer.stop();
*
*/
-template <class T>
+template<class T>
class TimerThread {
- public:
-
- friend class TimerDelegate;
- friend class TimerLooperDelegate;
-
+ public:
+ friend class TimerDelegate;
+ friend class TimerLooperDelegate;
+
+ /**
+ * @brief Default constructor
+ *
+ * @param name - display string to identify the thread.
+ * @param callee A class that use timer
+ * @param f CallBackFunction which will be called on timeout
+ * Attention! "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 looper,
+ * if true, TimerThread will call "f()" function every time out
+ * until stop()
+ */
+ TimerThread(const char* name, 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 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
+ *
+ * @param callee A class that use timer
+ *
+ * @param allBackFunction which will be called on timeout
+ * Attention! "f()" will be called not in main thread but in timer thread
+ * Never use stop() and start() methods inside f
+ */
+ virtual void start(uint32_t timeout_seconds, T* callee, void (T::*f)());
+
+ /**
+ * @brief Stops timer execution
+ * Must not be used in callback function!
+ */
+ virtual void stop();
+
+ /**
+ * @brief Tell timer status
+ * @return true if timer is currently running, otherwise return false
+ */
+ virtual bool isRunning();
+
+ /**
+ * @brief method suspends timer execution
+ */
+ virtual void pause();
+
+ /**
+ * @brief Stop timer update timeout and start timer again
+ * Note that it cancel thread of timer, If you use it from callback,
+ * it probably will stop execution of callback function
+ * @param timeout_seconds new timeout value
+ *
+ */
+ virtual void updateTimeOut(const uint32_t timeout_seconds);
+
+ 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 name - display string to identify the thread.
- * @param callee A class that use timer
- * @param f CallBackFunction which will be called on timeout
- * Attention! "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 looper,
- * if true, TimerThread will call "f()" function every time out
- * until stop()
+ * @param timer_thread The Timer_thread pointer
*/
- TimerThread(const char* name, T* callee , void (T::*f)(), bool is_looper = false);
+ explicit TimerDelegate(TimerThread* timer_thread);
/**
* @brief Destructor
*/
- virtual ~TimerThread();
+ virtual ~TimerDelegate();
/**
- * @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
+ * @brief Thread main function.
*/
- virtual void start(uint32_t timeout_seconds);
+ virtual void threadMain();
/**
- * @brief Stops timer execution
- * Must not be used in callback function!
+ * @brief Called by thread::thread to free all allocated resources.
*/
- virtual void stop();
+ virtual void exitThreadMain();
/**
- * @brief Tell tmer status
- * @return true if timer is currently running, otherwise return false
+ * @brief Set new Timeout
+ * @param timeout_seconds New timeout to be set
*/
- virtual bool isRunning();
-
- /*
- * @brief Stop timer update timeout and start timer again
- * Note that it cancel thread of timer, If you use it from callback,
- * it probably will stop execution of callback function
- * @param timeout_seconds new timeout value
- *
- */
- virtual void updateTimeOut(const uint32_t timeout_seconds);
- threads::Thread* thread_;
- protected:
-
- /**
- * @brief Interface called by delegator on timeout
- */
- void onTimeOut() const;
-
- private:
-
+ virtual void setTimeOut(const uint32_t timeout_seconds);
+
+ protected:
+ TimerThread* timer_thread_;
+ uint32_t timeout_seconds_;
+ sync_primitives::Lock state_lock_;
+ sync_primitives::ConditionalVariable termination_condition_;
+ volatile bool stop_flag_;
+ int32_t calculateMillisecondsLeft();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TimerDelegate);
+ };
+
+ /**
+ * @brief Delegate release looper timer.
+ * Will call delegate every timeout function while stop()
+ * won't be called
+ */
+ class TimerLooperDelegate : public TimerDelegate {
+ public:
/**
- * @brief Delegate release timer, will call callback function one time
+ * @brief Default constructor
+ *
+ * @param timer_thread The Timer_thread pointer
+ * @param timeout Timeout to be set
*/
- class TimerDelegate : public threads::ThreadDelegate {
- public:
-
- /**
- * @brief Default constructor
- *
- * @param timer_thread The Timer_thread pointer
- */
- TimerDelegate(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 Set new Timeout
- * @param timeout_seconds New timeout to be set
- */
- virtual void setTimeOut(const uint32_t timeout_seconds);
-
- protected:
- TimerThread* timer_thread_;
- uint32_t timeout_seconds_;
- sync_primitives::Lock state_lock_;
- sync_primitives::ConditionalVariable termination_condition_;
- volatile bool stop_flag_;
- int32_t calculateMillisecondsLeft();
- private:
- DISALLOW_COPY_AND_ASSIGN(TimerDelegate);
- };
-
+ explicit TimerLooperDelegate(TimerThread* timer_thread);
/**
- * @brief Delegate release looper timer.
- * Will call delegate every timeout function while stop()
- * won't be called
+ * @brief Thread main function.
*/
- class TimerLooperDelegate : public TimerDelegate {
- public:
-
- /**
- * @brief Default constructor
- *
- * @param timer_thread The Timer_thread pointer
- * @param timeout Timeout to be set
- */
- TimerLooperDelegate(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_;
- std::string name_;
- mutable bool is_running_;
- bool is_looper_;
-
- DISALLOW_COPY_AND_ASSIGN(TimerThread);
+ virtual void threadMain();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TimerLooperDelegate);
+ };
+ threads::Thread* thread_;
+ void (T::*callback_)();
+ T* callee_;
+ TimerDelegate* delegate_;
+ std::string name_;
+ volatile bool is_looper_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimerThread);
};
-template <class T>
-TimerThread<T>::TimerThread(const char* name, T* callee, void (T::*f)(), bool is_looper)
- : thread_(NULL),
- callback_(f),
- callee_(callee),
- delegate_(NULL),
- is_running_(false),
- is_looper_(is_looper) {
+template<class T>
+TimerThread<T>::TimerThread(const char* name, T* callee, void (T::*f)(),
+ bool is_looper)
+ : thread_(NULL),
+ callback_(f),
+ callee_(callee),
+ delegate_(NULL),
+ name_(name),
+ is_looper_(is_looper) {
+ delegate_ =
+ is_looper_ ? new TimerLooperDelegate(this) : new TimerDelegate(this);
+
+ thread_ = threads::CreateThread(name_.c_str(), delegate_);
}
-template <class T>
+template<class T>
TimerThread<T>::~TimerThread() {
- LOG4CXX_INFO(logger_, "TimerThread is to destroy " << name_);
- stop();
+ LOG4CXX_DEBUG(logger_, "TimerThread is to be destroyed " << name_);
+ thread_->join();
+ delete delegate_;
+ threads::DeleteThread(thread_);
callback_ = NULL;
callee_ = NULL;
}
-template <class T>
+template<class T>
void TimerThread<T>::start(uint32_t timeout_seconds) {
- LOG4CXX_TRACE(logger_, "Starting timer " << this);
- if (is_running_) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (isRunning()) {
LOG4CXX_INFO(logger_, "TimerThread start needs stop " << name_);
stop();
}
+ updateTimeOut(timeout_seconds);
+ thread_->start();
+}
- delegate_ = is_looper_ ?
- new TimerLooperDelegate(this) :
- new TimerDelegate(this);
- delegate_->setTimeOut(timeout_seconds);
-
- thread_ = threads::CreateThread("TimerThread", delegate_);
- if (delegate_ && thread_) {
- is_running_ = true;
- thread_->start();
- }
+template<class T>
+void TimerThread<T>::start(uint32_t timeout_seconds, T* callee,
+ void (T::*f)()) {
+ callee_ = callee;
+ callback_ = f;
+ start(timeout_seconds);
}
-template <class T>
+template<class T>
void TimerThread<T>::stop() {
- LOG4CXX_TRACE(logger_, "Stopping timer " << this);
- if (is_running_ && delegate_ && thread_) {
- LOG4CXX_INFO(logger_, "TimerThread thread_ stop " << name_);
- thread_->stop();
- is_running_ = false;
- } else {
- LOG4CXX_INFO(logger_, "TimerThread thread_ not stop " << name_);
- }
+ LOG4CXX_AUTO_TRACE(logger_);
+ DCHECK(thread_);
+ LOG4CXX_DEBUG(logger_, "Stopping timer " << name_);
+ thread_->join();
}
-template <class T>
+template<class T>
bool TimerThread<T>::isRunning() {
- return is_running_;
+ DCHECK(thread_);
+ return thread_->is_running();
+}
+
+template<class T>
+void TimerThread<T>::pause() {
+ LOG4CXX_DEBUG(logger_, "Suspension of timer " << name_);
+ const uint32_t wait_seconds = std::numeric_limits<uint32_t>::max();
+ updateTimeOut(wait_seconds);
}
-template <class T>
+template<class T>
void TimerThread<T>::updateTimeOut(const uint32_t timeout_seconds) {
delegate_->setTimeOut(timeout_seconds);
}
-template <class T>
-void TimerThread<T>::onTimeOut() const {
+template<class T> void TimerThread<T>::onTimeOut() const {
if (callee_ && callback_) {
(callee_->*callback_)();
- /*
- if (!is_looper_) {
- stop();
- }
- */
}
}
-template <class T>
+template<class T>
TimerThread<T>::TimerDelegate::TimerDelegate(TimerThread* timer_thread)
- : timer_thread_(timer_thread),
- timeout_seconds_(0),
- state_lock_(true),
- stop_flag_(false) {
+ : timer_thread_(timer_thread),
+ timeout_seconds_(0),
+ state_lock_(true),
+ stop_flag_(false) {
DCHECK(timer_thread_);
}
-template <class T>
-TimerThread<T>::TimerLooperDelegate::TimerLooperDelegate(TimerThread* timer_thread)
- : TimerDelegate(timer_thread) {
+template<class T>
+TimerThread<T>::TimerLooperDelegate::TimerLooperDelegate(
+ TimerThread* timer_thread)
+ : TimerDelegate(timer_thread) {
}
-template <class T>
+template<class T>
TimerThread<T>::TimerDelegate::~TimerDelegate() {
timer_thread_ = NULL;
}
-template <class T>
+template<class T>
void TimerThread<T>::TimerDelegate::threadMain() {
using sync_primitives::ConditionalVariable;
sync_primitives::AutoLock auto_lock(state_lock_);
+ stop_flag_ = false;
while (!stop_flag_) {
// Sleep
- int32_t wait_milliseconds_left = TimerDelegate::calculateMillisecondsLeft();
+ int32_t wait_milliseconds_left = TimerDelegate::calculateMillisecondsLeft();
ConditionalVariable::WaitStatus wait_status =
termination_condition_.WaitFor(auto_lock, wait_milliseconds_left);
// Quit sleeping or continue sleeping in case of spurious wake up
- if (ConditionalVariable::kTimeout == wait_status ||
- wait_milliseconds_left <= 0) {
- break;
+ if (ConditionalVariable::kTimeout == wait_status
+ || wait_milliseconds_left <= 0) {
+ LOG4CXX_TRACE(logger_,
+ "Timer timeout " << wait_milliseconds_left << " ms");
+ timer_thread_->onTimeOut();
+ return;
+ } else {
+ LOG4CXX_DEBUG(logger_,
+ "Timeout reset force: " << TimerDelegate::timeout_seconds_);
+ return;
}
}
- if (!stop_flag_) {
- timer_thread_->onTimeOut();
- timer_thread_->stop();
- }
}
-template <class T>
+template<class T>
void TimerThread<T>::TimerLooperDelegate::threadMain() {
using sync_primitives::ConditionalVariable;
sync_primitives::AutoLock auto_lock(TimerDelegate::state_lock_);
+ TimerDelegate::stop_flag_ = false;
while (!TimerDelegate::stop_flag_) {
- int32_t wait_milliseconds_left = TimerDelegate::calculateMillisecondsLeft();
+ int32_t wait_milliseconds_left = TimerDelegate::calculateMillisecondsLeft();
ConditionalVariable::WaitStatus wait_status =
- TimerDelegate::termination_condition_.WaitFor(auto_lock, wait_milliseconds_left);
+ TimerDelegate::termination_condition_.WaitFor(auto_lock,
+ wait_milliseconds_left);
// Quit sleeping or continue sleeping in case of spurious wake up
- if (ConditionalVariable::kTimeout == wait_status ||
- wait_milliseconds_left <= 0) {
- LOG4CXX_TRACE(logger_, "Timer timeout " << wait_milliseconds_left);
+ if (ConditionalVariable::kTimeout == wait_status
+ || wait_milliseconds_left <= 0) {
+ LOG4CXX_TRACE(logger_,
+ "Timer timeout " << wait_milliseconds_left << " ms");
TimerDelegate::timer_thread_->onTimeOut();
} else {
- LOG4CXX_DEBUG(logger_, "Timeout reset force: " << TimerDelegate::timeout_seconds_);
+ LOG4CXX_DEBUG(logger_,
+ "Timeout reset force: " << TimerDelegate::timeout_seconds_);
}
}
}
-
-template <class T>
-bool TimerThread<T>::TimerDelegate::exitThreadMain() {
+template<class T>
+void TimerThread<T>::TimerDelegate::exitThreadMain() {
sync_primitives::AutoLock auto_lock(state_lock_);
stop_flag_ = true;
termination_condition_.NotifyOne();
- return true;
}
-template <class T>
+template<class T>
void TimerThread<T>::TimerDelegate::setTimeOut(const uint32_t timeout_seconds) {
timeout_seconds_ = timeout_seconds;
termination_condition_.NotifyOne();
}
-template <class T>
+template<class T>
int32_t TimerThread<T>::TimerThread::TimerDelegate::calculateMillisecondsLeft() {
time_t cur_time = time(NULL);
time_t end_time = std::numeric_limits<time_t>::max();
- if (TimerDelegate::timeout_seconds_ + cur_time > TimerDelegate::timeout_seconds_) { // no overflow occurred
+ if (TimerDelegate::timeout_seconds_ + cur_time
+ > TimerDelegate::timeout_seconds_) { // no overflow occurred
end_time = cur_time + TimerDelegate::timeout_seconds_;
}
- int64_t wait_seconds_left = static_cast<int64_t>(difftime(end_time, cur_time));
- int32_t wait_milliseconds_left = std::numeric_limits<int32_t>::max();
- const int32_t millisecconds_in_second = 1000;
- if (wait_seconds_left < std::numeric_limits<int32_t>::max() / millisecconds_in_second) {
- wait_milliseconds_left = millisecconds_in_second * wait_seconds_left;
+ int64_t wait_seconds_left = static_cast<int64_t>(difftime(end_time, cur_time));
+ int32_t wait_milliseconds_left = std::numeric_limits<int32_t>::max();
+ const int32_t milliseconds_in_second = 1000;
+ if (wait_seconds_left
+ < std::numeric_limits<int32_t>::max() / milliseconds_in_second) {
+ wait_milliseconds_left = milliseconds_in_second * wait_seconds_left;
}
return wait_milliseconds_left;
}
} // namespace timer
-#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_TIMER_THREAD
+#endif // SRC_COMPONENTS_INCLUDE_UTILS_TIMER_THREAD_H_