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 11 AbstractConnection::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 23 AbstractConnection::~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 46 status_t 47 AbstractConnection::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 58 void 59 AbstractConnection::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 83 status_t 84 AbstractConnection::AddDownStreamChannel(Channel* channel) 85 { 86 if (!channel) 87 return B_BAD_VALUE; 88 return fDownStreamChannels.PushBack(channel); 89 } 90 91 // AddUpStreamChannel 92 status_t 93 AbstractConnection::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 106 int32 107 AbstractConnection::CountDownStreamChannels() const 108 { 109 return fDownStreamChannels.Count(); 110 } 111 112 // GetDownStreamChannel 113 Channel* 114 AbstractConnection::DownStreamChannelAt(int32 index) const 115 { 116 if (index < 0 || index >= fDownStreamChannels.Count()) 117 return NULL; 118 return fDownStreamChannels.ElementAt(index); 119 } 120 121 // GetUpStreamChannel 122 status_t 123 AbstractConnection::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 148 status_t 149 AbstractConnection::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