Звучит так, будто вы хотите получить доступ к файлу после снятия блокировки другой программой. 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;
}
}