8

Boostを使用してリーダー/ライターロックを実装する方法を説明する場合、このスレッドはゴールドです。それは比較的単純なようで、私はそれが本当に好きですが、名前のないロックを使用しているようで、プロセス間ソリューションが必要です(ポータブルである必要はなく、Windowsのみである可能性があります)。

プロセス間通信を行う方法はありshared_mutexますか?あるのはわかりますが、他のロックnamed_mutexでは機能しません。shared_lock

どんなポインタでも大歓迎です。

[編集]

その間に、頭の爪にぶつかりそうなこの糸に出くわしました。私には2つの問題があります:

  1. 完全なコードは表示されません(使用する必要があると思いますnamed_upgradable_mutexが、よくわかりません)。
  2. デストラクタでロック解除を行う既成のクラスを使用せず、ミューテックスで3つのraw呼び出しのシーケンスを使用する、変更された「ライター」の答えは好きではありません。

コメントや良い解決策はまだ大歓迎です。

4

1 に答える 1

11

Boost.Interprocessのドキュメントでは、サポートされているいわゆるアップグレード可能なミューテックスと、サポートされている2つのアップグレード可能なミューテックスタイプのアップグレード可能なミューテックス操作について説明しています。

編集:私はこれがうまくいくと信じています:

#include <iostream>
#include <string>
#include <unistd.h>

#include <boost/scope_exit.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/interprocess/sync/upgradable_lock.hpp>

// http://stackoverflow.com/questions/12439099/interprocess-reader-writer-lock-with-boost/

#define SHARED_MEMORY_NAME "SO12439099-MySharedMemory"

struct shared_data {
private:
    typedef boost::interprocess::interprocess_upgradable_mutex upgradable_mutex_type;

    mutable upgradable_mutex_type mutex;
    volatile int counter;

public:
    shared_data()
        : counter(0)
    {
    }

    int count() const {
        boost::interprocess::sharable_lock<upgradable_mutex_type> lock(mutex);
        return counter;
    }

    void set_counter(int counter) {
        boost::interprocess::scoped_lock<upgradable_mutex_type> lock(mutex);
        this->counter = counter;
    }
};

int main(int argc, char *argv[])
{
    using namespace boost::interprocess;

    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " WHICH" << std::endl;
        return 1;
    }

    const std::string which = argv[1];
    if (which == "parent") {
        shared_memory_object::remove(SHARED_MEMORY_NAME);
        shared_memory_object shm(create_only, SHARED_MEMORY_NAME, read_write);

        BOOST_SCOPE_EXIT(argc) {
            shared_memory_object::remove(SHARED_MEMORY_NAME);
        } BOOST_SCOPE_EXIT_END;

        shm.truncate(sizeof (shared_data));

        // Map the whole shared memory into this process.
        mapped_region region(shm, read_write);

        // Construct the shared_data.
        new (region.get_address()) shared_data;

        // Go to sleep for a minute.
        sleep(60);

        return 0;
    } else if (which == "reader_child") {
        shared_memory_object shm(open_only, SHARED_MEMORY_NAME, read_write);

        mapped_region region(shm, read_write);
        shared_data& d = *static_cast<shared_data *>(region.get_address());

        for (int i = 0; i < 100000; ++i) {
            std::cout << "reader_child: " << d.count() << std::endl;
        }
    } else if (which == "writer_child") {
        shared_memory_object shm(open_only, SHARED_MEMORY_NAME, read_write);

        mapped_region region(shm, read_write);
        shared_data& d = *static_cast<shared_data *>(region.get_address());

        for (int i = 0; i < 100000; ++i) {
            d.set_counter(i);
            std::cout << "writer_child: " << i << std::endl;
        }
    }
}

次のスクリプトを使用してMacでこれを試しました。

#!/usr/bin/env sh
./a.out reader_child &
./a.out reader_child &
./a.out writer_child &
./a.out reader_child &
./a.out reader_child &

(最初に親を開始する必要があります./a.out parent:)

出力には、「reader_child」行と「writer_child」行のインターリーブが示されていたため(すべての「reader_child」行は最初の「writer_child」行の後にゼロ以外の値を示しています)、機能しているように見えます。

于 2012-09-15T22:20:59.297 に答える