#ifndef _SHARED_MEMORY_HPP
#define _SHARED_MEMORY_HPP

#define SHARED_MEM_SIZE 65536

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <string>

namespace SHAREDMEMORY
{
    using namespace boost::interprocess;

    class SharedMemory {
    public:

        static SharedMemory& Instance()
        {
            static SharedMemory _instance;
            return _instance;
        }

        static void PurgeSharedMemory()
        {
            shared_memory_object::remove("KEY");
        }

        void SetSettings(const std::string& sKey, const std::string& sValue)
        {
            shared_memory_object shm(open_or_create, sKey.c_str(), read_write);
            shm.truncate(SHARED_MEM_SIZE);
            mapped_region region(shm, read_write);

            std::memset(region.get_address(), 0, SHARED_MEM_SIZE);
            std::memcpy(region.get_address(), sValue.c_str(), sValue.size());
        }

        void GetSettings(const std::string& sKey, std::string& sValue)
        {
            try
            {
                shared_memory_object shm(open_only, sKey.c_str(), read_only);
                mapped_region region(shm, read_only);

                char* str = static_cast<char*>(region.get_address());
                sValue.assign(str, strlen(str));
            }
            catch (...) {}
        }

        std::string GetKey()
        {
            return "KEY";
        }

        void DemonstrationOfSharingEntireClassObject()
        {
            // Arrange
            shared_memory_object shm(open_or_create, "TEST_SELF_OBJ", read_write);
            shm.truncate(SHARED_MEM_SIZE);
            mapped_region region(shm, read_write);

            // Store it
            std::memset(region.get_address(), 0, SHARED_MEM_SIZE);
            std::memcpy(region.get_address(), this, sizeof(this));

            // Retrieve it
            auto ptr = static_cast<SharedMemory*>(region.get_address());
            if (ptr)
            {
                // display something
                std::string str;

                // notice i make use of ptr pointer, which is pointer to the class object!
                ptr->GetSettings(ptr->GetKey(), str);
                printf("Key: [%s] Value[%s]", ptr->GetKey().c_str(), str.c_str());
            }
        }

    private:

        SharedMemory()
        { }

    private:

        // no private members!
    };
}

#endif