views:

391

answers:

3

What sync mechanism should I use to give exclusive access to the text file in boost? The file will likely be accessed by threads from only one process.

+1  A: 

I suppose it is acquire_file_lock

inline bool acquire_file_lock(file_handle_t hnd)
{
   struct ::flock lock;
   lock.l_type    = F_WRLCK;
   lock.l_whence  = SEEK_SET;
   lock.l_start   = 0;
   lock.l_len     = 0;
   return -1 != ::fcntl(hnd, F_SETLKW, &lock);
}

It is consistent with a non-boost implementation of a lock.

    struct flock fl = {F_WRLCK, SEEK_SET,   0,      0,     0 };
    int fd;

    fl.l_pid = getpid();

    if (argc > 1) 
        fl.l_type = F_RDLCK;

    if ((fd = open("lockdemo.c", O_RDWR)) == -1) {
        perror("open");
        exit(1);
    }

    printf("Press <RETURN> to try to get lock: ");
    getchar();
    printf("Trying to get lock...");

    if (fcntl(fd, F_SETLKW, &fl) == -1) {
        perror("fcntl");
        exit(1);
    }

    printf("got lock\n");
    printf("Press <RETURN> to
VonC
+1  A: 

If you are sure it will only be accessed from one process, a read-write lock with file handles in thread local storage could be a solution. That would simulate the above with only one writer but several readers.

Fredrik Jansson
A: 

The file locking APIs are generally for inter process locking. If you are in a single process everything in Boost.Thread package that suits your needs will do. Outside processes the Boost.Interprocess shoud be used. You might want to read the following warning from Boost.Interprocess:

Caution: Synchronization limitations

If you plan to use file locks just like named mutexes, be careful, because portable file locks have synchronization limitations, mainly because different implementations (POSIX, Windows) offer different guarantees. Interprocess file locks have the following limitations:

  • It's unspecified if a file_lock synchronizes two threads from the same process.
  • It's unspecified if a process can use two file_lock objects pointing to the same file.

The first limitation comes mainly from POSIX, since a file handle is a per-process attribute and not a per-thread attribute. This means that if a thread uses a file_lock object to lock a file, other threads will see the file as locked. Windows file locking mechanism, on the other hand, offer thread-synchronization guarantees so a thread trying to lock the already locked file, would block.

The second limitation comes from the fact that file locking synchronization state is tied with a single file descriptor in Windows. This means that if two file_lock objects are created pointing to the same file, no synchronization is guaranteed. In POSIX, when two file descriptors are used to lock a file if a descriptor is closed, all file locks set by the calling process are cleared.

To sum up, if you plan to use file locking in your processes, use the following restrictions:

  • For each file, use a single file_lock object per process.
  • Use the same thread to lock and unlock a file.
  • If you are using a std::fstream/native file handle to write to the file while using file locks on that file, don't close the file before releasing all the locks of the file.
CQ