Skip to content

Instantly share code, notes, and snippets.

@shotamatsuda
Created November 8, 2014 05:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shotamatsuda/bbab93e6cc41716534fb to your computer and use it in GitHub Desktop.
Save shotamatsuda/bbab93e6cc41716534fb to your computer and use it in GitHub Desktop.
A class to make singletons in a fairly safe manner
//
// sgss/singleton_holder.h
//
// MIT License
//
// Copyright (C) 2014 Shota Matsuda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#pragma once
#ifndef SGSS_SINGLETON_HOLDER_H_
#define SGSS_SINGLETON_HOLDER_H_
#include <boost/thread/mutex.hpp>
#include <functional>
namespace sgss {
template <typename T>
class SingletonHolder {
public:
using Type = T;
// Constructors
SingletonHolder();
template <typename Allocator>
explicit SingletonHolder(Allocator allocator);
template <typename Allocator, typename Deleter>
SingletonHolder(Allocator allocator, Deleter deleter);
~SingletonHolder();
// Accessing value
T& operator*() { return *get(); }
T * operator->() { return get(); }
T * get();
private:
// Disallow copy and assign
SingletonHolder& operator=(const SingletonHolder&);
SingletonHolder(const SingletonHolder&);
// Data members
T *value_;
std::function<T *()> allocator_;
std::function<void(T *)> deleter_;
boost::mutex mutex_;
};
#pragma mark - Inline Implementations
template <typename T>
inline SingletonHolder<T>::SingletonHolder()
: value_(nullptr),
allocator_([]() { return new T; }),
deleter_([](T *value) { delete value; }) {}
template <typename T>
template <typename Allocator>
inline SingletonHolder<T>::SingletonHolder(Allocator allocator)
: value_(nullptr),
allocator_(allocator),
deleter_([](T *value) { delete value; }) {}
template <typename T>
template <typename Allocator, typename Deleter>
inline SingletonHolder<T>::SingletonHolder(Allocator allocator, Deleter deleter)
: value_(nullptr),
allocator_(allocator),
deleter_(deleter) {}
template <typename T>
inline SingletonHolder<T>::~SingletonHolder() {
deleter_(value_);
}
template <typename T>
inline T * SingletonHolder<T>::get() {
boost::mutex::scoped_lock lock(mutex_);
if (!value_) {
value_ = allocator_();
}
return value_;
}
} // namespace sgss
#endif // SGSS_SINGLETON_HOLDER_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment