1 // Blocker.cpp 2 3 #include <new> 4 5 #include "Blocker.h" 6 7 // Data 8 struct Blocker::Data { 9 Data() 10 : semaphore(create_sem(0, "blocker")), 11 references(1), 12 userData(0) 13 { 14 } 15 16 Data(sem_id semaphore) 17 : semaphore(semaphore), 18 references(1) 19 { 20 } 21 22 ~Data() 23 { 24 if (semaphore >= 0) 25 delete_sem(semaphore); 26 } 27 28 sem_id semaphore; 29 int32 references; 30 int32 userData; 31 }; 32 33 // constructor 34 Blocker::Blocker() 35 : fData(new(std::nothrow) Data) 36 { 37 } 38 39 // constructor 40 Blocker::Blocker(sem_id semaphore) 41 : fData(new(std::nothrow) Data(semaphore)) 42 { 43 if (!fData) 44 delete_sem(semaphore); 45 } 46 47 // copy constructor 48 Blocker::Blocker(const Blocker& other) 49 : fData(NULL) 50 { 51 *this = other; 52 } 53 54 // destructor 55 Blocker::~Blocker() 56 { 57 _Unset(); 58 } 59 60 // InitCheck 61 status_t 62 Blocker::InitCheck() const 63 { 64 if (!fData) 65 return B_NO_MEMORY; 66 return (fData->semaphore < 0 ? fData->semaphore : B_OK); 67 } 68 69 // PrepareForUse 70 status_t 71 Blocker::PrepareForUse() 72 { 73 // check initialization 74 if (!fData || fData->semaphore < 0) 75 return B_NO_INIT; 76 // get semaphore count 77 int32 count; 78 status_t error = get_sem_count(fData->semaphore, &count); 79 if (error != B_OK) 80 return error; 81 // set the semaphore count to zero 82 if (count > 0) 83 error = acquire_sem_etc(fData->semaphore, count, B_RELATIVE_TIMEOUT, 0); 84 else if (count < 0) 85 error = release_sem_etc(fData->semaphore, -count, 0); 86 return error; 87 } 88 89 // Block 90 status_t 91 Blocker::Block(int32* userData) 92 { 93 if (!fData || fData->semaphore < 0) 94 return B_NO_INIT; 95 96 status_t error = acquire_sem(fData->semaphore); 97 98 if (userData) 99 *userData = fData->userData; 100 101 return error; 102 } 103 104 // Unblock 105 status_t 106 Blocker::Unblock(int32 userData) 107 { 108 if (!fData || fData->semaphore < 0) 109 return B_NO_INIT; 110 111 fData->userData = userData; 112 113 return release_sem(fData->semaphore); 114 } 115 116 // = 117 Blocker& 118 Blocker::operator=(const Blocker& other) 119 { 120 _Unset(); 121 fData = other.fData; 122 if (fData) 123 fData->references++; 124 return *this; 125 } 126 127 // == 128 bool 129 Blocker::operator==(const Blocker& other) const 130 { 131 return (fData == other.fData); 132 } 133 134 // != 135 bool 136 Blocker::operator!=(const Blocker& other) const 137 { 138 return (fData != other.fData); 139 } 140 141 // _Unset 142 void 143 Blocker::_Unset() 144 { 145 if (fData) { 146 if (--fData->references == 0) 147 delete fData; 148 fData = NULL; 149 } 150 } 151 152