├── .gitattributes ├── .gitignore ├── .travis.yml ├── Build.bat ├── Build.sh ├── CMakeLists.txt ├── LICENSE ├── README.md ├── Singleton ├── Includes │ └── Singleton │ │ ├── Private │ │ └── SpinLock.hpp │ │ └── Singleton.hpp └── Sources │ └── Test.cpp └── appveyor.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | *.cpp text 7 | *.hpp text 8 | *.cfg text 9 | 10 | ############################################################################### 11 | # Set the merge driver for project and solution files 12 | # 13 | # Merging from the command prompt will add diff markers to the files if there 14 | # are conflicts (Merging from VS is not affected by the settings below, in VS 15 | # the diff markers are never inserted). Diff markers may cause the following 16 | # file extensions to fail to load in VS. An alternative would be to treat 17 | # these files as binary and thus will always conflict and require user 18 | # intervention with every merge. To do so, just uncomment the entries below 19 | ############################################################################### 20 | #*.sln merge=binary 21 | #*.csproj merge=binary 22 | #*.vbproj merge=binary 23 | #*.vcxproj merge=binary 24 | #*.vcproj merge=binary 25 | #*.dbproj merge=binary 26 | #*.fsproj merge=binary 27 | #*.lsproj merge=binary 28 | #*.wixproj merge=binary 29 | #*.modelproj merge=binary 30 | #*.sqlproj merge=binary 31 | #*.wwaproj merge=binary 32 | 33 | ############################################################################### 34 | # behavior for image files 35 | # 36 | # image files are treated as binary by default. 37 | ############################################################################### 38 | #*.jpg binary 39 | #*.png binary 40 | #*.gif binary 41 | 42 | ############################################################################### 43 | # diff behavior for common document formats 44 | # 45 | # Convert binary document formats to text before diffing them. This feature 46 | # is only available from the command line. Turn it on by uncommenting the 47 | # entries below. 48 | ############################################################################### 49 | #*.doc diff=astextplain 50 | #*.DOC diff=astextplain 51 | #*.docx diff=astextplain 52 | #*.DOCX diff=astextplain 53 | #*.dot diff=astextplain 54 | #*.DOT diff=astextplain 55 | #*.pdf diff=astextplain 56 | #*.PDF diff=astextplain 57 | #*.rtf diff=astextplain 58 | #*.RTF diff=astextplain -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | /Debug 30 | 31 | Binaries 32 | Objects 33 | Dependencies 34 | ole32.pdb 35 | *~ 36 | #*# 37 | *.out 38 | *.dep 39 | *.opp 40 | *.ini 41 | TAGS 42 | 43 | #OS junk files 44 | [Tt]humbs.db 45 | *.DS_Store 46 | #Visual Studio files 47 | *.[Oo]bj 48 | *.user 49 | *.aps 50 | *.pch 51 | *.vspscc 52 | *.vssscc 53 | *_i.c 54 | *_p.c 55 | *.ncb 56 | *.suo 57 | *.tlb 58 | *.tlh 59 | *.bak 60 | *.[Cc]ache 61 | *.ilk 62 | *.log 63 | *.tlog 64 | *.sbr 65 | *.sdf 66 | *.opensdf 67 | *.unsuccessfulbuild 68 | ipch/ 69 | [Oo]bj/ 70 | [Bb]in 71 | [Dd]ebug*/ 72 | [Rr]elease*/ 73 | Ankh.NoLoad 74 | 75 | #MonoDevelop 76 | *.pidb 77 | *.userprefs 78 | 79 | #Tooling 80 | _ReSharper*/ 81 | *.resharper 82 | [Tt]est[Rr]esult* 83 | *.sass-cache 84 | 85 | #Project files 86 | [Bb]uild/ 87 | 88 | #NuGet 89 | packages/ 90 | *.nupkg 91 | 92 | #ncrunch 93 | *ncrunch* 94 | *crunch*.local.xml 95 | 96 | # visual studio database projects 97 | *.dbmdl 98 | 99 | #Test files 100 | *.testsettings -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: 2 | - cpp 3 | compiler: 4 | - gcc 5 | - clang 6 | before_install: 7 | - sudo apt-add-repository -y ppa:jkeiren/ppa 8 | - if test $CC = gcc; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi 9 | - sudo apt-get update -qq 10 | install: 11 | - if test $CC = gcc; then sudo apt-get install --yes --force-yes gcc-4.8 g++-4.8; fi 12 | - if test $CC = gcc; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20; fi 13 | - if test $CC = gcc; then sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 20; fi 14 | - if test $CC = gcc; then sudo update-alternatives --config gcc; fi 15 | - if test $CC = gcc; then sudo update-alternatives --config g++; fi 16 | before_script: 17 | - mkdir Build 18 | - cd Build 19 | - cmake .. 20 | script: 21 | - make 22 | - make test -------------------------------------------------------------------------------- /Build.bat: -------------------------------------------------------------------------------- 1 | mkdir Build 2 | cd Build 3 | cmake .. -G "Visual Studio 14" 4 | cmake --build . 5 | ctest . -------------------------------------------------------------------------------- /Build.sh: -------------------------------------------------------------------------------- 1 | mkdir Build 2 | cd Build 3 | cmake .. 4 | cmake --build . 5 | ctest . -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) 4 | 5 | project(Singleton) 6 | 7 | if (MSVC) 8 | 9 | else() 10 | include(CheckCXXCompilerFlag) 11 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 12 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) 13 | if (COMPILER_SUPPORTS_CXX11) 14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 15 | elseif (COMPILER_SUPPORTS_CXX0X) 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 17 | else () 18 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 19 | endif () 20 | endif () 21 | 22 | set(Singleton_HDRS 23 | ${PROJECT_SOURCE_DIR}/Singleton/Includes/Singleton/Singleton.hpp) 24 | 25 | source_group(Includes FILES ${Singleton_HDRS}) 26 | 27 | set(Singleton_Private_HDRS 28 | ${PROJECT_SOURCE_DIR}/Singleton/Includes/Singleton/Private/SpinLock.hpp) 29 | 30 | source_group(Includes\\Private FILES ${Singleton_Private_HDRS}) 31 | 32 | set(HDRS 33 | ${Singleton_HDRS} 34 | ${Singleton_Private_HDRS}) 35 | 36 | set(SRCS 37 | ${PROJECT_SOURCE_DIR}/Singleton/Sources/Test.cpp) 38 | 39 | source_group(Sources FILES ${SRCS}) 40 | 41 | include_directories("$(PROJECT_SOURCE_DIR)/Singleton/Includes") 42 | 43 | add_executable(SingletonTest ${SRCS} ${HDRS}) 44 | 45 | enable_testing() 46 | 47 | add_test(SingletonUnitTests SingletonTest) 48 | 49 | set_tests_properties(SingletonUnitTests 50 | PROPERTIES PASS_REGULAR_EXPRESSION "Success!") 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jonathan Herpêche 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Singleton [![Build Status](https://travis-ci.org/herpec-j/Singleton.svg?branch=master)](https://travis-ci.org/herpec-j/Singleton) [![Build Status](https://ci.appveyor.com/api/projects/status/github/herpec-j/Singleton?branch=master&svg=true)](https://ci.appveyor.com/project/herpec-j/singleton) 2 | Simple Singleton implementation using C++11. 3 | Compatible with Visual Studio 2015, g++4.8, and clang++3.4. 4 | An example of use and documentation are coming. 5 | -------------------------------------------------------------------------------- /Singleton/Includes/Singleton/Private/SpinLock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace AO 6 | { 7 | namespace Singleton 8 | { 9 | inline namespace Version_1 10 | { 11 | namespace Private 12 | { 13 | class SpinLock final 14 | { 15 | public: 16 | // Constructors 17 | inline SpinLock(void) 18 | : atomicLock(false) 19 | { 20 | return; 21 | } 22 | 23 | SpinLock(SpinLock const &) = default; 24 | 25 | SpinLock(SpinLock &&) = default; 26 | 27 | // Assignment Operators 28 | SpinLock &operator=(SpinLock const &) = default; 29 | 30 | SpinLock &operator=(SpinLock &&) = default; 31 | 32 | // Destructor 33 | ~SpinLock(void) = default; 34 | 35 | // Methods 36 | inline void lock(void) 37 | { 38 | while (atomicLock.exchange(true)); 39 | } 40 | 41 | inline void unlock(void) 42 | { 43 | atomicLock = false; 44 | } 45 | 46 | inline bool isLocked(void) const 47 | { 48 | return atomicLock; 49 | } 50 | 51 | private: 52 | // Attributes 53 | std::atomic_bool atomicLock; 54 | }; 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Singleton/Includes/Singleton/Singleton.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Singleton/Private/SpinLock.hpp" 6 | 7 | namespace AO 8 | { 9 | namespace Singleton 10 | { 11 | inline namespace Version_1 12 | { 13 | template 14 | class Singleton 15 | { 16 | public: 17 | // Static Methods 18 | template 19 | static inline Derived &GetInstance(Args &&...args) 20 | { 21 | return *GetInstancePointer(std::forward(args)...); 22 | } 23 | 24 | template 25 | static inline Derived *GetInstancePointer(Args &&...args) 26 | { 27 | static Derived *instancePointer = CreateInstance(std::forward(args)...); 28 | return instancePointer; 29 | } 30 | 31 | protected: 32 | using Access = Singleton; 33 | 34 | // Constructors 35 | Singleton(void) = default; 36 | 37 | Singleton(Singleton const &) = default; 38 | 39 | Singleton(Singleton &&) = default; 40 | 41 | // Assignment Operators 42 | Singleton &operator=(Singleton const &) = default; 43 | 44 | Singleton &operator=(Singleton &&) = default; 45 | 46 | // Destructor 47 | virtual ~Singleton(void) = default; 48 | 49 | private: 50 | // Static Attributes 51 | static Derived *InstancePointer; 52 | 53 | static Private::SpinLock Lock; 54 | 55 | // Static Methods 56 | template 57 | static inline Derived *CreateInstance(Args &&...args) 58 | { 59 | if (Singleton::InstancePointer == nullptr) 60 | { 61 | std::lock_guard lock(Singleton::Lock); 62 | if (Singleton::InstancePointer == nullptr) 63 | { 64 | void *data = static_cast(GetData()); 65 | new (data) Derived(std::forward(args)...); 66 | Singleton::InstancePointer = reinterpret_cast(data); 67 | std::atexit(&Singleton::DestroyInstance); 68 | } 69 | } 70 | return Singleton::InstancePointer; 71 | } 72 | 73 | static inline void DestroyInstance(void) 74 | { 75 | reinterpret_cast(GetData())->~Derived(); 76 | } 77 | 78 | static inline unsigned char *GetData(void) 79 | { 80 | static unsigned char data[sizeof(Derived)]; 81 | return data; 82 | } 83 | }; 84 | 85 | template 86 | Derived *Singleton::InstancePointer = nullptr; 87 | 88 | template 89 | Private::SpinLock Singleton::Lock; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Singleton/Sources/Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "Singleton/Singleton.hpp" 7 | 8 | static char const *__success = "Success!"; 9 | static std::queue __letters; 10 | static std::stack __numbers; 11 | 12 | template 13 | class Class final : public AO::Singleton::Singleton < Class > 14 | { 15 | private: 16 | friend typename Class::Access; 17 | 18 | // Constructors 19 | Class(void) 20 | { 21 | initialize(); 22 | __numbers.push(N); 23 | __letters.push(*__success++); 24 | } 25 | 26 | Class(Class const &) = default; 27 | 28 | Class(Class &&) = default; 29 | 30 | // Assignment Operators 31 | Class &operator=(Class const &) = default; 32 | 33 | Class &operator=(Class &&) = default; 34 | 35 | // Destructor 36 | ~Class(void) 37 | { 38 | assert(__numbers.top() == N && "Invalid destruction order"); 39 | __numbers.pop(); 40 | std::cout << __letters.front(); 41 | __letters.pop(); 42 | if (__letters.empty()) 43 | { 44 | std::cout << std::endl; 45 | } 46 | } 47 | 48 | // Methods 49 | void initialize(void) const; 50 | }; 51 | 52 | template <> 53 | void Class<1>::initialize(void) const 54 | { 55 | Class<4>::GetInstance(); 56 | Class<6>::GetInstance(); 57 | } 58 | 59 | template <> 60 | void Class<2>::initialize(void) const 61 | { 62 | return; 63 | } 64 | 65 | template <> 66 | void Class<3>::initialize(void) const 67 | { 68 | Class<1>::GetInstance(); 69 | } 70 | 71 | template <> 72 | void Class<4>::initialize(void) const 73 | { 74 | Class<2>::GetInstance(); 75 | } 76 | 77 | template <> 78 | void Class<5>::initialize(void) const 79 | { 80 | return; 81 | } 82 | 83 | template <> 84 | void Class<6>::initialize(void) const 85 | { 86 | return; 87 | } 88 | 89 | template <> 90 | void Class<7>::initialize(void) const 91 | { 92 | Class<8>::GetInstance(); 93 | } 94 | 95 | template <> 96 | void Class<8>::initialize(void) const 97 | { 98 | Class<6>::GetInstance(); 99 | Class<5>::GetInstance(); 100 | Class<3>::GetInstance(); 101 | } 102 | 103 | int main(int argc, char *argv[]) 104 | { 105 | Class<1>::GetInstance(); 106 | Class<2>::GetInstance(); 107 | Class<3>::GetInstance(); 108 | Class<4>::GetInstance(); 109 | Class<5>::GetInstance(); 110 | Class<6>::GetInstance(); 111 | Class<7>::GetInstance(); 112 | Class<8>::GetInstance(); 113 | return EXIT_SUCCESS; 114 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - Visual Studio 2015 CTP 3 | branches: 4 | only: 5 | - master 6 | install: 7 | - set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% 8 | before_build: 9 | - mkdir Build 10 | - cd Build 11 | - cmake .. -G "Visual Studio 14" 12 | build_script: 13 | - msbuild Singleton.sln /nologo /verbosity:minimal 14 | test_script: 15 | - msbuild RUN_TESTS.vcxproj /nologo /verbosity:minimal 16 | --------------------------------------------------------------------------------