内存映射文件类,线程和引用计数

时间:2010-08-17 09:11:11

标签: c++ boost

我正在组建一个我打算调用文件的课程。

文件对象只包含指向内存映射文件和链接的指针。

构造函数获取文件并将文件映射到内存范围。总之,它看起来 有点像这样:

class file
{
  public:
   file(unsigned char* filename) { open(filename); }         

   open(unsigned char* filename)
   {
       /// snip 
       length_ = fstat(.....)
       file_ = mmap(.....)
   }
  private:
   unsigned int length_;
   unsigned char* bytes_;
};

现在,可以复制此文件对象。

这很有趣。通常,像这样的类需要深层复制构造函数来复制bytes_。但是,我很满意我可以复制指针,因为内存是共享的,无论如何它应该看同一个文件。我不想要 重新映射文​​件。但是,很明显,为了防止内存泄漏,bytes_会在某个时刻发生 需要被释放。

我可以使用哪些机制来决定何时删除内存和munmap?

我正在考虑使用boost :: shared_ptr来释放析构函数中的内存,只有当它是最后一个引用时,但是我必须使用互斥锁来保护它吗? 是否有一些方便的升级功能供我使用?我不想拉另一个大图书馆,这不是一个选择。

即。

boost::shared_ptr<unsigned char> bytes_;

~file()
{
    // enter some sort of critical section 
    if (bytes_.unique()){
      munmap(bytes_);
      bytes_ = 0;
    }
    // exit critical section
}

3 个答案:

答案 0 :(得分:1)

我会略有不同。

问题是shared_ptr并不意味着处理数组,然后就像你说的那样存在同步问题。

简单的替代方案是使用Pimpl习语:

class FileImpl: boost::noncopyable
{
public:
  FileImpl(char const* name): mLength(fstat(name)), mFile(mmap(name)) {}
  ~FileImpl() { munmap(mFile); }

  unsigned int GetLength() const { return mLength; }
  unsigned char* GetFile() const { return mFile; }
private:
  unsigned int mLength;
  unsigned char* mFile;
};

class FileHandle
{
public:
  FileHandle(char const* name): mFile(new FileImpl(name)) {}

  void open(char const* name) { mFile = new FileImpl(name); }

private:
  boost::shared_ptr<FileImpl> mFile;
};

在破坏中你不会有任何同步问题(它自然由shared_ptr处理)。

您可能还希望使用Factory因为具有相同文件名的各种FileHandle对象的多个创建将导致多次调用mmap,我不确定这会不要在内存中复制文件。另一方面,在这种情况下,集中调用的工厂可以简单地返回已创建的FileHandle对象的副本。

答案 1 :(得分:0)

查看Boost提供的互斥(以及其他同步机制)。见this。此外,Boost还有一个线程库。您使用的是特定于操作系统的线程库吗?如果是这样,Boost.Threads可能值得一看。此外,您的file对象不应该在共享内存中。绕过指针看起来对我来说并不危险。

答案 2 :(得分:0)

shared_ptr是线程安全的,因为评论中发布的链接没有。

另一种方法是将复制构造函数和赋值运算符声明为private,允许(强制?)用户为其环境选择适当的管理策略,例如shared_ptr或ptr_container。添加move semantics以获得更大的灵活性。