1 // RequestPortPool.cpp 2 3 #include "RequestPortPool.h" 4 5 #include <stdlib.h> 6 7 #include "AutoLocker.h" 8 #include "Debug.h" 9 #include "RequestPort.h" 10 11 typedef AutoLocker<RequestPortPool> PoolLocker; 12 13 // constructor RequestPortPool()14RequestPortPool::RequestPortPool() 15 : fPorts(NULL), 16 fPortCount(0), 17 fFreePorts(0), 18 fFreePortSemaphore(-1), 19 fDisconnected(false) 20 { 21 fFreePortSemaphore = create_sem(0, "request port pool"); 22 } 23 24 // destructor ~RequestPortPool()25RequestPortPool::~RequestPortPool() 26 { 27 delete_sem(fFreePortSemaphore); 28 free(fPorts); 29 } 30 31 // InitCheck 32 status_t InitCheck() const33RequestPortPool::InitCheck() const 34 { 35 if (fFreePortSemaphore < 0) 36 return fFreePortSemaphore; 37 return B_OK; 38 } 39 40 // IsDisconnected 41 bool IsDisconnected() const42RequestPortPool::IsDisconnected() const 43 { 44 return fDisconnected; 45 } 46 47 // AddPort 48 status_t AddPort(RequestPort * port)49RequestPortPool::AddPort(RequestPort* port) 50 { 51 if (!port) 52 return B_BAD_VALUE; 53 PoolLocker _(this); 54 // resize the port array 55 PortAcquirationInfo* ports = (PortAcquirationInfo*)realloc(fPorts, 56 (fPortCount + 1) * sizeof(PortAcquirationInfo)); 57 if (!ports) 58 return B_NO_MEMORY; 59 fPorts = ports; 60 // add the port as used port and let AcquirePort() free it 61 fPorts[fPortCount].port = port; 62 fPorts[fPortCount].owner = -1; 63 fPorts[fPortCount].count = 1; 64 fPortCount++; 65 ReleasePort(port); 66 return B_OK; 67 } 68 69 // AcquirePort 70 RequestPort* AcquirePort()71RequestPortPool::AcquirePort() 72 { 73 // first check whether the thread does already own a port 74 thread_id thread = find_thread(NULL); 75 { 76 PoolLocker _(this); 77 if (fDisconnected) 78 return NULL; 79 for (int32 i = fFreePorts; i < fPortCount; i++) { 80 PortAcquirationInfo& info = fPorts[i]; 81 if (info.owner == thread) { 82 info.count++; 83 return info.port; 84 } 85 } 86 } 87 // the thread doesn't own a port yet, find a free one 88 status_t error = acquire_sem(fFreePortSemaphore); 89 if (error != B_OK) 90 return NULL; 91 PoolLocker _(this); 92 if (fDisconnected) 93 return NULL; 94 if (fFreePorts < 1) { 95 FATAL(("Inconsistent request port pool: We acquired the free port " 96 "semaphore, but there are no free ports.\n")); 97 return NULL; 98 } 99 PortAcquirationInfo& info = fPorts[--fFreePorts]; 100 info.owner = find_thread(NULL); 101 info.count = 1; 102 return info.port; 103 } 104 105 // ReleasePort 106 void ReleasePort(RequestPort * port)107RequestPortPool::ReleasePort(RequestPort* port) 108 { 109 if (!port) 110 return; 111 PoolLocker _(this); 112 // find the port 113 for (int32 i = fFreePorts; i < fPortCount; i++) { 114 PortAcquirationInfo& info = fPorts[i]; 115 if (info.port == port) { 116 if (--info.count == 0) { 117 // swap with first used port 118 if (i != fFreePorts) { 119 fPorts[i] = fPorts[fFreePorts]; 120 fPorts[fFreePorts].port = port; 121 } 122 fFreePorts++; 123 release_sem(fFreePortSemaphore); 124 } 125 if (port->InitCheck() != B_OK) 126 fDisconnected = true; 127 return; 128 } 129 } 130 WARN(("RequestPortPool::ReleasePort(%p): port not found\n", port)); 131 // Not found! 132 } 133 134