BaseSingleton.h
#ifndef BASESINGLETON_H
#define BASESINGLETON_H
#include <typeindex>
#include "base_export.h"
#include <mutex>
//class BASE_EXPORT BaseObject
// Singleton mode for cpp
//
// Features --
// 1. Works for both dynamical library and executable.
// 2. Multithread safe
// 3. Lazy consturction
BASE_EXPORT void getSharedInstance(const std::type_index &typeIndex,
void *(*getStaticInstance)(),
void *&instance);
template<typename T>
class BaseSingleton
{
public:
static T* Instance()
{
static void* instance = nullptr;
if (instance == nullptr)
{
getSharedInstance(typeid(T), &getStaticInstance, instance);
}
return reinterpret_cast<T *>(instance);
}
private:
static void* getStaticInstance()
{
static T t;
return reinterpret_cast<void *>(&reinterpret_cast<char &>(t));
}
};
template<typename T>
inline T* singleton()
{
return BaseSingleton<T>::Instance();
}
#define Singleton(T) BaseSingleton<T>::Instance()
#endif // BASESINGLETON_H
BaseSingleton.cpp
#include "BaseSingleton.h"
#include <typeinfo>
#include <unordered_map>
#include <mutex>
#include <memory>
#include <iostream>
namespace {
struct SingleTonHolder
{
void* object_;
std::shared_ptr<std::mutex> mutex_;
};
}
static std::mutex& getSingleTonMutex()
{
// Global mutex
// s_singleTonMutex is not 100% safety for multithread
// but if there's any singleton object used before thread, it's safe enough.
static std::mutex s_singleTonMutex;
return s_singleTonMutex;
}
static SingleTonHolder* getSingleTonType(const std::type_index &typeIndex)
{
static std::unordered_map<std::type_index, SingleTonHolder> s_singleObjects;
// Check the old value
std::unordered_map<std::type_index, SingleTonHolder>::iterator itr = s_singleObjects.find(typeIndex);
if (itr != s_singleObjects.end())
{
// std::cout<<__FUNCTION__<<__LINE__<<"======find====="<<typeIndex.name()<<std::endl;
return &itr->second;
}
// Create new one if no old value
std::pair<std::type_index, SingleTonHolder> singleHolder( typeIndex, SingleTonHolder() );
itr = s_singleObjects.insert(singleHolder).first;
SingleTonHolder& singleTonHolder = itr->second;
singleTonHolder.object_ = nullptr;
singleTonHolder.mutex_ = std::shared_ptr<std::mutex>(new std::mutex());
return &singleTonHolder;
}
void getSharedInstance(const std::type_index &typeIndex,
void *(*getStaticInstance)(),
void *&instance)
{
// Get the single instance
SingleTonHolder* singleTonHolder = nullptr;
{
// Locks and get the global mutex
std::lock_guard<std::mutex> myLock(getSingleTonMutex());
if (instance != nullptr)
{
return;
}
singleTonHolder = getSingleTonType(typeIndex);
}
// Create single instance
{
// Locks class T and make sure to call construction only once
std::lock_guard<std::mutex> myLock(*singleTonHolder->mutex_);
if (singleTonHolder->object_ == nullptr)
{
// construct the instance with static funciton
singleTonHolder->object_ = (*getStaticInstance)();
}
}
// Save single instance object
{
std::lock_guard<std::mutex> myLock(getSingleTonMutex());
instance = singleTonHolder->object_;
}
}
base_export.h
#ifndef BASE_EXPORT_H
#define BASE_EXPORT_H
#ifdef BASE_STATIC_DEFINE
# define BASE_EXPORT
# define BASE_NO_EXPORT
#else
# ifndef BASE_EXPORT
# ifdef Base_EXPORTS
/* We are building this library */
# define BASE_EXPORT __declspec(dllexport)
# else
/* We are using this library */
# define BASE_EXPORT __declspec(dllimport)
# endif
# endif
# ifndef BASE_NO_EXPORT
# define BASE_NO_EXPORT
# endif
#endif
#ifndef BASE_DEPRECATED
# define BASE_DEPRECATED __declspec(deprecated)
#endif
#ifndef BASE_DEPRECATED_EXPORT
# define BASE_DEPRECATED_EXPORT BASE_EXPORT BASE_DEPRECATED
#endif
#ifndef BASE_DEPRECATED_NO_EXPORT
# define BASE_DEPRECATED_NO_EXPORT BASE_NO_EXPORT BASE_DEPRECATED
#endif
#if 0 /* DEFINE_NO_DEPRECATED */
# ifndef BASE_NO_DEPRECATED
# define BASE_NO_DEPRECATED
# endif
#endif
#endif /* BASE_EXPORT_H */