[Boost-bugs] [Boost C++ Libraries] #12476: Using named_condition_any with a readers-writer lock

Subject: [Boost-bugs] [Boost C++ Libraries] #12476: Using named_condition_any with a readers-writer lock
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-09-21 14:01:32


#12476: Using named_condition_any with a readers-writer lock
----------------------------------------------+--------------------------
 Reporter: Chris Evans <chris.evans@…> | Owner: igaztanaga
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: interprocess
  Version: Boost 1.58.0 | Severity: Problem
 Keywords: interprocess named_condition_any |
----------------------------------------------+--------------------------
 I am trying to use condition variables to signify updated data in a
 managed_shared_memory segment. I have one "writer" and multiple "readers"
 of the shared state, so I am using a readers-writer lock.

 Unfortunately, although the code compiles, the reader processes are never
 awakened from wait() and block forever.

 It seems named_condition_any may be incompatible with
 named_sharable_mutex, scoped_lock, sharable_lock, or some combination of
 the three. Attached is a producer and consumer process that demonstrates
 the behavior. Run the producer first, then run the consumer.

 Expected behavior: consumer process will print values for "copy of int"
 every 2 seconds (as producer updates)

 Observed behavior: consumer process blocks on named_condition_any::wait()
 and never awakens.

 Including the code here in case the attachments don't go through:

 PRODUCER:
 {{{
 #include <thread>
 #include <chrono>
 #include <iostream>

 #include <boost/interprocess/sync/scoped_lock.hpp>
 #include <boost/interprocess/sync/named_mutex.hpp>
 #include <boost/interprocess/sync/named_sharable_mutex.hpp>
 #include <boost/interprocess/sync/sharable_lock.hpp>
 #include <boost/interprocess/sync/named_condition_any.hpp>
 #include <boost/interprocess/managed_shared_memory.hpp>

 namespace bi = boost::interprocess;
 using SharedMutex = bi::named_sharable_mutex;
 using ReadLock = bi::sharable_lock<SharedMutex>;
 using WriteLock = bi::scoped_lock<SharedMutex>;
 using NewEntryCondition = bi::named_condition_any;

 constexpr char SHM_NAME[] = "shared_mem";
 constexpr char MUT_NAME[] = "shm_mut";
 constexpr char COND_NAME[] = "shm_cond";
 constexpr char CUR_INT_NAME[] = "shm_int";


 int main(int argc, char *argv[])
 {
     // Remove the shared mem, condition variable, mutex
     struct shm_remove
     {
         shm_remove() { bi::shared_memory_object::remove( SHM_NAME ); }
         ~shm_remove() { bi::shared_memory_object::remove( SHM_NAME ); }
     } remover;
     struct mut_remove
     {
         mut_remove() { SharedMutex::remove(MUT_NAME); }
         ~mut_remove() { SharedMutex::remove(MUT_NAME); }
     } mut_remover;

     struct cond_remove
     {
         cond_remove() { NewEntryCondition::remove(COND_NAME); }
         ~cond_remove() { NewEntryCondition::remove(COND_NAME); }
     } cond_remover;

     // Create the shared mem, condition variable, mutex
     bi::managed_shared_memory segment(bi::create_only, SHM_NAME, 2*65536);
     SharedMutex sh_mut(bi::create_only, MUT_NAME);
     NewEntryCondition sh_cond(bi::create_only, COND_NAME);

     int& shared_int = *segment.construct<int>("shared_int")(0);

     for (int i=0;;i++) {
         std::this_thread::sleep_for(std::chrono::seconds(2));

         {
             WriteLock w_lock( sh_mut );

             shared_int = i;
             std::cout << "set shared_int to: " << shared_int << std::endl;

             sh_cond.notify_all();
         }

     }



     return 0;
 }
 }}}

 CONSUMER:

 {{{
 #include <thread>
 #include <chrono>
 #include <iostream>

 #include <boost/interprocess/sync/scoped_lock.hpp>
 #include <boost/interprocess/sync/named_mutex.hpp>
 #include <boost/interprocess/sync/named_sharable_mutex.hpp>
 #include <boost/interprocess/sync/sharable_lock.hpp>
 #include <boost/interprocess/sync/named_condition_any.hpp>
 #include <boost/interprocess/managed_shared_memory.hpp>

 namespace bi = boost::interprocess;
 using SharedMutex = bi::named_sharable_mutex;
 using ReadLock = bi::sharable_lock<SharedMutex>;
 using WriteLock = bi::scoped_lock<SharedMutex>;
 using NewEntryCondition = bi::named_condition_any;

 constexpr char SHM_NAME[] = "shared_mem";
 constexpr char MUT_NAME[] = "shm_mut";
 constexpr char COND_NAME[] = "shm_cond";
 constexpr char CUR_INT_NAME[] = "shm_int";


 int main(int argc, char *argv[])
 {
     // Open the shared mem, condition variable, mutex
     bi::managed_shared_memory segment(bi::open_only, SHM_NAME);
     SharedMutex sh_mut(bi::open_only, MUT_NAME);
     NewEntryCondition sh_cond(bi::open_only, COND_NAME);

     int& shared_int = *segment.find<int>("shared_int").first;
     int copy_of_int = -1;

     for (int i=0;;i++) {
         {
             ReadLock r_lock( sh_mut );

             std::cout << "calling named_condition_any::wait()" <<
 std::endl;
             sh_cond.wait(
                     r_lock,
                     [&shared_int, &copy_of_int]() {
                         std::cout << "checking predicate..." << std::endl;
                         return (copy_of_int < shared_int);
                     });

             copy_of_int = shared_int;
             std::cout << "copy of int = " << copy_of_int << std::endl;
         }

     }

     return 0;
 }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/12476>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:20 UTC