9

いくつかの共有メモリ上でミューテックスロックを必要とするマルチスレッドサーバーアプリケーションがあります。

共有メモリは基本的にsTLマップなどです。

多くの場合、私は地図から読んでいます。しかし、私も時々それに追加する必要があります。

例:typedef std :: map MessageMap; MessageMap msgmap; boost:shared_mutex access_;

void ProcessMessage(Message* message)
{
  //  Access message... read some stuff from it  message->...

  UUID id = message->GetSessionID();

  // Need to obtain a lock here. (shared lock? multiple readers)
  // How is that done?
  boost::interprocess::scoped_lock(access_);

  // Do some readonly stuff with msgmap
  MessageMap::iterator it = msgmap.find();
  // 

  // Do some stuff...

  // Ok, after all that I decide that I need to add an entry to the map.
  // how do I upgrade the shared lock that I currently have?
  boost::interprocess::upgradable_lock


  // And then later forcibly release the upgrade lock or upgrade and shared lock if I'm not looking
  // at the map anymore.
  // I like the idea of using scoped lock in case an exception is thrown, I am sure that
  // all locks are released.
}

編集:私は異なるロックタイプを混乱させるかもしれません。

共有/アップグレードと排他の違いは何ですか。つまり、説明がわかりません。たくさんの読者を許可したいだけなら、共有アクセスだけを取得したいようです。また、共有メモリに書き込むには、アップグレードアクセスが必要です。それとも排他的ですか?ブーストの説明は明確ではありません。

あなたが書くかもしれないので、アップグレードアクセスは得られますか?しかし、共有とは、あなたが間違いなく書かないことを意味します。それはそれが何を意味するのでしょうか?

編集:私がやりたいことをもう少し明確に説明しましょう。私はまだ答えに満足していません。

これがもう一度例ですが、私が使用しているコードの例もあります。実際のコードではなく、単なる説明です。

typedef boost::shared_mutex Mutex;
typedef boost::shared_lock<Mutex> ReadLock;
typedef boost::unique_lock<Mutex> WriteLock;
Mutex mutex;
typedef map<int, int> MapType;    // Your map type may vary, just change the typedef
MapType mymap;

void threadoolthread() // There could be 10 of these.
{   
    // Add elements to map here
    int k = 4;   // assume we're searching for keys equal to 4
    int v = 0;   // assume we want the value 0 associated with the key of 4

    ReadLock read(mutex); // Is this correct?
    MapType::iterator lb = mymap.lower_bound(k);
    if(lb != mymap.end() && !(mymap.key_comp()(k, lb->first)))
    {
        // key already exists
    }
    else
    {
        // Acquire an upgrade lock yes?  How do I upgrade the shared lock that I already        have?
        // I think then sounds like I need to upgrade the upgrade lock to exclusive is that correct as well?

        // Assuming I've got the exclusive lock, no other thread in the thread pool will be able to insert.
        // the key does not exist in the map
        // add it to the map
        {
          WriteLock write(mutex, boost::adopt_lock_t());  // Is this also correct?
          mymap.insert(lb, MapType::value_type(k, v));    // Use lb as a hint to insert,
                                                        // so it can avoid another lookup
        }
        // I'm now free to do other things here yes?  what kind of lock do I have here, if any?  does the readlock still exist?
    }
4

2 に答える 2

15

アプリケーションはマルチスレッドであるとおっしゃっていたので、boost::interprocessではなくboost::threadを使用する必要があります。

ドキュメント(テストされていない)から、次のように行う必要があります。

typedef boost::thread::shared_mutex shared_mutex;
boost::thread::upgrade_lock<shared_mutex> readLock(access_);

// Read access...

boost::thread::upgrade_to_unique_lock<shared_mutex> writeLock(readLock);

// Write access..

またit、読み取りアクセスをロックしている間に取得するため、誰かがこのノードを削除する可能性があり、書き込みセクションに到達すると無効になることに注意してください。間違って、ごめんなさい。

編集:ブーストの説明明確だと思います。とにかくそれをあなたに言い換えてみましょう:

ミューテックスの概念には主に3つのタイプがあります(質問とは関係がないため、TimedLockableはカウントしません)。

  • ロック可能—単純な排他的所有権ミューテックス。誰かがそれをロック()した場合、所有者がそれをロック解除するまで、誰もそれを再びロック()することはできません。boost :: thread::mutexはこの概念を実装しています。この概念をRAIIスタイルでロックするには、lock_guardまたはunique_lockを使用してより複雑なインターフェースを使用します。
  • SharedLockable —追加の「共有」所有権を持つLockableです。lock()を使用して排他的所有権を取得するか、lock_shared()を使用して共有所有権を取得できます。共有部分をロックすると、所有権を排他的なものにアップグレードできなくなります。もう一度unlock_shared()とlock()を実行する必要があります。これは、他の誰かがunlock_shared()とlock()の間で保護されたリソースを変更する可能性があることを意味します。リソースへのアクセスの種類を事前に知っている場合に役立ちます。shared_mutexは、この概念を実装しています。lock_guardまたはunique_lockを使用して排他的所有権を取得し、shared_lockを使用して共有所有権を取得します。
  • UpgradeLockable —ロックを解除せずに共有所有権から排他的所有権にアップグレードできるSharedLockableです。shared_mutexもこの概念を実装しています。上記のロックを使用して、排他的または共有の所有権を取得できます。アップグレード可能な共有所有権を取得するには、upgrade_lockを使用し、upgrade_to_unique_lockでアップグレードします。
于 2010-10-09T09:49:02.033 に答える
5

boost-interprocess単一のプロセスを使用している場合は望ましくありません。ライブラリ名が示すように、プロセス間通信 (IPC) に使用されます。おそらく、boost-thread ミューテックスとロックの概念を使用したいと思うでしょう。

#include <boost/thread/locks.hpp>  
#include <boost/thread/shared_mutex.hpp>  

int
main()
{
    typedef boost::shared_mutex Mutex;
    typedef boost::shared_lock<Mutex> ReadLock;
    typedef boost::unique_lock<Mutex> WriteLock;
    Mutex mutex;

    {
        // acquire read lock
        ReadLock read( mutex );

        // do something to read resource
    }

    {
        // acquire write lock
        WriteLock write( mutex, boost::adopt_lock_t() );

        // do something to write resource
    }
}

これについても、boost メーリング リストに投稿があります。

于 2010-10-09T18:08:55.720 に答える