在 其他工具类二 中我们介绍了辅助性的工具类,如:通用文件操作的 File
类,通用字符串操作的 Str
类等。今天我们来看看线程安全相关类。
线程安全相关类都在 namespace el::base::threading
。
这里为了可移植性,考虑到 C++11
之前的和 C++11
之后所使用 API
的差异性都作了相应封装。 具体包括以下类:
- 通用互斥量
Mutex
- 加锁接口
lock
- 尝试加锁接口
try_lock
- 解锁接口
unlock
- 加锁接口
- 通用区间锁
ScopedLock
- 线程安全基类
ThreadSafe
(仅能被继承)- 加锁接口:
acquireLock
- 解锁接口:
releaseLock
- 获取锁接口:
lock
- 加锁接口:
- 获取当前线程
ID
通用接口(返回线程id
的字符串):getCurrentThreadId
C++11
之后启用线程安全并且支持标准库的线程情况下,Mutex
和 ScopedLock
的类型定义如下:
typedef std::recursive_mutex Mutex;
typedef std::lock_guard<base::threading::Mutex> ScopedLock;
线程安全相关类的实现如下:
namespace threading
{
#if ELPP_THREADING_ENABLED
#if !ELPP_USE_STD_THREADING
namespace internal
{
/// @brief A mutex wrapper for compiler that dont yet support std::recursive_mutex
class Mutex : base::NoCopy
{
public:
Mutex(void)
{
#if ELPP_OS_UNIX
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_underlyingMutex, &attr);
pthread_mutexattr_destroy(&attr);
#elif ELPP_OS_WINDOWS
InitializeCriticalSection(&m_underlyingMutex);
#endif // ELPP_OS_UNIX
}
virtual ~Mutex(void)
{
#if ELPP_OS_UNIX
pthread_mutex_destroy(&m_underlyingMutex);
#elif ELPP_OS_WINDOWS
DeleteCriticalSection(&m_underlyingMutex);
#endif // ELPP_OS_UNIX
}
inline void lock(void)
{
#if ELPP_OS_UNIX
pthread_mutex_lock(&m_underlyingMutex);
#elif ELPP_OS_WINDOWS
EnterCriticalSection(&m_underlyingMutex);
#endif // ELPP_OS_UNIX
}
inline bool try_lock(void)
{
#if ELPP_OS_UNIX
return (pthread_mutex_trylock(&m_underlyingMutex) == 0);
#elif ELPP_OS_WINDOWS
return TryEnterCriticalSection(&m_underlyingMutex);
#endif // ELPP_OS_UNIX
}
inline void unlock(void)
{
#if ELPP_OS_UNIX
pthread_mutex_unlock(&m_underlyingMutex);
#elif ELPP_OS_WINDOWS
LeaveCriticalSection(&m_underlyingMutex);
#endif // ELPP_OS_UNIX
}
private:
#if ELPP_OS_UNIX
pthread_mutex_t m_underlyingMutex;
#elif ELPP_OS_WINDOWS
CRITICAL_SECTION m_underlyingMutex;
#endif // ELPP_OS_UNIX
};
/// @brief Scoped lock for compiler that dont yet support std::lock_guard
template <typename M>
class ScopedLock : base::NoCopy
{
public:
explicit ScopedLock(M &mutex)
{
m_mutex = &mutex;
m_mutex->lock();
}
virtual ~ScopedLock(void)
{
m_mutex->unlock();
}
private:
M *m_mutex;
ScopedLock(void);
};
} // namespace internal
typedef base::threading::internal::Mutex Mutex;
typedef base::threading::internal::ScopedLock<base::threading::Mutex> ScopedLock;
#else
typedef std::recursive_mutex Mutex;
typedef std::lock_guard<base::threading::Mutex> ScopedLock;
#endif // !ELPP_USE_STD_THREADING
#else
namespace internal
{
/// @brief Mutex wrapper used when multi-threading is disabled.
class NoMutex : base::NoCopy
{
public:
NoMutex(void) {}
inline void lock(void) {}
inline bool try_lock(void)
{
return true;
}
inline void unlock(void) {}
};
/// @brief Lock guard wrapper used when multi-threading is disabled.
template <typename Mutex>
class NoScopedLock : base::NoCopy
{
public:
explicit NoScopedLock(Mutex &)
{
}
virtual ~NoScopedLock(void)
{
}
private:
NoScopedLock(void);
};
} // namespace internal
typedef base::threading::internal::NoMutex Mutex;
typedef base::threading::internal::NoScopedLock<base::threading::Mutex> ScopedLock;
#endif // ELPP_THREADING_ENABLED
/// @brief Base of thread safe class, this class is inheritable-only
class ThreadSafe
{
public:
virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); }
virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); }
virtual inline base::threading::Mutex &lock(void) ELPP_FINAL { return m_mutex; }
protected:
ThreadSafe(void) {}
virtual ~ThreadSafe(void) {}
private:
base::threading::Mutex m_mutex;
};
#if ELPP_THREADING_ENABLED
#if !ELPP_USE_STD_THREADING
/// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned.
static std::string getCurrentThreadId(void)
{
std::stringstream ss;
#if (ELPP_OS_WINDOWS)
ss << GetCurrentThreadId();
#endif // (ELPP_OS_WINDOWS)
return ss.str();
}
#else
/// @brief Gets ID of currently running threading using std::this_thread::get_id()
static std::string getCurrentThreadId(void)
{
std::stringstream ss;
ss << std::this_thread::get_id();
return ss.str();
}
#endif // !ELPP_USE_STD_THREADING
#else
static inline std::string getCurrentThreadId(void)
{
return std::string();
}
#endif // ELPP_THREADING_ENABLED
} // namespace threading
上面的代码考虑到未启用线程安全,跨平台和系统不支持标准库线程的情况,出现了很多条件编译分支,代码本身并不复杂。
线程安全相关类到这里就介绍完了。至此,easylogging++的源码就差不多分析完了,剩下的一些类模板的源码我会在后面的设计理念篇逐一介绍。
标签:++,lock,void,easylogging,源码,mutex,Mutex,OS,ELPP From: https://www.cnblogs.com/DesignLife/p/16970566.html