1 // Lockable.cpp 2 3 #include "Lockable.h" 4 5 6 // LockerCandidate 7 8 // constructor 9 LockerCandidate::LockerCandidate(Blocker blocker) 10 : fBlocker(blocker), 11 fThread(find_thread(NULL)) 12 { 13 } 14 15 // GetThread 16 thread_id 17 LockerCandidate::GetThread() const 18 { 19 return fThread; 20 } 21 22 // Block 23 status_t 24 LockerCandidate::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 35 status_t 36 LockerCandidate::Unblock(bool success) 37 { 38 return fBlocker.Unblock(success); 39 } 40 41 42 // #pragma mark - 43 44 // Lockable 45 46 // constructor 47 Lockable::Lockable() 48 : fLockOwner(-1), 49 fLockCounter(0) 50 { 51 } 52 53 // destructor 54 Lockable::~Lockable() 55 { 56 // unblock all 57 while (LockerCandidate* candidate = fLockerCandidates.First()) { 58 fLockerCandidates.Remove(candidate); 59 candidate->Unblock(false); 60 } 61 } 62 63 // Lock 64 bool 65 Lockable::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 76 void 77 Lockable::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 94 bool 95 Lockable::IsLocked() const 96 { 97 return (fLockOwner == find_thread(NULL)); 98 } 99 100 // QueueLockerCandidate 101 void 102 Lockable::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