簡體   English   中英

將Interprocess named_mutex提升為類成員

[英]Boost Interprocess named_mutex as a class member

我有一個類設計為一些增強共享內存的包裝器。 當我嘗試將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;
   }

我在創建鎖定對象的構造函數中遇到錯誤,但我不知道為什么。 我讀到我必須定義自己的副本構造函數和賦值運算符,而我已經做到了。 有任何想法嗎?

您收到錯誤,因為必須初始化互斥成員。

這是通過默認構造函數發生的。 在這種情況下是私有的。 因此,您會收到錯誤消息(關於boost :: interprocess :: named_upgradable_mutex的默認構造函數named_upgradable_mutex()是私有的)。

您擁有的代碼實際將發生的事情是:在進入SharedMemoryVal構造函數的主體之前,將使用其默認構造函數初始化互斥成員。 然后,在主體中,您將為互斥對象分配一個新構造的對象。 哪怕效率低下,只要named_upgradable_mutex的默認(無參數)構造函數是公共的,它就可以工作(將其設為私有是有意義的,因為默認構造不帶名稱的互斥體是沒有意義的)。

我建議您閱讀Scott Meyers的Effective C ++(以及更有效的C ++)。 如果您沒有它們,我建議您購買它們。 在有效的C ++第1章,第4項“確保在使用對象之前確保對象已初始化”中,您將獲得類似的解釋,說明在ctor主體中將變量分配給成員變量(如上所述的默認構造+賦值)而不是初始化的情況。它們在初始化列表中(僅用於構造)。

在更有效的C ++中,您有兩項。 項目12:在構造函數中,初始化優先於賦值。

第13項:按照聲明的順序在初始化列表中列出成員。 (這與下面有關初始化順序的注釋有關)更詳細。

一些在線材料說明了上述行為: 為什么將成員初始化優先於分配?

要解決此問題,請將互斥鎖的構造移至初始化程序列表。 有關成員初始化程序列表的更多信息,這里成員初始化程序列表

喜歡:

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類聲明中的互斥鎖之后聲明了互斥鎖成員,則在使用互斥鎖構造函數調用互斥鎖構造函數時,該互斥鎖將未初始化,因為初始化是按照標頭中聲明的順序進行的,而不是按成員初始化器列表的順序進行。 在您的情況下,您在互斥對象之前聲明了mutexName,這樣就可以了。 只是不要在標頭中的互斥量之后移動它的聲明。以為我也應該提到這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM