TcpTransport& ConnectionPool::borrowObject(const InetSocketAddress& key) { if (closed) { throw new HotRodClientException("Pool is closed"); } if (!idle.count(key) || !busy.count(key)) { throw new HotRodClientException("Pool is closed"); } TransportQueuePtr idleQ = idle[key]; TransportQueuePtr busyQ = busy[key]; // See if an object is readily available TcpTransport* obj; bool ok = idleQ->poll(obj); for (;;) { if (ok) { // Check if the object is still valid, if not destroy it if (configuration.isTestOnBorrow() && !factory->validateObject(key, *obj)) { factory->destroyObject(key, *obj); ok = false; } // We have a valid object if (ok) { busyQ->push(obj); break; } } // See if we can create a new one if (busyQ->size() < configuration.getMaxActive()) { obj = &factory->makeObject(key); } else { // Wait for an object to become idle obj = idleQ->pop(); } ok = true; } factory->activateObject(key, *obj); return *obj; }
TcpTransport& ConnectionPool::borrowObject(const InetSocketAddress& key) { sys::ScopedLock<sys::Mutex> l(lock); if (closed) { throw HotRodClientException("Pool is closed"); } if (!idle.count(key) || !busy.count(key)) { throw HotRodClientException("Pool has no idle or no busy transports."); } TransportQueuePtr idleQ = idle[key]; TransportQueuePtr busyQ = busy[key]; // See if an object is readily available TcpTransport* obj = NULL; bool ok = idleQ->poll(obj); if (ok) { totalIdle--; } for (;;) { if (ok) { // Check if the object is still valid, if not destroy it if (configuration.isTestOnBorrow() && !factory->validateObject(key, *obj)) { factory->destroyObject(key, *obj); ok = false; } // We have a valid object if (ok) { busyQ->push(obj); totalActive++; break; } } // See if we can create a new one if (idleQ->size() == 0 && //the idle queue is empty (configuration.getMaxActive() < 0 || busyQ->size() < (size_t) configuration.getMaxActive()) && //max active not reached! !hasReachedMaxTotal()) { obj = &factory->makeObject(key); } else if (hasReachedMaxTotal()) { //max total reached. try to destroy a existing idle connection. if not possible, wait until some other connection is available. if (tryRemoveIdle()) { //removal successful. obj = &factory->makeObject(key); } else { allocationQueue.push(key); { sys::ScopedUnlock<sys::Mutex> u(lock); obj = idleQ->pop(); } totalIdle--; } } else { // Wait for an object to become idle { sys::ScopedUnlock<sys::Mutex> u(lock); obj = idleQ->pop(); } totalIdle--; } ok = true; } factory->activateObject(key, *obj); return *obj; }