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 
31 namespace 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)