// 싱글톤 : 객체가 하나만 생성되게 한다.
// Mayer의singleton( stack 이용 )
class MouseCursor
{
private:
        MouseCursor() {}
public:
        static MouseCursor& GetInstance()
        {
               static MouseCursor m;
               return m;
        }
};
void main()
{
        MouseCursor& m1 = MouseCursor::GetInstance();
        MouseCursor& m2 = MouseCursor::GetInstance();
}
//heap 공간에singleton 구현하기
#include <iostream>
using namespace std;
class Singleton
{
private:
        static Singleton* m_cursor;
        Singleton() {} 
        Singleton(const Singleton&); 
        ~Singleton()
        {
               if ( m_cursor != NULL )
               {
                       delete m_cursor;
               }
        }  
public:
        static Singleton* GetInstance() 
        {
               if (m_cursor == NULL)
                       m_cursor = new Singleton();
               return m_cursor;
        }
};
Singleton* Singleton::m_cursor = NULL;
void main()
{
        Singleton* single1 = Singleton::GetInstance();
        Singleton* single2 = Singleton::GetInstance();
}
// Double Checked Locking Singleton( 윈도우- 멀티스레드환경대비)
// 객체를 생성할 때 CRITICAL_SECTION 으로 감싸준다.
#include <iostream>
#include <windows.h>
using namespace std;
class CriticalSection
{
private:
        CRITICAL_SECTION cs;
public:
        CriticalSection() { InitializeCriticalSection(&cs); }
        ~CriticalSection() { DeleteCriticalSection(&cs); }
        void Enter()
        {
               EnterCriticalSection(&cs);
        }
        void Leave()
        {
               LeaveCriticalSection(&cs);
        }
};
CriticalSection g_cs;
class Singleton
{
private:
        static Singleton* m_cursor;
        
        Singleton() {} 
        Singleton(const Singleton&); 
        ~Singleton()
        {
               if ( m_cursor != NULL )
               {
                       delete m_cursor;
               }
        }  
public:
        static Singleton* GetInstance() 
        {
               if (m_cursor == NULL)
               {
                       m_cursor = new Singleton();
               }
               return m_cursor;
        }
};
Singleton* Singleton::m_cursor = NULL;
DWORD WINAPI SingletonProc(void* pv)
{
        Singleton* pSingle = NULL;
        while (1)
        {
               if (pSingle == NULL)
               {
                       g_cs.Enter();
                       pSingle = Singleton::GetInstance();
                       cout << "Singleton create : " << pSingle << endl;
                       g_cs.Leave();
               }
               Sleep(0);
        }
        return 0;
}
void main()
{
        HANDLE hThread[2];
        hThread[0] = CreateThread( NULL, 0, SingletonProc, NULL, 0, NULL );
        hThread[1] = CreateThread( NULL, 0, SingletonProc, NULL, 0, NULL );
        WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
        CloseHandle(hThread[0]);
        CloseHandle(hThread[1]); 
}