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