1// Lockable.cpp 2 3#include "Lockable.h" 4 5 6// LockerCandidate 7 8// constructor 9LockerCandidate::LockerCandidate(Blocker blocker) 10 : fBlocker(blocker), 11 fThread(find_thread(NULL)) 12{ 13} 14 15// GetThread 16thread_id 17LockerCandidate::GetThread() const 18{ 19 return fThread; 20} 21 22// Block 23status_t 24LockerCandidate::Block() 25{ 26 int32 userData; 27 status_t error = fBlocker.Block(&userData); 28 if (error != B_OK) 29 return error; 30 31 return (userData ? B_OK : B_ENTRY_NOT_FOUND); 32} 33 34// Unblock 35status_t 36LockerCandidate::Unblock(bool success) 37{ 38 return fBlocker.Unblock(success); 39} 40 41 42// #pragma mark - 43 44// Lockable 45 46// constructor 47Lockable::Lockable() 48 : fLockOwner(-1), 49 fLockCounter(0) 50{ 51} 52 53// destructor 54Lockable::~Lockable() 55{ 56 // unblock all 57 while (LockerCandidate* candidate = fLockerCandidates.First()) { 58 fLockerCandidates.Remove(candidate); 59 candidate->Unblock(false); 60 } 61} 62 63// Lock 64bool 65Lockable::Lock() 66{ 67 thread_id thread = find_thread(NULL); 68 if (fLockOwner >= 0 && fLockOwner != thread) 69 return false; 70 fLockOwner = thread; 71 fLockCounter++; 72 return true; 73} 74 75// Unlock 76void 77Lockable::Unlock() 78{ 79 thread_id thread = find_thread(NULL); 80 if (fLockOwner != thread) 81 return; 82 if (--fLockCounter > 0) 83 return; 84 if (LockerCandidate* candidate = fLockerCandidates.First()) { 85 fLockerCandidates.Remove(candidate); 86 fLockOwner = candidate->GetThread(); 87 fLockCounter = 1; 88 candidate->Unblock(true); 89 } else 90 fLockOwner = -1; 91} 92 93// IsLocked 94bool 95Lockable::IsLocked() const 96{ 97 return (fLockOwner == find_thread(NULL)); 98} 99 100// QueueLockerCandidate 101void 102Lockable::QueueLockerCandidate(LockerCandidate* candidate) 103{ 104 if (!candidate) 105 return; 106 if (fLockOwner >= 0) { 107 fLockerCandidates.Insert(candidate); 108 } else { 109 // if the object is not locked, wake up the candidate right now 110 fLockOwner = candidate->GetThread(); 111 fLockCounter = 1; 112 candidate->Unblock(true); 113 } 114} 115