別のプログラムがロックを解除した後、ファイルにアクセスしたいようです。 UNIX(とCygwin)では、単にファイルをロックするだけでこの動作が実現します。 ScopeGuard
のようなものを使用して
はFile_locker
を不要にすることができますが、ScopeGuard
を使用していない場合は、次のように行く:
UNIX:
#include <stdexcept>
#include <string>
#include "sys/file.h" //flock
#include "sys/fcntl.h" //open
class File_locker {
int file_descriptor;
public:
File_locker(std::string filename)
{
// you can use errno to determine why the open/flock failed,
// but this is a demo, not production code
file_descriptor = ::open(filename.c_str(), O_RDWR);
if (file_descriptor < 0)
throw std::runtime_error((std::string("unable to open file ")
+ filename).c_str());
if (::flock(file_descriptor, LOCK_EX)) {
::close(file_descriptor);
throw std::runtime_error((std::string("unable to flock file ")
+ filename).c_str());
}
}
~File_locker()
{
::flock(file_descriptor, LOCK_UN); // don't forget to unlock
::close(file_descriptor);
}
};
のWindowsでは、あなたがファイルをポーリングする必要が表示されます。
のWindows:
#include <string>
#include "windows.h"
class File_locker {
HANDLE file_handle;
static const int MAX_TRIES = 10;
static const int SLEEP_INTERVAL = 500;
public:
File_locker(std::string filename)
{
// you can use GetLastError() to determine why the open failed,
// but this is a demo, not production code
for (int i = 0; i < MAX_TRIES; ++i) {
file_handle = ::CreateFile(filename.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (file_handle != INVALID_HANDLE_VALUE)
return;
::Sleep(SLEEP_INTERVAL);
}
throw std::runtime_error((std::string("unable to open file ")
+ filename).c_str());
}
~File_locker()
{
::CloseHandle(file_handle);
}
};
ので、同じようにそれを使用します。
#include <fstream>
#include <stdexcept>
// .. define File_locker, as above
int main()
{
try {
File_locker fl("filename.txt");
// once fl is constructed, nobody else has the file locked
std::fstream file("filename.txt");
// ...
return 0;
}
catch (std::runtime_error& ex)
{
// just bail
return 1;
}
}
待っているように見えませんか? – Andomar
is_openブロックは、あなたが望んでいると思っていません。 –
いいえ、私は使用しているバージョンでスリープ(100)していません。 –