00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _OASYS_LOCK_H_
00019 #define _OASYS_LOCK_H_
00020
00021 #include "Atomic.h"
00022 #include "Thread.h"
00023
00024 #include "../debug/Logger.h"
00025 #include "../util/Pointers.h"
00026
00027 namespace oasys {
00028
00032 class Lock : public Logger {
00033 public:
00037 Lock() : Logger("Lock", "/lock"),
00038 lock_count_(0),
00039 lock_holder_(0),
00040 lock_holder_name_(0),
00041 scope_lock_count_(0)
00042 {}
00043
00048 virtual ~Lock()
00049 {
00050 if (is_locked()) {
00051 ASSERT(is_locked_by_me());
00052 ASSERT(scope_lock_count_ == 0);
00053 }
00054 }
00055
00061 virtual int lock(const char* lock_user) = 0;
00062
00068 virtual int unlock() = 0;
00069
00075 virtual int try_lock(const char* lock_user) = 0;
00076
00082 bool is_locked()
00083 {
00084 return (lock_count_.value != 0);
00085 }
00086
00093 bool is_locked_by_me()
00094 {
00095 return is_locked() &&
00096 pthread_equal(lock_holder_, Thread::current());
00097 }
00098
00099 protected:
00100 friend class ScopeLock;
00101 friend class ScopeLockIf;
00102
00108 atomic_t lock_count_;
00109
00120 volatile pthread_t lock_holder_;
00121
00126 const char* lock_holder_name_;
00127
00134 int scope_lock_count_;
00135 };
00136
00150 class ScopeLock {
00151 public:
00152 ScopeLock()
00153 : lock_(NULL)
00154 {
00155 }
00156
00157 ScopeLock(Lock* l,
00158 const char* lock_user)
00159 : lock_(l)
00160 {
00161 do_lock(lock_user);
00162 }
00163
00164 ScopeLock(const Lock* l,
00165 const char* lock_user)
00166 : lock_(const_cast<Lock*>(l))
00167 {
00168 do_lock(lock_user);
00169 }
00170
00171 ScopeLock(oasys::ScopePtr<Lock> l,
00172 const char* lock_user)
00173 : lock_(l.ptr())
00174 {
00175 do_lock(lock_user);
00176 }
00177
00178 void set_lock(Lock* l, const char* lock_user)
00179 {
00180 lock_ = l;
00181 do_lock(lock_user);
00182 }
00183
00184 void do_lock(const char* lock_user) {
00185 ASSERT(lock_ != NULL);
00186 int ret = lock_->lock(lock_user);
00187 ASSERT(ret == 0);
00188 lock_->scope_lock_count_++;
00189 }
00190
00191 void unlock() {
00192 if (lock_ != NULL) {
00193 lock_->scope_lock_count_--;
00194 lock_->unlock();
00195 lock_ = NULL;
00196 }
00197 }
00198
00199 ~ScopeLock()
00200 {
00201 if (lock_) {
00202 unlock();
00203 }
00204 }
00205
00206 protected:
00207 Lock* lock_;
00208 };
00209
00215 class ScopeLockIf {
00216 public:
00217 ScopeLockIf(Lock* l,
00218 const char* lock_user,
00219 bool use_lock)
00220 : lock_(l), use_lock_(use_lock)
00221 {
00222 do_lock(lock_user);
00223 }
00224
00225 ScopeLockIf(const Lock* l,
00226 const char* lock_user,
00227 bool use_lock)
00228 : lock_(const_cast<Lock*>(l)), use_lock_(use_lock)
00229 {
00230 do_lock(lock_user);
00231 }
00232
00233 ScopeLockIf(oasys::ScopePtr<Lock> l,
00234 const char* lock_user,
00235 bool use_lock)
00236 : lock_(l.ptr()), use_lock_(use_lock)
00237 {
00238 do_lock(lock_user);
00239 }
00240
00241 void do_lock(const char* lock_user) {
00242 if (use_lock_)
00243 {
00244 int ret = lock_->lock(lock_user);
00245 ASSERT(ret == 0);
00246 lock_->scope_lock_count_++;
00247 }
00248 }
00249
00250 void unlock() {
00251 if (use_lock_)
00252 {
00253 lock_->scope_lock_count_--;
00254 lock_->unlock();
00255 lock_ = 0;
00256 }
00257 }
00258
00259 ~ScopeLockIf()
00260 {
00261 if (use_lock_ && lock_) {
00262 unlock();
00263 }
00264 }
00265
00266 protected:
00267 Lock* lock_;
00268 bool use_lock_;
00269 };
00270
00271 }
00272
00273 #endif