class Pool implements IPool {

    public Object take() throws PoolTakeException {
        if (freeItemsCounter.getAndDecrement() <= 0) {
            freeItemsCounter.getAndIncrement();
            try {
                throw new PoolTakeException("Reached limit of items for this pool.", new OutOfResourceException(this));
            } catch (InvalidArgumentException ex) {
                throw new PoolTakeException("Reached limit of items for this pool.", ex);
            }
        }

        try {
            Object result = freeItems.poll();
            if (result == null) {
                result = creationFunction.get();
            }

            return result;
        } catch (Exception e) {
            freeItemsCounter.getAndIncrement();
            throw new PoolTakeException("Failed to get item", e);
        }
    }

    public  Pool(final Integer maxItems, final Supplier<Object>  func);

}