Search code examples
c++linuxatomic

Allocating a atomic on shared memory


I am trying to allocate a atomic on a shared memory block (on linux). The atomic will be accessed and modified my multiple threads simultaneously. The rational behind allocating it on shared memory is because I want to persist the values so if my process is restarted the previous state can be recovered. I know for a fact if i use a mutex in shared memory i have to initialize it as a SHARED. Is there any such requirement for atomics? Is this feasible?


Solution

  • Yes, you can do that. Here is an example I ripped from Quora (ripped code from Quora), not my code and includes boost so I have not tested it:

    #include <atomic>
    #include <string>
    #include <iostream>
    #include <cstdlib>
    #include <boost/interprocess/managed_shared_memory.hpp>
    
    using namespace std::string_literals;
    namespace bip = boost::interprocess;
    static_assert(ATOMIC_INT_LOCK_FREE == 2,
                  "atomic_int must be lock-free");
    int main(int argc, char *argv[])
    {
      if(argc == 1) //Parent process
      {
        struct shm_remove {
          shm_remove() { bip::shared_memory_object::remove("szMem");}
          ~shm_remove(){ bip::shared_memory_object::remove("szMem");}
        } remover;
        bip::managed_shared_memory segment(bip::create_only,
                                           "szMem", 65536);
        auto ap = segment.construct<std::atomic_int>("the counter")(0);
        //Launch 5 child processes
        std::string s = argv[0] +" child"s;
        std::system((s + '&' + s + '&' + s + '&' + s + '&' + s).c_str());
        std::cout << "parent existing: counter = " << *ap << '\n';
        segment.destroy<std::atomic_int>("the counter");
     } else { // child
        bip::managed_shared_memory segment(bip::open_only, "szMem");
        auto res = segment.find<std::atomic_int>("the counter");
        for(int n = 0; n < 100000; ++n)
            ++*res.first; // C++17 will remove the dumb "first"
        std::cout << "child exiting, counter = " << *res.first << '\n';
      }
    }
    

    Here is documentation: link to Boost docs