Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/io/lock_file.h

Go to the documentation of this file.
00001 //  Copyright (C) 2002  Petter Urkedal (petter.urkedal@matfys.lth.se)
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: lock_file.h,v 1.1 2002/05/30 18:01:37 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_IO_LOCK_FILE_H
00031 #define MORE_IO_LOCK_FILE_H
00032 
00033 #include <more/gen/utility.h>
00034 
00035 
00036 namespace more {
00037 namespace io {
00038 
00039   enum access_t
00040   {
00041       access_none = 0,
00042       access_x = 1,
00043       access_w = 2,
00044       access_wx = 3,
00045       access_r = 4,
00046       access_rx = 5,
00047       access_rw = 6,
00048       access_rwx = 7
00049   };
00050   inline access_t operator~(access_t acc) { return access_t(~int(acc)); }
00051   inline access_t operator&(access_t x, access_t y)
00052   {
00053       return access_t(int(x) & int(y));
00054   }
00055   inline access_t operator|(access_t x, access_t y)
00056   {
00057       return access_t(int(x) | int(y));
00058   }
00059   inline access_t& operator&=(access_t& x, access_t y) { return x = x & y; }
00060   inline access_t& operator|=(access_t& x, access_t y) { return x = x | y; }
00061 
00062   extern struct infinite_tag {} const infinite;
00063 
00064   /** A handle to a lock file.  Read-only locks are not NFS safe
00065    ** (TODO).  A workaround is to use \c access_rw also when only read
00066    ** access is needed. */
00067   struct lock_file : gen::noncopyable
00068   {
00069       /** Construct an undefined lock file handle. */
00070       lock_file()
00071           : m_access(access_none) {}
00072 
00073       /** Construct a handle for a named lock file, but do not create
00074        ** the file yet. */
00075       explicit lock_file(std::string path)
00076           : m_path(path),
00077             m_access(access_none) {}
00078 
00079 //       /** Partially copy \a lf.  The path and access are copied, but
00080 //        ** not the lock status.
00081 //        ** \post <tt>this.have_lock() == false</tt>  */
00082 //       lock_file(lock_file const& lf)
00083 //        : m_path(lf.m_path),
00084 //          m_access(access_none) {}
00085 
00086       /** Calls unlock(). */
00087       ~lock_file() { release(); }
00088 
00089       /** Set or change the file name of the lock.  This causes an
00090        ** unlock. */
00091       void set_file_name(std::string);
00092 
00093       /** Return the current access of the lock. */
00094       access_t access() const { return m_access; }
00095 
00096       /** Try to obtain the lock without blocking, and return true if
00097        ** successful.  The valid arguments for \a access are \c
00098        ** access_none, which causes an unlock, \c access_r which gives
00099        ** read access, and \c access_rw which gives read write access.
00100        ** In addition \c access_w will be changed to \c access_rw. */
00101       bool adjust(access_t access);
00102 
00103       /** Return \c adjust(acc | access()). */
00104       bool aquire(access_t acc) { return adjust(acc | access()); }
00105 
00106       /** Attempt every \a dt seconds for \a t seconds to \c
00107        ** aquire(access).  Return true if the lock was obtained.  See
00108        ** <tt>adjust(access_t)</tt> for constraint on \a access. */
00109       bool aquire(access_t access, double t, double dt = 1.0);
00110 
00111       /** Attempt every \a dt seconds indefinitely to \c
00112        ** aquire(access).  See <tt>adjust(access_t)</tt> for
00113        ** constraint on \a access. */
00114       bool aquire(access_t access, infinite_tag, double dt = 1.0);
00115 
00116       /** Release all access.  This function should ideally neither
00117        ** hang nor fail.  In the case of read-only locks, however, it
00118        ** may in exceptional cases hang for a few seconds, and
00119        ** possibly fail.  This may be the case if another program was
00120        ** interrupted at the critical stage while adjusting its own
00121        ** read-only lock, or if the lock files were tampered with. */
00122       void release(access_t access = access_rw);
00123 
00124       /** Swap two locks. */
00125       void swap(lock_file& lk)
00126       {
00127           std::swap(m_path, lk.m_path);
00128           std::swap(m_access, lk.m_access);
00129       }
00130 
00131       /** \depreciated Same ass release(). */
00132       void unlock() { release(); }
00133 
00134       /** \depreciated Use another constructor.
00135        ** Construct a handle and create the lock file with the given
00136        ** name if possible. If blocking=true it will hang until it
00137        ** manages to create the lock.  */
00138       lock_file(std::string path, bool blocking)
00139           : m_access(access_rw)
00140       {
00141           lock(path, blocking);
00142       }
00143       /** \depreciated Use \c access().
00144        ** Returns true after successful locking and before
00145        ** unlock(). */
00146       bool have_lock() const { return m_access == access_rw; }
00147 
00148       /** \depreciated
00149        ** Establish the lock with the given file name. */
00150       void lock(std::string path, bool blocking);
00151 
00152     private:
00153       std::string       m_path;
00154       access_t          m_access;
00155       int*              m_cnt;
00156   };
00157 
00158   struct lock_file_restorer
00159   {
00160       explicit lock_file_restorer(lock_file& lk)
00161           : m_lk(lk), m_acc(lk.access()) {}
00162 
00163       ~lock_file_restorer() { m_lk.adjust(m_acc); }
00164 
00165     private:
00166       lock_file& m_lk;
00167       access_t m_acc;
00168   };
00169 
00170 }}
00171 
00172 #endif

Generated on Sat Sep 7 19:11:16 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.