Boost Interprocess将named_mutex作为类成员

时间:2014-09-24 19:04:06

标签: c++ boost locking mutex

我有一个类被设计为一些boost共享内存的包装器。当我尝试将named_mutex作为类成员并在构造函数中初始化它时,我得到编译错误。以下是相关代码:

   template< class T > class SharedMemoryVal
   {
      public:
         SharedMemoryVal( const std::string &name, bool readOnly );

         SharedMemoryVal( const SharedMemoryVal& other )
         {
            name = other.name;
            mutexName = other.mutexName;
            permissions = other.permissions;
            shm = other.shm;
            mutex = boost::interprocess::named_upgradable_mutex( boost::interprocess::open_or_create, mutexName.c_str() );
         }

         const SharedMemoryVal& operator=( const SharedMemoryVal& other )
         {
            if( this == &other )
               return *this;

            name = other.name;
            mutexName = other.mutexName;
            permissions = other.permissions;
            shm = other.shm;
            mutex = boost::interprocess::named_upgradable_mutex( boost::interprocess::open_or_create, mutexName.c_str() );
         }

         int8_t GetVal( T *val );

         int8_t SetVal( T val );

         virtual ~SharedMemoryVal();

      private:
         std::string name;
         std::string mutexName;
         boost::interprocess::mode_t permissions;
         boost::interprocess::shared_memory_object shm;
         mutable boost::interprocess::named_upgradable_mutex mutex;
   };

   using namespace boost::interprocess;

   /**
    * Construct new shared memory data value
    * @param[in] name - Name of shared memory segment
    * @param[in] readOnly
    */
   template< class T > SharedMemoryVal< T >::SharedMemoryVal( const std::string &name, bool readOnly )
   {
      // Set name
      this->name = name;

      // Create mutex
      mutexName = this->name.append( "_mutex" );

      /* GETTING AN ERROR HERE */
     /*  error: \u2018boost::interprocess::named_upgradable_mutex::named_upgradable_mutex()\u2019 is private*/
      mutex = named_upgradable_mutex( open_or_create, mutexName.c_str() );

      //Create a shared memory object.
      if( readOnly )
      {
         permissions = read_only;
         shm = shared_memory_object( open_only, name.c_str(), read_only );
      }
      else
      {
         permissions = read_write;
         shm = shared_memory_object( create_only, name.c_str(), read_write );

         // Set size
         shm.truncate( sizeof(T) );

      }
   }

   template< class T > SharedMemoryVal< T >::~SharedMemoryVal()
   {
      shared_memory_object::remove( name.c_str() );
      named_upgradable_mutex::remove( mutexName.c_str() );
   }
   /**
    * Return current data value
    * @return current data value
    */
   template< class T > int8_t SharedMemoryVal< T >::GetVal( T *val )
   {
      int8_t retVal = -1;
      //Map the whole shared memory in this process
      mapped_region region( shm, permissions );

      // Get data pointer
      T *data = static_cast< T * >( region.get_address() );

      // Lock
      {
         // This will only lock if someone else is writing.
         // Multiple processes can read at the same time
         sharable_lock< named_upgradable_mutex > lock( mutex );
         // If there wasn't a problem getting the data
         if( data != NULL )
         {
            *val = *data;
            retVal = 0;
         }
      }
      return retVal;
   }
   /**
    * Set shared memory data value
    * @param[in] val - value to set
    */
   template< class T > int8_t SharedMemoryVal< T >::SetVal( T val )
   {
      int8_t retVal = -1;
      //Map the whole shared memory in this process
      mapped_region region( shm, permissions );

      // Get data pointer
      T *data = static_cast< T * >( region.get_address() );

      // Do lock
      {
         // Lock will always be unlocked at the end of this block
         scoped_lock< named_upgradable_mutex > lock( mutex );

         // If we got the data OK
         if( data != NULL )
         {
            *data = val;
            retVal = 0;
         }
      }

      return retVal;
   }

我在创建锁定对象的构造函数中遇到错误,但我无法弄清楚原因。我读到我必须定义自己的复制构造函数和赋值运算符,并且我已经完成了。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您收到错误是因为必须初始化互斥锁成员。

这是通过默认构造函数发生的。在这种情况下,这是私人的。因此,您会收到错误(关于boost :: interprocess :: named_upgradable_mutex的默认构造函数named_upgradable_mutex()是私有的)。

您拥有的代码实际上会发生什么:在进入SharedMemoryVal构造函数的主体之前,将使用其默认构造函数初始化互斥锁成员。然后在正文中,您将新构造的对象分配给互斥锁成员。如果named_upgradable_mutex的默认(无参数)构造函数是公共的(因为默认构造没有名称的互斥体是无意义的),即使它效率低也可行。但

我建议您阅读Scott Meyers的Effective C ++(以及更有效的C ++)。如果你没有它们,我建议你买它们。在Effective C ++第1章第4项中确保对象在使用之前已初始化&#39;如果你在ctor体中为你的成员变量分配(如上所述的默认构造+赋值)而不是在初始化列表中初始化它们(仅构造),你会得到类似的解释。

在更有效的C ++中,您有两个项目。 第12项:首选初始化为构造函数中的赋值。

第13项:按照声明的顺序列出初始化列表中的成员。 (这与下面关于初始化顺序的说明有关)更详细。

一些说明上述行为的在线资料:Why preffer member initialization over assignment?

要解决此问题,请将互斥锁的构造移至初始化列表。有关成员初始值设定项列表的更多信息,请Member initializer list

像:

template< class T > SharedMemoryVal< T >::
SharedMemoryVal( const std::string &name, bool readOnly ) : 
    mutexName( name.append("_mutex") ),
    mutex (open_or_create, mutexName.c_str() ) 
        {
        }

注意:请注意初始化顺序,并确保在互斥之前初始化mutexName。 如果你在SharedMemoryVal类声明中的mutex之后声明mutexName成员,那么在使用它时调用mutex构造函数时,mutexName将是未初始化的,因为初始化按头中的声明顺序发生,而不是按成员初始化列表的顺序发生。在你的情况下,你在互斥之前声明了mutexName,所以你会没事的。只是在标题中的互斥量之后不要移动它的声明......我想也应该提一下。