00001 //# LatticeLocker.h: Class to hold a (user) lock on a lattice 00002 //# Copyright (C) 1999,2000 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef LATTICES_LATTICELOCKER_H 00029 #define LATTICES_LATTICELOCKER_H 00030 00031 00032 //# Includes 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/lattices/Lattices/LatticeBase.h> 00035 #include <casacore/tables/Tables/TableLock.h> 00036 00037 00038 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00039 00040 // <summary> 00041 // Class to hold a (user) lock on a lattice. 00042 // </summary> 00043 00044 // <use visibility=export> 00045 00046 // <reviewed reviewer="" date="" tests="tTableLockSync.cc"> 00047 // </reviewed> 00048 00049 // <prerequisite> 00050 //# Classes you should understand before using this one. 00051 // <li> <linkto class=Lattice>Lattice</linkto> 00052 // <li> <linkto class=TableLock>TableLock</linkto> 00053 // </prerequisite> 00054 00055 // <synopsis> 00056 // Class LatticeLocker can be used to acquire a (user) lock on a lattice. 00057 // The lock can be a read or write lock. 00058 // The destructor releases the lock when needed. 00059 // <p> 00060 // LatticeLocker simply uses the <src>lock</src> and <src>unlock</src> 00061 // function of class Lattice. 00062 // The advantage of LatticeLocker over these functions is that the 00063 // destructor of LatticeLocker is called automatically by the system, 00064 // so unlocking the lattice does not need to be done explicitly and 00065 // cannot be forgotten. Especially in case of exception handling this 00066 // can be quite an adavantage. 00067 // <p> 00068 // This class is meant to be used with the UserLocking option. 00069 // It can, however, also be used with the other locking options. 00070 // In case of PermanentLocking(Wait) it won't do anything at all. 00071 // In case of AutoLocking it will acquire and release the lock when 00072 // needed. However, it is possible that the system releases an 00073 // auto lock before the LatticeLocker destructor is called. 00074 // <p> 00075 // The constructor of LatticeLocker will look if the lattice is 00076 // already appropriately locked. If so, it will set a flag to 00077 // prevent the destructor from unlocking the lattice. In this way 00078 // nested locks can be used. I.e. one can safely use LatticeLocker 00079 // in a function without having to be afraid that its destructor 00080 // would undo a lock set in a higher function. 00081 // <br>Similarly LatticeLocker will remember if a lattice was 00082 // already read-locked, when a write-lock is acquired. In such a 00083 // case the destructor will try to ensure that the lattice remains 00084 // read-locked. 00085 // </synopsis> 00086 00087 // <example> 00088 // <srcblock> 00089 // // Open a lattice to be updated. 00090 // PagedArray<Float> myLattice (Table ("theLattice", 00091 // LatticeLock::UserLocking, 00092 // Lattice::Update); 00093 // // Start of some critical section requiring a lock. 00094 // { 00095 // LatticeLocker lock1 (myLattice, FileLocker::Write); 00096 // ... write the data 00097 // } 00098 // // The LatticeLocker destructor invoked by } unlocks the table. 00099 // </srcblock> 00100 // </example> 00101 00102 // <motivation> 00103 // LatticeLocker makes it easier to unlock a lattice. 00104 // It also makes it easier to use locking in a nested way. 00105 // </motivation> 00106 00107 //# <todo asof="$DATE:$"> 00108 //# A List of bugs, limitations, extensions or planned refinements. 00109 //# </todo> 00110 00111 00112 class LatticeLocker 00113 { 00114 public: 00115 // The constructor acquires a read or write lock on a lattice. 00116 // If the lattice was already locked, the destructor will 00117 // not unlock the lattice. This means that the class can be used in 00118 // a nested way. 00119 // <br> 00120 // The number of attempts (default = forever) can be specified when 00121 // acquiring the lock does not succeed immediately. When nattempts>1, 00122 // the system waits 1 second between each attempt, so nattempts 00123 // is more or less equal to a wait period in seconds. 00124 // An exception is thrown when the lock cannot be acquired. 00125 explicit LatticeLocker (LatticeBase& lattice, 00126 FileLocker::LockType, 00127 uInt nattempts = 0); 00128 00129 // If the constructor acquired the lock, the destructor releases 00130 // the lock and flushes the data if changed. 00131 ~LatticeLocker(); 00132 00133 // Has this process the read or write lock, thus can the table 00134 // be read or written safely? 00135 Bool hasLock (FileLocker::LockType) const; 00136 00137 private: 00138 // The copy constructor and assignment are not possible. 00139 // Note that only one lock can be held on a lattice, so copying a 00140 // TableLocker object imposes great difficulties which object should 00141 // release the lock. 00142 // It can be solved by turning LatticeLocker into a handle class 00143 // with a reference counted body class. 00144 // However, that will only be done when the need arises. 00145 // <group> 00146 LatticeLocker (const LatticeLocker&); 00147 LatticeLocker& operator= (const LatticeLocker&); 00148 // </group> 00149 00150 //# Variables. 00151 LatticeBase* itsLatticePtr; 00152 Bool itsOwnLock; 00153 Bool itsHadReadLock; 00154 }; 00155 00156 00157 inline Bool LatticeLocker::hasLock (FileLocker::LockType type) const 00158 { 00159 return itsLatticePtr->hasLock (type); 00160 } 00161 00162 00163 00164 } //# NAMESPACE CASACORE - END 00165 00166 #endif