interprocess.qbk

来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 1,625 行 · 第 1/5 页

QBK
1,625
字号
synchronization between processes.Mutexes guarantee that only one thread can lock a given mutex. If a code sectionis surrounded by a mutex locking and unlocking, it's guaranteed that only a thread at a time executes that section of code.When that thread [*unlocks] the mutex, other threads can enter to that coderegion:[c++]   //The mutex has been previously constructed   lock_the_mutex();   //This code will be executed only by one thread   //at a time.   unlock_the_mutex();A mutex can also be [*recursive] or [*non-recursive]:* Recursive mutexes can be locked several types by the same thread. To fully unlock the  mutex, the thread has two unlock the mutex the same times it has locked it.* Non-recursive mutexes can't be locked several types by the same thread. If a mutex  is locked twice by a thread, the result is undefined, it might throw an error or   the thread could be blocked forever.[endsect][section:mutexes_mutex_operations Mutex Operations]All the mutex types from [*Boost.Interprocess] implement the following operations:[blurb ['[*void lock()]]][*Effects:] The calling thread tries to obtain ownership of the mutex, and if another thread has ownership of the mutex, it waits until it can obtain the ownership. If a thread takes ownership of the mutex the mutex must be unlocked by the same thread. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.[*Throws:] *interprocess_exception* on error.[blurb ['[*bool try_lock()]]][*Effects:] The calling thread tries to obtain ownership of the mutex, and if another thread has ownership of the mutex returns immediately. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.[*Returns:] If the thread acquires ownership of the mutex, returns true, if the another thread has ownership of the mutex, returns false.[*Throws:] *interprocess_exception* on error.[blurb ['[*bool timed_lock(const boost::posix_time::ptime &abs_time)]]][*Effects:] The calling thread will try to obtain exclusive ownership of the mutex if it can do so in until the specified time is reached. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.[*Returns:] If the thread acquires ownership of the mutex, returns true, if the timeout expires returns false.[*Throws:] *interprocess_exception* on error.[blurb ['[*void unlock()]]][*Precondition:] The thread must have exclusive ownership of the mutex.[*Effects:] The calling thread releases the exclusive ownership of the mutex. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.[*Throws:] An exception derived from *interprocess_exception* on error.[endsect][section:mutexes_interprocess_mutexes Boost.Interprocess Mutex Types And Headers]Boost.Interprocess offers the following mutex types:[c++]   #include <boost/interprocess/sync/interprocess_mutex.hpp>* [classref boost::interprocess::interprocess_mutex]: A non-recursive,  anonymous mutex that can be placed in shared memory or memory mapped files.[c++]   #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>* [classref boost::interprocess::interprocess_recursive_mutex]: A recursive,  anonymous mutex that can be placed in shared memory or memory mapped files.[c++]   #include <boost/interprocess/sync/named_mutex.hpp>* [classref boost::interprocess::named_mutex named_mutex]: A non-recursive,  named mutex.[c++]   #include <boost/interprocess/sync/named_recursive_mutex.hpp>* [classref boost::interprocess::named_recursive_mutex named_recursive_mutex]: A recursive,  named mutex.[endsect][section:mutexes_scoped_lock Scoped lock]It's very important to unlock a mutex after the process has read or written the data.This can be difficult when dealing with exceptions, so usually mutexes are usedwith a scoped lock, a class that can guarantee that a mutex will always be unlockedeven when an exception occurs. To use a scoped lock just include:[c++]   #include <boost/interprocess/sync/scoped_lock.hpp>Basically, a scoped lock calls [*unlock()] in its destructor, and a mutex is alwaysunlocked when an exception occurs. Scoped lock has many constructors to lock,try_lock, timed_lock a mutex or not to lock it at all. [c++]   using namespace boost::interprocess;   //Let's create any mutex type:   MutexType mutex;   {      //This will lock the mutex      scoped_lock<MutexType> lock(mutex);            //Some code      //The mutex will be unlocked here   }   {      //This will try_lock the mutex      scoped_lock<MutexType> lock(mutex, try_to_lock);            //Check if the mutex has been successfully locked      if(lock){         //Some code      }         //If the mutex was locked it will be unlocked   }      {      boost::posix_time::ptime abs_time = ...      //This will timed_lock the mutex      scoped_lock<MutexType> lock(mutex, abs_time);            //Check if the mutex has been successfully locked      if(lock){         //Some code      }         //If the mutex was locked it will be unlocked   }For more information, check the [classref boost::interprocess::scoped_lock scoped_lock's reference].[endsect][section:mutexes_anonymous_example Anonymous mutex example]Imagine that two processes need to write traces to a cyclic buffer builtin shared memory. Each process needs to obtain exclusive access to thecyclic buffer, write the trace and continue.To protect the cyclic buffer, we can store a process shared mutex in thecyclic buffer. Each process will lock the mutex before writing the data andwill write a flag when ends writing the traces(`doc_anonymous_mutex_shared_data.hpp` header):[import ../example/doc_anonymous_mutex_shared_data.hpp][doc_anonymous_mutex_shared_data]This is the process main process. Creates the shared memory, constructs the cyclic buffer and start writing traces:[import ../example/doc_anonymous_mutexA.cpp][doc_anonymous_mutexA]The second process opens the shared memory, obtains access to the cyclic bufferand starts writing traces:[import ../example/doc_anonymous_mutexB.cpp][doc_anonymous_mutexB]As we can see, a mutex is useful to protect data but not to notify to another processan event. For this, we need a condition variable, as we will see in the next section.[endsect][section:mutexes_named_example Named mutex example]Now imagine that two processes want to write a trace to a file. First they writetheir name, and after that they write the message. Since the operating system caninterrupt a process in any moment we can mix parts of the messages of both processes,so we need a way to write the whole message to the file atomically. To achieve this, we can use a named mutex so that each process locks the mutex before writing:[import ../example/doc_named_mutex.cpp][doc_named_mutex][endsect][endsect][section:conditions Conditions][section:conditions_whats_a_condition What's A Condition Variable?]In the previous example, a mutex is used to ['lock] but we can't use it to['wait] efficiently until the condition to continue is met. A condition variablecan do two things:*  [*wait]: The thread is blocked until some other thread notifies that it can   continue because the condition that lead to waiting has disapeared.*  [*notify]: The thread sends a signal to one blocked thread or to all blocked   threads to tell them that they the condition that provoked their wait has   disapeared.Waiting in a condition variable is always associated with a mutex. The mutex must be locked prior to waiting on the condition. When waitingon the condition variable, the thread unlocks the mutex and waits [*atomically].When the thread returns from a wait function (because of a signal or a timeout,for example) the mutex object is again locked.[endsect][section:conditions_interprocess_conditions Boost.Interprocess Condition Types And Headers]Boost.Interprocess offers the following condition types:[c++]   #include <boost/interprocess/sync/interprocess_condition.hpp>* [classref boost::interprocess::interprocess_condition]:  An anonymous condition variable that can be placed in shared memory or memory  mapped files to be used with [classref boost::interprocess::interprocess_mutex].[c++]   #include <boost/interprocess/sync/named_condition.hpp>* [classref boost::interprocess::named_condition]: A named  condition variable to be used with [classref boost::interprocess::named_mutex].Named conditions are similar to anonymous conditions, but they are used incombination with named mutexes. Several times, we don't want to storesynchronization objects with the synchronized data:*  We want to change the synchronization method (from interprocess    to intra-process, or without any synchronization) using the same data.   Storing the process-shared anonymous synchronization with the synchronized   data would forbid this.*  We want to send the synchronized data through the network or any other   communication method. Sending the process-shared synchronization objects   wouldn't have any sense.[endsect][section:conditions_anonymous_example Anonymous condition example]Imagine that a process that writes a trace to a simple shared memory buffer thatanother process prints one by one. The first process writes the trace and waitsuntil the other process prints the data. To achieve this, we can use twocondition variables: the first one is used to block the sender until the secondprocess prints the message and the second one to block the receiver until thebuffer has a trace to print.The shared memory trace buffer (doc_anonymous_condition_shared_data.hpp):[import ../example/doc_anonymous_condition_shared_data.hpp][doc_anonymous_condition_shared_data]This is the process main process. Creates the shared memory, places therethe buffer and starts writing messages one by one until it writes "last message"to indicate that there are no more messages to print:[import ../example/doc_anonymous_conditionA.cpp][doc_anonymous_conditionA]The second process opens the shared memory and prints each messageuntil the "last message" message is received:[import ../example/doc_anonymous_conditionB.cpp][doc_anonymous_conditionB]With condition variables, a process can block if it can't continue the work,and when the conditions to continue are met another process can wake it.[endsect][endsect][section:semaphores Semaphores][section:semaphores_whats_a_semaphores What's A Semaphore?]A semaphore is a synchronization mechanism between processes based in an internalcount that offers two basic operations:*  [*Wait]: Tests the value of the semaphore count, and waits if the value is less than or   equal than 0. Otherwise, decrements the semaphore count.*  [*Post]: Increments the semaphore count. If any process is blocked, one of those processes   is awoken.If the initial semaphore count is initialized to 1, a [*Wait] operation is equivalent to a mutex locking and [*Post] is equivalent to a mutex unlocking. This type of semaphore is knownas a [*binary semaphore]. Although semaphores can be used like mutexes, they have a unique feature: unlike mutexes, a [*Post] operation need not be executed by the same thread/process that executed the[*Wait] operation.[endsect][section:semaphores_interprocess_semaphores Boost.Interprocess Semaphore Types And Headers]

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?