#include <iostream>
#include <algorithm>
#include <utility>

typedef long LONG;
typedef int BOOL;

struct STOP_FLAG
{
    STOP_FLAG()
        : shared(new Shared())
    {
    }
    
    ~STOP_FLAG()
    {
        shared->release();
    }

    STOP_FLAG(const STOP_FLAG& s)
        : shared((s.shared->grab(), s.shared))
    {
    }
    
    // assignment operator by copy/swap idiom
    STOP_FLAG& operator = (STOP_FLAG s)
    {
        std::swap(shared, s.shared);
        return *this;
    }
    
private:
    struct Shared
    {
        BOOL value;
        LONG refCount;
        
        Shared() : value(), refCount()
        {
            grab();
        }
        
        void grab()
        {
            std::cout << '\t' << __PRETTY_FUNCTION__ << ':' << refCount+1 << '\n';
            ++refCount;
        }
        
        void release()
        {
            std::cout << '\t' << __PRETTY_FUNCTION__ << ':' << refCount-1 << '\n';
            if (!--refCount)
                delete this;
        }
        
    } *shared;
};

int main()
{
    std::cout << "STOP_FLAG sf;" << '\n';
    STOP_FLAG sf;
    {
        std::cout << "STOP_FLAG s2(sf);" << '\n';
        STOP_FLAG s2(sf);
        
        std::cout << "s2 = sf;" << '\n';
        s2 = sf;
        
        std::cout << "STOP_FLAG s3;" << '\n';
        STOP_FLAG s3;
        
        std::cout << "s3 = s2;" << '\n';
        s3 = s2;
        
        std::cout << "STOP_FLAG s4[3];" << '\n';
        STOP_FLAG s4[3];
        
        std::cout << "s4[0] = s3;" << '\n';
        s4[0] = s3;
        std::cout << "s4[1] = s3;" << '\n';
        s4[1] = s3;
        std::cout << "s4[2] = s3;" << '\n';
        s4[2] = s3;
        
        std::cout << "STOP_FLAG s5;" << '\n';
        STOP_FLAG s5;

        std::cout << "s3 = s5;" << '\n';
        s3 = s5;

        std::cout << "scope exiting\n";
    }
    std::cout << "scope exited\n";
}