librostlab 1.0.20
file_lock_resource.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2011 Laszlo Kajan, Technical University of Munich, Germany
3
4 This file is part of librostlab.
5
6 librostlab is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef ROSTLAB_FLOCK_RESOURCE
20#define ROSTLAB_FLOCK_RESOURCE
21
22#include <errno.h>
23#include <fcntl.h>
24#include <iostream>
25#include <stdio.h>
26#include <string.h>
27#include <unistd.h>
28
30
31namespace rostlab {
32
38{
39 private:
40 std::string _filename;
41 FILE* _fh;
42 // this is a resource - disable copy contructor and copy assignment
45 operator=(const file_lock_resource&){return *this;};
46 public:
47 bool dbg;
48
49 class wouldblock : public exception {};
50
51 public:
52 file_lock_resource() : _fh(NULL), dbg(false) {};
53
56 file_lock_resource( const std::string& __file, const std::string& __mode = "r", int __cmd = F_SETLKW, short __type = F_RDLCK, bool __dbg = false ) : _fh(NULL), dbg(__dbg)
57 {
58 acquire( __file, __mode, __cmd, __type, __dbg );
59 }
60
61 inline void acquire( const std::string& __file, const std::string& __mode = "r", int __cmd = F_SETLKW, short __type = F_RDLCK, bool __dbg = false ) throw ( runtime_error, wouldblock )
62 {
63 dbg = __dbg;
64 release();
65 //
66 _filename = __file;
67 _fh = fopen( _filename.c_str(), __mode.c_str() );
68 if( !_fh ) throw runtime_error( strerror( errno ) );
69
70 // instead of flock us fcntl()/POSIX locking so that it works with NFS as well
71 flock lock;
72 lock.l_type = __type;
73 lock.l_whence = SEEK_SET;
74 lock.l_start = 0;
75 lock.l_len = 0;
76
77 if( fcntl( fileno(_fh), __cmd, &lock ) )
78 {
79 int fcntl_errno = errno;
80 fclose(_fh); _fh = NULL;
81 if( fcntl_errno == EACCES || fcntl_errno == EAGAIN ) throw wouldblock();
82 else throw runtime_error( strerror( fcntl_errno ) );
83 }
84 else if(dbg) std::cerr << "LOCK_" << __mode << " " << __cmd << " " << __type << " '" << _filename << "'\n";
85 }
86
87 inline void release() throw (runtime_error)
88 {
89 if( _fh )
90 {
91 // lkajan: no need to explicitly release the lock: it is released when the file is closed
92 if( fclose(_fh) ) throw runtime_error( strerror( errno ) );
93 if(dbg) std::cerr << "LOCK_UN '" << _filename << "'\n";
94 _fh = NULL;
95 }
96 }
97
99 {
100 release();
101 }
102
103 operator FILE* () { return _fh; }
104
105 inline const std::string&
106 filename() const { return _filename; }
107};
108
109};
110
111#endif // ROSTLAB_FLOCK_RESOURCE
112// vim:et:ts=2:ai:
const std::string & filename() const
void acquire(const std::string &__file, const std::string &__mode="r", int __cmd=F_SETLKW, short __type=F_RDLCK, bool __dbg=false)
file_lock_resource(const std::string &__file, const std::string &__mode="r", int __cmd=F_SETLKW, short __type=F_RDLCK, bool __dbg=false)