jjzjj

c++ - LockFileEx 读写升级/降级

coder 2024-02-26 原文

我需要打开一个文件,对其进行读取锁定,然后尝试获取写入锁定,但如果失败则保留读取锁定。

这在使用 fcntl 锁定的 POSIX 中效果很好。

在 Windows 中,我可以使用 LockFileEx 来获取文件锁。我可以获得读写锁(共享和独占)。

但是,在Windows中,我似乎必须取独占写锁,然后再加上读锁。这与我在 POSIX 上所做的顺序相反,它会给我的抽象层带来问题。当我在 POSIX 中按该顺序执行此操作时,我通过获取读锁失去了写锁,因为 fcntl 替换了现有锁而不是像 Windows 那样添加锁。

我可以用 #ifdefs 破解它以更改调用站点的锁定顺序,但我正在寻找好的想法来修复我的抽象代码。

// This is the header file
struct LockFileImpl;
class LockFile {
    protected:
    boost::scoped_ptr<LockFileImpl> p;

    public:
    LockFile(const File &); 
    virtual ~LockFile();

    void unlock() const;
    void rd_lock() const;
    void wr_lock() const;
    bool rd_try() const;
    bool wr_try() const;
};

class LockFileRead : public LockFile{
    public:
    LockFileRead(const File &f) : LockFile(f)
    { rd_lock(); }
};

class LockFileWrite : public LockFile{
    public:
    LockFileWrite(const File &f) : LockFile(f)
    { wr_lock(); }
};

// This is the Win32 implementation file. There's a different one for POSIX.
struct LockFileImpl
{
    handle_t hFile;
    bool rd_locked;
    bool wr_locked;

    LockFileImpl(handle_t x) : hFile(x), rd_locked(false), wr_locked(false)
    {}
};

LockFile::LockFile(const File &f)
    : p( new LockFileImpl(f.handle()) )
{
}

LockFile::~LockFile()
{
    unlock();
}


void LockFile::unlock() const
{
    if(p->wr_locked) {
        throw_win32_err_if( UnlockFile(p->hFile, 0, 0, 1, 0) == 0 );
        p->wr_locked = false;
    }
    if(p->rd_locked) {
        throw_win32_err_if( UnlockFile(p->hFile, 0, 0, 1, 0) == 0 );
        p->rd_locked = false;
    }
}

void LockFile::rd_lock() const
{
    OVERLAPPED over = {0};
    over.Offset = 0;
    throw_win32_err_if( !LockFileEx(p->hFile, 0, 0, 1, 0, &over) );
    p->rd_locked = true;
    if(p->wr_locked) {
        throw_win32_err_if( UnlockFile(p->hFile, 0, 0, 1, 0) == 0 );
        p->wr_locked = false;
    }
}

void LockFile::wr_lock() const
{
    OVERLAPPED over = {0};
    over.Offset = 0;
    throw_win32_err_if( !LockFileEx(p->hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &over) );
    p->wr_locked = true;
}

bool LockFile::rd_try() const
{
    OVERLAPPED over = {0};
    over.Offset = 0;
    bool r = !!LockFileEx(p->hFile, LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &over);
    if(r) {
        p->rd_locked = true;
        if(p->wr_locked) {
            throw_win32_err_if( UnlockFile(p->hFile, 0, 0, 1, 0) == 0 );
            p->wr_locked = false;
        }
    }
    return r;
}

bool LockFile::wr_try() const
{
    OVERLAPPED over = {0};
    over.Offset = 0;
    bool r = !!LockFileEx(p->hFile, LOCKFILE_FAIL_IMMEDIATELY|LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &over);
    if(r) {
        p->wr_locked = true;
    }
    return r;
}

最佳答案

为什么不使用 pimpl 方法?无论如何,你快到了。创建 WinLockFileImplPosixLockFileImpl,它们都继承了一个抽象的 LockFileImpl。然后,在下面的代码周围放置一个ifdef,以确定在编译时使用哪个类。您必须已经有一个 ifdef 可以在其他平台上编译时删除 windows 代码,对吗?

LockFile::LockFile(const File &f)
#ifdef POSIX
    : p( new PosixLockFileImpl(f.handle()) )
#else
    : p( new WinLockFileImpl(f.handle()) )
#endif

哦,您需要将您的代码移动到实现类中,这会将 LockFile 更改为看起来更像这样:

void LockFile::unlock() const
{
    p->unlock();
}

关于c++ - LockFileEx 读写升级/降级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3168504/

有关c++ - LockFileEx 读写升级/降级的更多相关文章

  1. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  5. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  9. ruby-on-rails - RVM/降级 bundler gem - 2

    我有以下有趣的场景:我已经通过RVM安装了ruby​​1.9.2,它预打包了bundler1.1.4。我的应用程序需要bundler1.0.15。我试过运行以下命令:gemuninstallbundler我得到以下信息:INFO:gem"bundler"isnotinstalled有什么想法可以降级我的bundler吗?谢谢。 最佳答案 找到解决方案。显然rvm在所有gemspec可见的全局gemspec中安装它的gem。所以通过这样做:rvmuse1.9.2@global然后是:gemuninstallbundler成功了。这也可

  10. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

随机推荐