c++ - 当 boost 库 "interprocess"定义一个 named_mutex 时,这些 named_mutex 是否在不同进程之间正常工作,或者只与线程一起工作?

标签 c++ visual-c++ boost visual-c++-2008 boost-interprocess

我想我一定是从名称 boost::interprocess 中假设了一些不正确的东西。 文档重复 named_mutex 是全局的 here .

虽然我无法让它工作。同一个可执行文件的两个拷贝应该同时运行,我希望名为 boost::interprocess 的库中的命名互斥体有时实际上可能会阻塞。它没有。它也不能防止以下代码中的数据文件损坏。

这是 boost 文档中的一些代码:

#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>


int main ()
{
   using namespace boost::interprocess;
   try{
      struct file_remove
      {
         file_remove() { std::remove("file_name"); }
         ~file_remove(){ std::remove("file_name"); }
      } file_remover;
      struct mutex_remove
      {
         mutex_remove() { named_mutex::remove("fstream_named_mutex"); }
         ~mutex_remove(){ named_mutex::remove("fstream_named_mutex"); }
      } remover;

      //Open or create the named mutex
      named_mutex mutex(open_or_create, "fstream_named_mutex");

      std::ofstream file("file_name");

      for(int i = 0; i < 10; ++i){

         //Do some operations...

         //Write to file atomically
         scoped_lock<named_mutex> lock(mutex);
         file << "Process name, ";
         file << "This is iteration #" << i;
         file << std::endl;
      }
   }
   catch(interprocess_exception &ex){
      std::cout << ex.what() << std::endl;
      return 1;
   }
   return 0;

这是我对它所做的,这样我就可以向自己证明互斥体正在做某事:

#include <windows.h>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <cstdio>


int main (int argc, char *argv[])
{
   srand((unsigned) time(NULL));

   using namespace boost::interprocess;
   try{
       /*
      struct file_remove
      {
         file_remove() { std::remove("file_name"); }
         ~file_remove(){ std::remove("file_name"); }
      } file_remover;
      */

      struct mutex_remove
      {
         mutex_remove() { named_mutex::remove("fstream_named_mutex"); }
         ~mutex_remove(){ named_mutex::remove("fstream_named_mutex"); }
      } remover;

      //Open or create the named mutex
      named_mutex mutex(open_or_create, "fstream_named_mutex");

      std::ofstream file("file_name");

      for(int i = 0; i < 100; ++i){

         //Do some operations...

         //Write to file atomically
         DWORD n1,n2;
         n1 = GetTickCount();
         scoped_lock<named_mutex> lock(mutex);
         n2 = GetTickCount();
         std::cout << "took " << (n2-n1) << " msec to acquire mutex";
         int randomtime = rand()%10;
         if (randomtime<1) 
            randomtime = 1;
         Sleep(randomtime*100);
         std::cout << " ... writing...\n";
         if (argc>1)
            file << argv[1];
         else
             file << "SOMETHING";
         file << " This is iteration #" << i;
         file << std::endl;
         file.flush(); // added in case this explains the corruption, it does not.
      }
   }
   catch(interprocess_exception &ex){
      std::cout << "ERROR " << ex.what() << std::endl;
      return 1;
   }
   return 0;
}

控制台输出:

took 0 msec to acquire mutex ... writing...
took 0 msec to acquire mutex ... writing...
took 0 msec to acquire mutex ... writing...
took 0 msec to acquire mutex ... writing...

此外,该演示会写入一个文件,如果您运行该程序的两个拷贝,该文件将丢失一些数据。

我希望如果我删除 file_name 并运行该程序的两个拷贝,我应该对 file_name 进行交错写入,每个实例包含 100 行。

(请注意,演示代码显然没有在附加模式下使用 ofstream,而是在每次程序运行时简单地重写文件,所以如果我们想要一个演示来显示两个进程写入到一个文件,我知道它不起作用的原因,但我确实期望上面的代码是互斥的可行演示,但事实并非如此。还调用了一个非常方便和恰当的方法名为 ofstream::flush() 的方法本可以包含在内,但没有包含。)

在 Visual C++ 2008 上使用 Boost 1.53

最佳答案

事实证明,Boost 是一个很棒的库,它穿插在文档中的代码示例有时可能会被破坏。至少文档中用于 boost::interprocess::named_mutex 的那个在 Windows 系统上不起作用。

*在演示代码中始终删除互斥锁会导致互斥锁不起作用。 *

至少应该在演示代码中对此进行注释。它没有通过“最小惊奇原则”,虽然我想知道它为什么在那里,我认为它必须是惯用的和必要的,它是愚蠢的和不必要的,实际上。或者,如果有必要,它是 Joel Spolsky 称之为泄漏抽象的示例。如果互斥量确实是 Windows 中 C:\ProgramData 下的文件系统点,我肯定不想知道它,或者知道如果我没有检测到它会留下大便会破坏抽象箱并清理干净。 (确实,Boost 中互斥量的 posix 友好语义使他们使用 posix 风格的实现,而不是直接转到 Win32 API 并实现一个没有文件系统垃圾的简单互斥量。)

这是一个工作演示:

#include <windows.h>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
#include <windows.h>

int main (int argc, char *argv[])
{
   srand((unsigned) time(NULL));

   using namespace boost::interprocess;
   try{
       /*
      // UNCOMMENT THIS IF YOU WANT TO MAKE THIS DEMO IMPOSSIBLE TO USE TO DEMO ANYTHING

      struct file_remove
      {
         file_remove() { std::remove("file_name"); }
         ~file_remove(){ std::remove("file_name"); }
      } file_remover;

      // UNCOMMENT THIS IF YOU WANT TO BREAK THIS DEMO HORRIBLY:

      struct mutex_remove
      {
         mutex_remove() { named_mutex::remove("fstream_named_mutex"); }
         ~mutex_remove(){ named_mutex::remove("fstream_named_mutex"); }
      } remover;
      */

      //Open or create the named mutex
      named_mutex mutex(open_or_create, "fstream_named_mutex");

      std::ofstream file("file_name", std::ios_base::app );
      int randomtime = 0;
      for(int i = 0; i < 100; ++i){

         //Do some operations...

         //Write to file atomically
         DWORD n1,n2;
         n1 = GetTickCount();

         {
         scoped_lock<named_mutex> lock(mutex);
         n2 = GetTickCount();
         std::cout << "took " << (n2-n1) << " msec to acquire mutex";

         randomtime = rand()%10;
         if (randomtime<1) 
            randomtime = 1;

         std::cout << " ... writing...\n";
         if (argc>1)
            file << argv[1];
         else
             file << "SOMETHING";
         file << "...";
         Sleep(randomtime*100);
         file << " This is iteration #" << i;
         file << std::endl;
         file.flush();
         }
         Sleep(randomtime*100); // let the other guy in.
      }
   }
   catch(interprocess_exception &ex){
      std::cout << "ERROR " << ex.what() << std::endl;
      return 1;
   }
   return 0;
}

我很乐意对这个答案进行评论和编辑,这样人们就会有一个使用这个命名互斥体的工作演示。

要使用演示:
- 构建它并运行它的两个拷贝。传入一个参数,以便您可以查看哪个实例写入了哪些行(start myexename ABCstart myexename DEF 从 Windows 中的命令提示符) - 如果这是您的第二次运行,如果您不想将第二次运行附加到第一次运行,请删除任何名为“file_name”的杂散输出。

enter image description here

关于c++ - 当 boost 库 "interprocess"定义一个 named_mutex 时,这些 named_mutex 是否在不同进程之间正常工作,或者只与线程一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15314726/

相关文章:

c++ - STL算法生成斐波那契数直到达到某个值

C++ memcpy : double incompatible with const void

c++ - 使用无效句柄调用 SetEvent

c++ - 从cygwin移植到win32 native 程序

c++ - 用于检测 MSVC C 运行时库的预处理器宏

c++ - 如何识别boost fusion vector 中的类型

c++ - 选择两个城市的概率C++

visual-c++ - g++ 和 cl 的编译器#defines

c++ - libboost_regex 未编译

c++ - boost::asio::deadline_timer cancel() 方法未调用计时器处理程序