当boost库"interprocess"被启动时.定义了named_mutex,那些named_mutexes是否在不同进程之间正常工作,或者仅在线程之间正常工作? [英] When boost library "interprocess" defines a named_mutex do those named_mutexes work properly between different processes, or only with threads?

查看:95
本文介绍了当boost库"interprocess"被启动时.定义了named_mutex,那些named_mutexes是否在不同进程之间正常工作,或者仅在线程之间正常工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我必须假设boost::interprocess这个名字是错误的. 文档重复named_mutex是全局此处.

I think I must be assuming something from the name boost::interprocess that is not true. The documents repeat that named_mutex is global here.

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

I am unable to make it work though. Two copies of the same executable should be run at the same time, and I expect that a named mutex in a library named boost::interprocess might actually BLOCK sometimes. It doesn't. It also doesn't prevent data file corruption in the code below.

以下是boost文档中的一些代码:

Here's some code from the boost docs:

#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;

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

Here's what I did to it so I could prove to myself the mutex was doing something:

#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...

此外,该演示还将写入文件,如果您运行该程序的两个副本,该文件将丢失一些数据.

Also, the demo writes to a file, which if you run two copies of the program will be missing some data.

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

I expect that if I delete file_name and run two copies of the program, I should get interleaved writes to file_name containing 100 rows from each instance.

(注意,该演示代码显然未在附加模式下使用ofstream,而是每次该程序运行时它仅重写文件,因此,如果我们希望演示显示两个写入文件的进程,我'知道了为什么它不起作用的原因,但是我期望的是上述代码是互斥的可行演示,但事实并非如此.它还调用了一个非常方便且易于使用的ofstream::flush()方法可以包括在内,但不包括在内.)

(Note, that the demo code is clearly not using an ofstream in append mode, instead it simply rewrites the file each time this program runs, so if we wanted a demo to show two processes writing to a file, I'm aware of that reason why it wouldn't work, but what I did expect is for the above code to be a feasible demonstration of mutual exclusion, which it is not. Also calls to a very handy and aptly named ofstream::flush() method could have been included, and weren't.)

在Visual C ++ 2008上使用Boost 1.53

推荐答案

事实证明Boost是一个很棒的库,并且散布在文档中的代码示例有时可能会损坏.至少文档中的boost::interprocess::named_mutex之一在Windows系统上不起作用.

It turns out that Boost is a wonderful library, and it code examples interspersed in the documentation may sometimes be broken. At least the one for boost::interprocess::named_mutex in the docs is not functional on Windows systems.

*作为演示代码的一部分,始终删除互斥锁会导致该互斥锁不起作用. *

*Always deleting a mutex as part of the demo code causes the mutex to not function. *

至少应该在演示代码中对此进行注释.它没有通过最小惊奇原则",尽管我想知道为什么它在那里,但我认为它必须是惯用的和必要的,实际上它是白痴的和不必要的.或者,如果有必要,这是Joel Spolsky称之为泄漏抽象的一个示例.如果互斥锁确实是Windows中C:\ProgramData下的文件系统点,我当然不想知道它,或者知道杂物被遗忘了,如果我不检测这种情况并清理它,将会破坏抽象. (肯定有气味,例如Boost中互斥锁的posix友好语义,已经使他们使用posix样式的实现,而不是直接使用Win32 API并实现了没有文件系统混乱的简单互斥锁.)

That should be commented in the demo code at the very least. It fails to pass the "principle of least amazement", although I wondered why it was there, I thought it must be idiomatic and necessary, it's idiotic and unnecessary, in actual fact. Or if it's necessary it's an example of what Joel Spolsky would call a leaky abstraction. If mutexes are really filesystem points under C:\ProgramData in Windows I sure don't want to know about it, or know that turds get left behind that will break the abstraction if I don't detect that case and clean it up. (Sure smells like posix friendly semantics for mutexes in Boost have caused them to use a posix-style implementation instead of going to Win32 API directly and implementing a simple mutex that has no filesystem turds.)

这是一个工作示例:

#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;
}

我希望对这个答案进行批判和修改,以便人们可以使用此互斥体来进行演示.

I would love critques and edits on this answer, so that people will have a working demo of using this named mutex .

要使用演示,请执行以下操作:
-构建它并运行它的两个副本.传入参数,以便您可以看到哪个实例写了哪些行(Windows中的命令提示符下为start myexename ABCstart myexename DEF) -如果是第二次运行,如果您不希望将第二次运行追加到第一次运行,则删除任何名为"file_name"的杂散输出.

To use the demo:
- Build it and run two copies of it. Pass a parameter in so you can see which instance wrote which lines (start myexename ABC and start myexename DEF from a command prompt in windows) - If it's your second run, delete any stray output named "file_name" if you don't want the second run appended to the first.

这篇关于当boost库"interprocess"被启动时.定义了named_mutex,那些named_mutexes是否在不同进程之间正常工作,或者仅在线程之间正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆