Provided by: libbobcat-dev_6.02.02-1_amd64 bug

NAME

       FBB::SharedCondition - Shared Memory Condition Variable

SYNOPSIS

       #include <bobcat/sharedcondition>
       Linking option: -lpthread, -lbobcat

DESCRIPTION

       Condition variables are used to synchronize threads based on the values of data. Condition
       variables allow threads to wait until a certain condition has occurred,  after  which  the
       threads  continue  their actions. Thus waiting threads don’t continuously have to poll the
       state of a variable (requiring the threads to gain access to the variable before they  can
       inspect  its  value). Using condition variables waiting threads simply wait until they are
       notified.

       SharedCondition objects can be used in combination  with  shared  memory.  SharedCondition
       objects interface to objects (called Condition objects in this man-page) which are defined
       in shared memory and contain a SharedMutex and a shared condition object. These  Condition
       objects  may  be  accessed  by  threads  running  in  different processes. These different
       processes might run a single main thread, or they themselves can be multi-threaded.

       Condition variables are used in situations like these:

       o      There exists a thread which should be suspended until a certain condition has  been
              met.

       o      This thread locks a mutex (or waits until the lock has been obtained)

       o      While  the  condition  hasn’t  been  met,  the  thread  is suspended (i.e., waits),
              automatically releasing the mutex’s lock.

       o      Somehow (see  below)  the  thread  is  resumed,  at  which  point  the  thread  has
              automatically reacquired the lock.

       o      Once  the  condition  has  been  met,  the while loop ends, and the mutex’s lock is
              released.

       o      There exists a second thread, which influences the variables that are  elements  of
              the condition, and which may notify the waiting thread, once the required condition
              has been met.

       o      This second thread locks the same mutex as used by the first thread.

       o      The second thread modifies the variables that are involved,  and  if  the  required
              condition has been met, it notifies the first thread.

       o      The  second  thread  releases the mutex’s lock, allowing the first thread to obtain
              the mutex’s lock.

       While the first thread is waiting, it is suspended. It may be resumed when it  receives  a
       notification  from  another  thread,  but  also  for spurious reasons. Therefore the first
       thread must verify that the condition has been met after resuming its actions.

       As  condition  variables  are  always  used  in  combination  with  a  mutex,  SharedMutex
       encapsulates  the  mutex-handling. The software using SharedCondition objects doesn’t have
       to handle the mutex itself.

       SharedCondition objects are used to synchronize  actions  by  different  processes,  using
       shared  memory  as  their  vehicle  of synchronization/communication. The actual condition
       variable  that  is  used  by  a  SharedCondition  object  is  defined  in  shared  memory.
       SharedCondition objects themselves are small objects, containing the necessary information
       to access the actual shared memory condition variable.

NAMESPACE

       FBB
       All constructors, members, operators and manipulators, mentioned  in  this  man-page,  are
       defined in the namespace FBB.

INHERITS FROM

       SharedMutex(3bobcat)

CONSTRUCTORS, DESTRUCTOR

       o      SharedCondition():
              The  default  constructor  creates  an  empty  stub which cannot yet be used (or an
              FBB::Exception  is  thrown).  As  the  SharedCondition  class  supports  assignment
              operators,  empty  stubs  can  easily  be  (re)configured  at  any time after their
              construction.

       o      ~SharedCondition():
              The class’s destructor releases (if applicable) its lock on  the  shared  condition
              variables  mutex  lock.  The  destructor  takes no action if its object is an empty
              stub.

       Default, copy, and move constructors as well as the copy and move assignment operators are
       available.

MEMBER FUNCTIONS

       Returning  from  SharedCondition member functions the offset of the SharedMemory object in
       which the condition variable has been defined has not  changed.  Internally,  the  current
       offset is saved; the requested function is performed; and the original offset is restored.
       Consequently, SharedCondition member functions can be used disregarding the SharedMemory’s
       current offset.

       o      void lock() const:
              When returning from this member, the current process has locked the SharedCondition
              object. Be careful not to call lock twice during the same thread of execution  (cf.
              sharedmutex(3bobcat) for details).

       o      void notify() noexept:
              One  of  the  threads  waiting  on  the SharedCondition object wakes up. The thread
              calling notify should release its mutex lock shortly after calling notify, allowing
              the  notified  thread  to  obtain  the  lock.  A  prototypical piece of pseudo code
              illustrating the use of notify looks like this:

                  sharedCondition.lock();     // lock the mutex
                  ...                         // operate on the condition’s variables
                  if (conditionWasMet)        // ready to notify
                      sharedCondition.notify();
                  sharedCondition.unlock();   // release the lock

              As the sharedCondition.lock  ...  sharedCondition.unlock  sequence  itself  may  be
              executed  at different flow of control sections, the unlock member cannot be called
              from within notify.

       o      void notifyAll() noexept:
              Different from the plain notify member, this member wakes up  all  of  the  threads
              waiting  on  the  SharedCondition  object.  However,  after  the current thread has
              released its mutex lock only one of these signaled threads will actually obtain the
              lock. The pseudo code for using notifyAll is identical to the pseudo code for using
              notify (i.e., calling notifyAll, of course).

       o      std::streamsize offset() const:
              The location of the shared condition variable (within the SharedMemory  object)  is
              returned.  The shared condition object ends at offset() + SharedCondition::width(),
              see below.

       o      void unlock() const:
              The object’s lock is released (nothing happens if called when  the  current  object
              does not have the object’s  lock).

       o      void wait():
              Before  calling  wait  the  current  thread  should  have  obtained  a  lock on the
              SharedCondition object.

              When calling wait the running thread suspends its activities and waits until  being
              notified.  Once  notified, it reacquires the lock and continues. Shortly after this
              the process should again release its lock on the SharedCondition object.   lock.  A
              prototypical piece of pseudo code illustrating how to use wait looks like this:

                  sharedCondition.lock();         // lock the mutex
                  while (conditionWasNotYetMet)   // waiting required
                      sharedCondition.wait();
                  ...                             // do something: we have the lock
                  sharedCondition.unlock();       // release the lock

       o      void wait(Predicate pred):
              This  member  was implemented as a member template. Predicate either is a predicate
              function or a predicate function object. The predicate function  or  the  predicate
              function  object’s  function  call  operators may not require arguments. As long as
              pred is returning false, wait() (no arguments) is called. The function returns once
              pred has returned true.

              The  running  thread  should  have obtained a lock on the SharedCondition condition
              variable prior to calling this member, and  should  release  the  lock  after  this
              member has returned.

              The pseudo code for using wait(pred) is identical to the pseudo code for using wait
              (albeit that pred has to be passed to wait, of course).

       o      std::cv_status wait_for(std::chrono::duration<Type, Unit> const &relTime):
              This member was implemented as a member template. Type  defines  the  type  of  the
              variable holding the amount of time (usually int64_t), specified in time unit Unit.
              Predefined duration types  are  available  from  the  std::chrono  namespace,  like
              std::chrono::seconds(4),  representing 4 seconds, or std::chrono::milliseconds(30),
              representing 30 milliseconds.

              The running thread should have obtained a lock on SharedCondition prior to  calling
              this member, and should release the lock after this member has returned.

              This  member acts like wait, returning std::cv_status::no_timeout if a notification
              was received  before  relTime  has  passed.  Otherwise  std::cv_status::timeout  is
              returned.

              A  prototypical  piece  of  pseudo code illustrating how to use wait_for looks like
              this:

                  sharedCondition.lock();         // lock the mutex
                  while (conditionWasNotYetMet)   // waiting required
                  {
                      while (sharedCondition.wait_for(someTime)
                             == std::cv_status::timeout)
                          handle_timeout

                      do_something
                  }
                  sharedCondition.unlock();       // release the lock

              When returning from wait_for the current thread has obtained the shared condition’s
              lock,  but  maybe  due  to a timeout: this can be verified by inspecting wait_for’s
              return value, and an appropriate action can be selected.

       o      bool wait_for(std::chrono::duration<Type, Unit> const &relTime, Predicate pred):
              This member was implemented as a member template. Type  defines  the  type  of  the
              variable holding the amount of time (usually int64_t), specified in time unit Unit.
              Predicate either is a predicate function  or  a  predicate  function  object.   The
              predicate  function  or the predicate function object’s function call operators may
              not require arguments.

              The running thread should have obtained a lock on SharedCondition prior to  calling
              this member, and should release the lock after this member has returned.

              As  long as pred returns false, wait_for(relTime) is called. If the latter function
              returns std::cv_status::timeout, then pred is  called,  and  its  return  value  is
              returned. Otherwise true is returned.

              The pseudo code for using this member is identical to the pseudo code for using the
              abovementioned wait_for member (albeit that pred must also be passed  to  wait_for,
              of course).

       o      std::cv_status wait_until(std::chrono::time_point<Clock, Duration> const &absTime):
              This member has been implemented as a member template. Clock defines the clock-type
              to use (usually std::chrono::system_clock), Duration is the type name of a duration
              type  (as  used  with  wait_for). E.g., to specify 5 seconds after the current time
              this member could be called like this:

                  std::chrono::system_clock::now() + std::chrono::seconds(5)

              The running thread should have obtained a lock on SharedCondition prior to  calling
              this member, and should release the lock after this member has returned.

              This member acts like wait_for(relative-time), returning std::cv_status::no_timeout
              if  a  notification   was   received   before   absTime   has   passed.   Otherwise
              std::cv_status::timeout is returned.

              The pseudo code for using this member is identical to the pseudo code for using the
              abovementioned wait_for(relative-time) member (albeit that absolute  time  must  be
              specified).

       o      bool  wait_until(std::chrono::time_point<Clock, Duration> const &absTime, Predicate
              pred):
              This member was implemented  as  a  member  template.  Clock  and  Duration  define
              identical  types  as  mentioned  at  the  previous  member.   Predicate either is a
              predicate function or a predicate function object (not expecting arguments).

              The running thread should have obtained a lock on SharedCondition prior to  calling
              this member, and should release the lock after this member has returned.

              As  long  as  pred  returns  false,  wait_until(absTime)  is  called. If the latter
              function returns std::cv_status::timeout, then pred is called, and its return value
              is returned. Otherwise true is returned.

              The pseudo code for using this member is identical to the pseudo code for using the
              abovementioned  wait_until  member  (albeit  that  pred  must  also  be  passed  to
              wait_until, of course).

STATIC MEMBER FUNCTIONS

       o      SharedCondition   &attach(SharedMemory   &shmem,  std::ios::off_type  offset  =  0,
              std::ios::seekdir origin = std::ios::beg):
              The SharedCondition object interfacing to the shared condition variable located  at
              offset (relative to origin) in shmem is returned.

              An  FBB::Exception is thrown if the requested offset is invalid (i.e., smaller than
              0 or exceeding shmem.maxOffset()).

       o      FBB::SharedCondition create(SharedMemory &shmem):
              A  shared  condition  variable  is  initialized  at  the  current  offset  of   the
              SharedMemory  object  referred  to  by  shmem,  or  at the first offset of the next
              physical shared data segment.

              A SharedCondition object interfacing to the initialized shared  condition  variable
              is returned.

              An  FBB::Exception  is  thrown  if  there  isn’t  enough  memory  available  in the
              SharedMemory object to define a shared condition variable.

       o      size_t size() const:
              Returns the size in bytes of the shared condition variables stored in  SharedMemory
              objects.

EXAMPLE

       #include <iostream>

       #include <bobcat/sharedcondition>
       #include <bobcat/sharedmemory>

       using namespace std;
       using namespace FBB;

       int main(int argc, char **argv)
       try
       {
           if (argc == 1)
           {
               cout <<
                   "Argument:\n"
                   "   c: create a shared memory segment + SharedCondition "
                                                           ", display ID\n"
                   "   k <id>: kill shared memory segment <id>\n"
                   "   m <id>: show a message every 5 secs, otherwise wait until\n"
                   "           being notified in segment <id>\n"
                   "   n <id>: notify the SharedCondition in segment ID <id>\n"
               ;
               return 0;
           }

           switch (argv[1][0])
           {
               case ’c’:
               {
                   SharedMemory shmem(1, SharedMemory::kB);

                   SharedCondition cond = SharedCondition::create(shmem);

                   void *ptr = shmem.ptr();

                   cout << "ID = " << shmem.id() << ", SharedCondition at " <<
                           cond.offset() << endl;
                   break;
               }

               case ’k’:
               {
                   SharedMemory shmem(stoll(argv[2]));
                   shmem.kill();
                   break;
               }

               case ’m’:
               {
                   SharedMemory shmem(stoll(argv[2]));
                   SharedCondition cond = SharedCondition::attach(shmem);

                   cond.lock();
                   cout << "Obtained the lock. Now waiting for a notification\n";

                   while (true)
                   {
                       switch (cond.wait_for(chrono::seconds(5)))
                       {
                           case cv_status::timeout:
                               cout << "Waited for 5 seconds\n\n";
                           break;

                           case cv_status::no_timeout:
                               cond.unlock();
                               cout << "Received the notification. Unlocked.\n";
                           return 0;
                       }
                   }
               }

               case ’w’:
               {
                   SharedMemory shmem(stoll(argv[2]));
                   SharedCondition cond = SharedCondition::attach(shmem);

                   cond.lock();
                   cout << "Obtained the lock. Now waiting for a notification\n";

                   cond.wait();
                   cout << "Received the notification. Unlocking.\n";

                   cond.unlock();
                   break;
               }

               case ’n’:
               {
                   SharedMemory shmem(stoll(argv[2]));

                   SharedCondition cond = SharedCondition::attach(shmem);

                   cout << "Notifying the other after Enter ";
                   cin.ignore(1000, ’\n’);

                   cond.lock();
                   cout << "Obtained the lock. Now notifying the other\n";
                   cond.notify();
                   cout << "Sent the notification. Now unlocking.\n";
                   cond.unlock();
                   break;
               }

           }
       }
       catch (exception const &exc)
       {
           cout << "Exception: " << exc.what() << endl;
       }

FILES

       bobcat/sharedcondition - defines the class interface

SEE ALSO

       bobcat(7)     isharedstream(3bobcat),     osharedstream(3bobcat),    sharedblock(3bobcat),
       sharedmemory(3bobcat), sharedpos(3bobcat), sharedreadme(7bobcat),  sharedsegment(3bobcat),
       sharedstream(3bobcat), sharedbuf(3bobcat)

BUGS

       None Reported.

BOBCAT PROJECT FILES

       o      https://fbb-git.gitlab.io/bobcat/: gitlab project page;

       o      bobcat_6.02.02-x.dsc: detached signature;

       o      bobcat_6.02.02-x.tar.gz: source archive;

       o      bobcat_6.02.02-x_i386.changes: change log;

       o      libbobcat1_6.02.02-x_*.deb: debian package containing the libraries;

       o      libbobcat1-dev_6.02.02-x_*.deb:  debian  package  containing the libraries, headers
              and manual pages;

BOBCAT

       Bobcat is an acronym of `Brokken’s Own Base Classes And Templates’.

COPYRIGHT

       This is free software, distributed under the terms  of  the  GNU  General  Public  License
       (GPL).

AUTHOR

       Frank B. Brokken (f.b.brokken@rug.nl).