2014-09-24 54 views
0

我有一个类设计为一些提升共享内存的包装。当我尝试将一个named_mutex作为一个类成员并在构造函数中初始化它时,出现编译错误。这里是相关的代码:作为类成员提升进程间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

由于互斥成员必须被初始化,因此您会收到错误消息。

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

实际发生的代码是:在进入SharedMemoryVal构造函数的主体之前,mutex成员将使用其默认构造函数进行初始化。然后在主体中,您将为互斥成员分配一个新构造的对象。即使效率低下,只要named_upgradable_mutex的默认(无参数)构造函数是public的(私有是有道理的,因为默认构造没有名字的mutex是无意义的)。

我建议你阅读Scott Meyers的Effective C++(和更有效的C++)。如果你没有他们,我推荐你买他们。在Effective C++第1章中,第4项'确保对象在被使用之前被初始化',你可以得到类似的解释,说明如果你在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,这样你就可以。只是不要在标题中的互斥体之后移动它的声明......我想我也应该提到这一点。

+0

这是完美的。谢谢! – nrcrast 2014-09-24 20:23:13

+0

你很好 – ds27680 2014-09-24 20:36:43