2012-09-15 90 views
6

This thread是解釋如何使用Boost實現讀寫器鎖定的黃金。它看起來相對簡單,我真的很喜歡它,但它似乎也使用了非命名鎖,我需要一個進程間解決方案(不需要是便攜式的,可以是Windows)。提升內部讀寫器鎖定

有沒有辦法讓一個進程間shared_mutex?我看到有一個named_mutex,但我不能讓它與shared_lock其他鎖一起使用。

任何指針表示讚賞。

[編輯]

在此期間,我所遇到的this thread幾乎擊中了要害。我有兩個問題:

  1. 它不顯示完整的代碼(我猜我需要使用named_upgradable_mutex,但我不是很確定),並
  2. 我不喜歡修改後的「作家答案「它沒有使用現成的類,而是在析構函數中解鎖,但在互斥體上有3個原始調用。

仍然歡迎評論或好的解決方案。

回答

9

的Boost.Interprocess中文檔描述了所謂的upgradable mutexes它支持和upgradable mutex operations兩個支持升級的互斥鎖類型:

編輯:我相信這個工程:

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

(你必須先啓動父:

#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上./a.out parent

輸出顯示「reader_child」和「writer_chi」的交錯ld「行(所有的」reader_child「行在第一個」writer_child「行之後顯示一個非零值),所以它似乎正在工作。

+0

謝謝!對我來說,即使它不是我正在尋找的那個伎倆,也清除了一些疑惑。 – wpfwannabe

+0

爲什麼當計數器被鎖定保護時,你使用volatile? –

+0

@BryanFok:我使用了'volatile',因爲在鎖定'interprocess_upgradable_mutex'時我沒有看到任何內存屏障保證。有三種實現:posix,windows和spin。如果使用posix或windows實現,我不認爲需要'volatile',因爲pthread_mutex_lock()/ WaitForSingleObject()在幕後調用。旋轉實現使用原子CAS操作,我認爲有CAS架構沒有內存屏障保證的體系結構。例如,請參閱[本答案](http://stackoverflow.com/a/24143387/196844)。 –