private T getOrCreate() throws E { try { T client = elements.poll(); // a client was available, all good. otherwise, create one if (client != null) { return client; } return create(); } catch (Exception e) { // if an exception is thrown after acquiring the semaphore, release the // semaphore before propagating the exception semaphore.release(); throw e; } }