1// AbstractConnection.cpp 2 3#include "AbstractConnection.h" 4#include "AutoLocker.h" 5#include "Channel.h" 6#include "Debug.h" 7 8// constructor 9AbstractConnection::AbstractConnection() 10 : Connection(), 11 fInitStatus(B_NO_INIT), 12 fDownStreamChannels(), 13 fUpStreamChannelSemaphore(-1), 14 fUpStreamChannelLock(), 15 fUpStreamChannels(), 16 fFreeUpStreamChannels(0) 17{ 18} 19 20// destructor 21AbstractConnection::~AbstractConnection() 22{ 23 // Danger: If derived classes implement Close(), this call will not reach 24 // them. So, the caller should rather call Close() explicitely before 25 // destroying the connection. 26 Close(); 27 // delete all channels 28 for (ChannelVector::Iterator it = fDownStreamChannels.Begin(); 29 it != fDownStreamChannels.End(); 30 it++) { 31 delete *it; 32 } 33 fDownStreamChannels.MakeEmpty(); 34 AutoLocker<Locker> _(fUpStreamChannelLock); 35 for (ChannelVector::Iterator it = fUpStreamChannels.Begin(); 36 it != fUpStreamChannels.End(); 37 it++) { 38 delete *it; 39 } 40 fUpStreamChannels.MakeEmpty(); 41} 42 43// Init 44status_t 45AbstractConnection::Init() 46{ 47 fInitStatus = B_OK; 48 // create upstream channel semaphore 49 fUpStreamChannelSemaphore = create_sem(0, "upstream channels"); 50 if (fUpStreamChannelSemaphore < 0) 51 return (fInitStatus = fUpStreamChannelSemaphore); 52 return fInitStatus; 53} 54 55// Close 56void 57AbstractConnection::Close() 58{ 59 // close all channels 60 for (ChannelVector::Iterator it = fDownStreamChannels.Begin(); 61 it != fDownStreamChannels.End(); 62 it++) { 63 (*it)->Close(); 64 } 65 AutoLocker<Locker> _(fUpStreamChannelLock); 66 for (ChannelVector::Iterator it = fUpStreamChannels.Begin(); 67 it != fUpStreamChannels.End(); 68 it++) { 69 (*it)->Close(); 70 } 71} 72 73//// GetAuthorizedUser 74//User* 75//AbstractConnection::GetAuthorizedUser() 76//{ 77// return NULL; 78//} 79 80// AddDownStreamChannel 81status_t 82AbstractConnection::AddDownStreamChannel(Channel* channel) 83{ 84 if (!channel) 85 return B_BAD_VALUE; 86 return fDownStreamChannels.PushBack(channel); 87} 88 89// AddUpStreamChannel 90status_t 91AbstractConnection::AddUpStreamChannel(Channel* channel) 92{ 93 if (!channel) 94 return B_BAD_VALUE; 95 AutoLocker<Locker> _(fUpStreamChannelLock); 96 status_t error = fUpStreamChannels.PushBack(channel); 97 if (error != B_OK) 98 return error; 99 PutUpStreamChannel(channel); 100 return B_OK; 101} 102 103// CountDownStreamChannels 104int32 105AbstractConnection::CountDownStreamChannels() const 106{ 107 return fDownStreamChannels.Count(); 108} 109 110// GetDownStreamChannel 111Channel* 112AbstractConnection::DownStreamChannelAt(int32 index) const 113{ 114 if (index < 0 || index >= fDownStreamChannels.Count()) 115 return NULL; 116 return fDownStreamChannels.ElementAt(index); 117} 118 119// GetUpStreamChannel 120status_t 121AbstractConnection::GetUpStreamChannel(Channel** channel, bigtime_t timeout) 122{ 123 if (!channel) 124 return B_BAD_VALUE; 125 if (timeout < 0) 126 timeout = 0; 127 // acquire the semaphore 128 status_t error = acquire_sem_etc(fUpStreamChannelSemaphore, 1, 129 B_RELATIVE_TIMEOUT, timeout); 130 if (error != B_OK) 131 return error; 132 // we've acquire the semaphore successfully, so a free channel must be 133 // waiting for us 134 AutoLocker<Locker> _(fUpStreamChannelLock); 135 if (fFreeUpStreamChannels < 1) { 136 ERROR(("AbstractConnection::GetUpStreamChannel(): Acquired the " 137 "upstream semaphore successfully, but there's no free channel!\n")); 138 return B_ERROR; 139 } 140 fFreeUpStreamChannels--; 141 *channel = fUpStreamChannels.ElementAt(fFreeUpStreamChannels); 142 return B_OK; 143} 144 145// PutUpStreamChannel 146status_t 147AbstractConnection::PutUpStreamChannel(Channel* channel) 148{ 149 if (!channel) 150 return B_BAD_VALUE; 151 // find the channel 152 AutoLocker<Locker> _(fUpStreamChannelLock); 153 int32 index = fUpStreamChannels.IndexOf(channel, fFreeUpStreamChannels); 154 if (index < 0) 155 return B_BAD_VALUE; 156 // swap it with the first non-free channel, release the semaphore, 157 // and bump the free channel count 158 if (index != fFreeUpStreamChannels) { 159 Channel*& target = fUpStreamChannels.ElementAt(fFreeUpStreamChannels); 160 fUpStreamChannels.ElementAt(index) = target; 161 target = channel; 162 } 163 status_t error = release_sem(fUpStreamChannelSemaphore); 164 if (error == B_OK) 165 fFreeUpStreamChannels++; 166 return error; 167} 168 169