Apollo Singleton Macro
#ifndef CYBER_COMMON_MACROS_H_
#define CYBER_COMMON_MACROS_H_
#include <iostream>
#include <memory>
#include <mutex>
#include <type_traits>
#include <utility>
#include "cyber/base/macros.h"
DEFINE_TYPE_TRAIT(HasShutdown, Shutdown)
template <typename T>
typename std::enable_if<HasShutdown<T>::value>::type CallShutdown(T *instance) {
instance->Shutdown();
}
template <typename T>
typename std::enable_if<!HasShutdown<T>::value>::type CallShutdown(
T *instance) {
(void)instance;
}
// There must be many copy-paste versions of these macros which are same
// things, undefine them to avoid conflict.
#undef UNUSED
#undef DISALLOW_COPY_AND_ASSIGN
#define UNUSED(param) (void)param
#define DISALLOW_COPY_AND_ASSIGN(classname) \
classname(const classname &) = delete; \
classname &operator=(const classname &) = delete;
#define DECLARE_SINGLETON(classname) \
public: \
static classname *Instance(bool create_if_needed = true) { \
static classname *instance = nullptr; \
if (!instance && create_if_needed) { \
static std::once_flag flag; \
std::call_once(flag, \
[&] { instance = new (std::nothrow) classname(); }); \
} \
return instance; \
} \
\
static void CleanUp() { \
auto instance = Instance(false); \
if (instance != nullptr) { \
CallShutdown(instance); \
} \
} \
\
private: \
classname(); \
DISALLOW_COPY_AND_ASSIGN(classname)
#endif // CYBER_COMMON_MACROS_H_
细节分析
- 为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:”=delete”函数。程序员只需在函数声明后上“=delete;”,就可将该函数禁用。
class X3 { public: X3(); X3(const X3&) = delete; // 声明拷贝构造函数为 deleted 函数 X3& operator = (const X3 &) = delete; // 声明拷贝赋值操作符为 deleted 函数 };
- 在多线程编程中,有一个常见的情景是某个任务只需要执行一次。在C++11中提供了很方便的辅助类once_flag,call_once。
#include <iostream> #include <thread> #include <mutex> std::once_flag flag; void do_once() { //也可以写在这里。要记住static,一旦flag被销毁了就不能保证只执行一次了 //static std::once_flag flag; std::call_once(flag, [](){ std::cout << "Called once" << std::endl; }); } int main() { std::thread t1(do_once); std::thread t2(do_once); std::thread t3(do_once); std::thread t4(do_once); t1.join(); t2.join(); t3.join(); t4.join(); } //可以看到,只会输出一行Called once