gpt4 book ai didi

c++ - 如何在对象的生命周期内保持 Boost upgradable_lock?

转载 作者:太空宇宙 更新时间:2023-11-04 12:09:23 29 4
gpt4 key购买 nike

我正在实现一对用于进程间通信的类,其中一个进程将是唯一的写入者,并且会有很多读取者。一类处理阅读;一个负责写作。为了防止任何其他进程成为编写器,我想要一个编写器类的单个对象,它在 boost::named_upgradable_mutex 的整个生命周期内保持一个可升级的锁。为此,writer 类有一个 boost::interprocess::upgradable_lock 类型的成员变量,在构造对象时将其传递给互斥量。当编写器进程写入时,它会调用编写器类的 Write() 方法,该方法应将该锁升级为独占锁,执行写入,并以原子方式将独占锁再次降级为仅可升级。

我已按照 Lock Transfers Through Move Semantics 上的 Boost 文档,在我的编写器类的 Write() 方法中成功实现了第一部分——将锁升级为独占锁。 .然而,第二部分 - 将锁降级为可升级 - 导致类型为 boost::interprocess::upgradable_lock 的新局部变量,它将超出范围并在 Write() 返回时释放互斥锁。我需要将该可升级锁放回我类的 upgradable_lock 成员变量中,以便升级功能将仅保留在我的 writer 对象中。最好的方法是什么?我设法想出的唯一一件事是在返回之前用我的成员变量交换局部变量。代码如下所示:

using boost::interprocess;
scoped_lock<named_upgradable_mutex> my_exclusive_lock(move(m_lock));

// do write here

upgradable_lock<named_upgradable_mutex> my_demoted_lock(move(my_exclusive_lock));
m_lock.swap(my_demoted_lock); // how else to do this?

这行得通,但最后一行确实违反直觉,让我花了一些时间来思考。有没有更好的办法?是否可以将降级锁直接放入我的成员变量中?另外,重用成员变量存储降级锁是否有任何意想不到的后果?

最佳答案

考虑使用 move assignment operator .以下代码使用 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() == falsem_lock.mutex() == 0)。


我想不出为可升级锁重用成员变量有任何意想不到的后果。但是,有几个主题需要考虑:

  • 一个目标是“防止任何其他进程成为写入者”。通过在 Writer 构造函数中获取锁,除了防止其他进程 creating Writer 代码之外em>写作。因此,阻塞调用可能对应用程序代码造成影响或带来不便。考虑以下代码:

    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.

    一个妥协的选择可能是尝试通过this constructor获取锁,然后向 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 没有互斥量的句柄,因为当所有权转移到 m_lock.mutex() 设置为 null >my_exclusive_lockmove .
    • 进一步调用 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;
}

产生以下输出:

upgradable lock own:  1 -- mutex: 0xbff9b21c++ Entering scope ++Transferring ownership via move: Upgradable->Scopedupgradable lock owns: 0 -- mutex: 0exclusive lock owns:  1 -- mutex: 0xbff9b21cTransferring ownership via move: Scoped->Upgradableupgradable lock owns: 1 -- mutex: 0xbff9b21cexclusive lock owns:  0 -- mutex: 0-- Exiting scope --upgradable lock own:  1 -- mutex: 0xbff9b21c

关于c++ - 如何在对象的生命周期内保持 Boost upgradable_lock?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10537077/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com