title: Making processes wait until resource is loaded into shared memory using Boost.Interprocess
body: <p>Suppose I have <code>n</code> processes with IDs <code>1</code> to <code>n</code>. I have a file with lots of data, where each process will only store a disjoint subset of the data. I would like to load and process the file using exactly one process, store the resulting data in a data structure allocated via Boost.Interprocess in shared memory, and then allow any (including the one who loaded the file) process to read from the data.</p>
  <p>For this to work, I need to make use of some of the Boost.Interprocess synchronization constructs located <a href="https://www.boost.org/doc/libs/1_76_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions" rel="nofollow noreferrer">here</a> to ensure processes do not try to read the data before it has been loaded. However, I am struggling with this part and it is likely due to my lack of experience in this area. At the moment, I have <code>process(1)</code> loading the file into shared memory and I need a way to ensure any given process cannot read the file contents until the load is complete, even if the read might happen arbitrarily long after the loading occurs.</p>
  <p>I wanted to try and use a combination of a mutex and condition variable using the <code>notify_all</code> call so that <code>process(1)</code> can signal to the other processes it is okay to read from the shared memory data, but this seems to have an issue in that <code>process(1)</code> might send a <code>notify_all</code> call before some <code>process(i)</code> has even tried to <code>wait</code> for the condition variable to signal it is okay to read the data.</p>
  <p>Any ideas for how to approach this in a reliable manner?</p>
  <p><strong>Edit 1</strong></p>
  <p>Here is my attempt to clarify my dilemma and express more clearly what I have tried. I have some class that I allocate into a shared memory space using Boost.Interprocess that has a form similar to the below:</p>
  <pre><code>namespace bi = boost::interprocess;
  
  class cache {
  public:
     
     cache() = default;
     ~cache() = default;
  
     void set_process_id(std::size_t ID) { id = ID; }
  
     void load_file(const std::string&amp; filename) {
        
        // designated process to load
        // file has ID equal to 0
        if( id == 0 ){
            
           // lock using the mutex
           bi::scoped_lock&lt;bi::interprocess_mutex&gt; lock(m);
           
           // do work to process the file and
           // place result in the data variable
  
           // after processing file, notify all other
           // processes that they can access the data
           load_cond.notify_all();
  
        }
  
  
     }
     void read_into(std::array&lt;double, 100&gt;&amp; data_out) {
         { // wait to read data until load is complete
            // lock using the mutex
            bi::scoped_lock&lt;bi::interprocess_mutex&gt; lock(m);
            load_cond.wait(lock);
         }
  
         data_out = data;
     }
  
  private:
     
     size_t id;
     std::array&lt;double, 100&gt; data;
     bi::interprocess_mutex m;
     bi::interprocess_condition load_cond;
  
  };
  </code></pre>
  <p>The above is roughly what I had when I asked the question but did not sit well with me because if the <code>read_into</code> method was called after the designated process executes the <code>notify_all</code> call, then the <code>read_into</code> would be stuck. What I just did this morning that seems to fix this dilemma is change this class to the following:</p>
  <pre><code>namespace bi = boost::interprocess;
  
  class cache {
  public:
     
     cache():load_is_complete(false){}
     ~cache() = default;
  
     void set_process_id(std::size_t ID) { id = ID; }
  
     void load_file(const std::string&amp; filename) {
        
        // designated process to load
        // file has ID equal to 0
        if( id == 0 ){
            
           // lock using the mutex
           bi::scoped_lock&lt;bi::interprocess_mutex&gt; lock(m);
           
           // do work to process the file and
           // place result in the data variable
  
           // after processing file, notify all other
           // processes that they can access the data
           load_is_complete = true;
           load_cond.notify_all();
  
        }
  
  
     }
     void read_into(std::array&lt;double, 100&gt;&amp; data_out) {
         { // wait to read data until load is complete
            // lock using the mutex
            bi::scoped_lock&lt;bi::interprocess_mutex&gt; lock(m);
            if( not load_is_complete ){
               load_cond.wait(lock);
            }
         }
  
         data_out = data;
     }
  
  private:
     
     size_t id;
     std::array&lt;double, 100&gt; data;
     bool load_is_complete;
     bi::interprocess_mutex m;
     bi::interprocess_condition load_cond;
  
  };
  </code></pre>
  <p>Not sure if the above is the most elegant, but I believe it should ensure processes cannot access the data being stored in shared memory until it has completed loading, whether they get to the mutex <code>m</code> before the designated process or after the designated process has loaded the file contents. If there is a more elegant way, I would like to know.</p>