1// Blocker.cpp 2 3#include <new> 4 5#include "Blocker.h" 6 7// Data 8struct 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 34Blocker::Blocker() 35 : fData(new(std::nothrow) Data) 36{ 37} 38 39// constructor 40Blocker::Blocker(sem_id semaphore) 41 : fData(new(std::nothrow) Data(semaphore)) 42{ 43 if (!fData) 44 delete_sem(semaphore); 45} 46 47// copy constructor 48Blocker::Blocker(const Blocker& other) 49 : fData(NULL) 50{ 51 *this = other; 52} 53 54// destructor 55Blocker::~Blocker() 56{ 57 _Unset(); 58} 59 60// InitCheck 61status_t 62Blocker::InitCheck() const 63{ 64 if (!fData) 65 return B_NO_MEMORY; 66 return (fData->semaphore < 0 ? fData->semaphore : B_OK); 67} 68 69// PrepareForUse 70status_t 71Blocker::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 90status_t 91Blocker::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 105status_t 106Blocker::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// = 117Blocker& 118Blocker::operator=(const Blocker& other) 119{ 120 _Unset(); 121 fData = other.fData; 122 if (fData) 123 fData->references++; 124 return *this; 125} 126 127// == 128bool 129Blocker::operator==(const Blocker& other) const 130{ 131 return (fData == other.fData); 132} 133 134// != 135bool 136Blocker::operator!=(const Blocker& other) const 137{ 138 return (fData != other.fData); 139} 140 141// _Unset 142void 143Blocker::_Unset() 144{ 145 if (fData) { 146 if (--fData->references == 0) 147 delete fData; 148 fData = NULL; 149 } 150} 151 152