gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:24:31 37 4
gpt4 key购买 nike

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

这在使用 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/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com