考虑使用移动赋值运算符。以下代码使用swap()
:
upgradable_lock<named_upgradable_mutex> my_demoted_lock(move(my_exclusive_lock));
m_lock.swap(my_demoted_lock);
会成为:
m_lock = upgradable_lock<named_upgradable_mutex>(move(my_exclusive_lock));
在这种特殊情况下,swap()
移动赋值运算符是可互换的,没有任何副作用,因为m_lock
它处于默认构造状态 ( m_lock.owns() == false
and m_lock.mutex() == 0
)。
我想不出重用可升级锁的成员变量的任何意外后果。但是,有几个主题需要考虑:
一个目标是“防止任何其他进程成为作家”。在Writer
构造函数中获取锁后,代码会阻止其他进程创建,Writer
此外还会阻止其他进程写入。结果,阻塞调用可能对应用程序代码强加或不方便。考虑以下代码:
Reader reader;
Writer writer; // This may block, but the application code cannot react
// to it without dedicating an entire thread to the
// construction of the writer.
一种妥协的替代方法可能是尝试通过此构造函数获取锁,然后添加成员函数以Writer
提供应用程序更多的控制权。虽然这仍然允许其他进程创建一个Writer
,但它会阻止多个进程拥有写入权限:
class Writer
{
public:
bool IsPrivileged(); // Returns true if this the privileged Writer.
bool TryBecomePrivileged(); // Non-blocking attempt to become the
// privileged Writer. Returns true on success.
bool BecomePrivileged(); // Blocks waiting to become the privileged
// Writer. Returns true on success.
void RelinquishPrivileges(); // We're not worthy...we're not worthy...
enum Status { SUCCESS, NOT_PRIVILEGED };
Status Write( const std::string& ); // If this is not the privileged Writer,
// then attempt to become it. If the
// attempt fails, then return
// NOT_PRIVILEGED.
};
在该Writer::Write()
方法中,如果“ do write here ”代码中的任何调用抛出异常,则堆栈将展开,导致:
my_exclusive_lock
释放独占锁,允许其他进程获得可升级锁。
m_lock
没有互斥体的句柄,正如在move中将所有权转移到时m_lock.mutex()
设置的那样。null
my_exclusive_lock
- 进一步调用
Writer::Write()
将尝试在不获取排他锁的情况下进行写入!即使m_lock
有一个互斥锁的句柄,m_lock.owns()
也会是false
,所以转移到my_exclusive_lock
不会尝试锁定。
这是一个示例程序:
#include <boost/interprocess/sync/named_upgradable_mutex.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/interprocess/sync/upgradable_lock.hpp>
#include <boost/move/move.hpp>
#include <iostream>
int main()
{
namespace bip = boost::interprocess;
typedef bip::named_upgradable_mutex mutex_t;
struct mutex_remove
{
mutex_remove() { mutex_t::remove( "example" ); }
~mutex_remove() { mutex_t::remove( "example" ); }
} remover;
// Open or create named mutex.
mutex_t mutex( bip::open_or_create, "example" );
// Acquire upgradable lock.
bip::upgradable_lock< mutex_t > m_lock( mutex, bip::try_to_lock );
std::cout << "upgradable lock own: " << m_lock.owns()
<< " -- mutex: " << m_lock.mutex()
<< std::endl;
// Acquire the exclusive lock.
{
std::cout << "++ Entering scope ++" << std::endl;
std::cout << "Transferring ownership via move: Upgradable->Scoped"
<< std::endl;
bip::scoped_lock< mutex_t > exclusive_lock( boost::move( m_lock ) );
std::cout << "upgradable lock owns: " << m_lock.owns()
<< " -- mutex: " << m_lock.mutex()
<< "\nexclusive lock owns: " << exclusive_lock.owns()
<< " -- mutex: " << exclusive_lock.mutex()
<< std::endl;
// do write here...
// Demote lock from exclusive to just an upgradable.
std::cout << "Transferring ownership via move: Scoped->Upgradable"
<< std::endl;
m_lock = bip::upgradable_lock< mutex_t >( boost::move( exclusive_lock ) );
std::cout << "upgradable lock owns: " << m_lock.owns()
<< " -- mutex: " << m_lock.mutex()
<< "\nexclusive lock owns: " << exclusive_lock.owns()
<< " -- mutex: " << exclusive_lock.mutex()
<< std::endl;
std::cout << "-- Exiting scope --" << std::endl;
}
std::cout << "upgradable lock own: " << m_lock.owns()
<< " -- mutex: " << m_lock.mutex()
<< std::endl;
return 0;
}
产生以下输出:
可升级锁拥有:1 -- 互斥锁:0xbff9b21c
++ 进入范围 ++
通过 move 转移所有权:Upgradable->Scoped
可升级锁拥有:0 -- 互斥锁:0
独占锁拥有:1 -- 互斥锁:0xbff9b21c
通过移动转移所有权:Scoped->Upgradable
可升级锁拥有:1 -- 互斥锁:0xbff9b21c
独占锁拥有:0 -- 互斥锁:0
-- 退出范围 --
可升级锁拥有:1 -- 互斥锁:0xbff9b21c