LCOV - code coverage report
Current view: top level - server/util/git - CloseablePool.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 22 29 75.9 %
Date: 2022-11-19 15:00:39 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2022 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.util.git;
      16             : 
      17             : import com.google.common.flogger.FluentLogger;
      18             : import java.util.ArrayList;
      19             : import java.util.List;
      20             : import java.util.function.Supplier;
      21             : 
      22             : /**
      23             :  * Pool to manage resources that need to be closed but to whom we might lose the reference to or
      24             :  * where closing resources individually is not always possible.
      25             :  *
      26             :  * <p>This pool can be used when we want to reuse closable resources in a multithreaded context.
      27             :  * Example:
      28             :  *
      29             :  * <pre>{@code
      30             :  * try (CloseablePool<T> pool = new CloseablePool(() -> new T())) {
      31             :  *   for (int i = 0; i < 100; i++) {
      32             :  *     executor.submit(() -> {
      33             :  *       try (CloseablePool<T>.Handle handle = pool.get()) {
      34             :  *         // Do work that might potentially take longer than the timeout.
      35             :  *         handle.get(); // pooled instance to be used
      36             :  *       }
      37             :  *     }).get(1000, MILLISECONDS);
      38             :  *   }
      39             :  * }
      40             :  * }</pre>
      41             :  */
      42             : public class CloseablePool<T extends AutoCloseable> implements AutoCloseable {
      43          93 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      44             : 
      45             :   private final Supplier<T> tCreator;
      46             :   private List<T> ts;
      47             : 
      48             :   /**
      49             :    * Instantiate a new pool. The {@link Supplier} must be capable of creating a new instance on
      50             :    * every call.
      51             :    */
      52          93 :   public CloseablePool(Supplier<T> tCreator) {
      53          93 :     this.ts = new ArrayList<>();
      54          93 :     this.tCreator = tCreator;
      55          93 :   }
      56             : 
      57             :   /**
      58             :    * Get a shared instance or create a new instance. Close the returned handle to return it to the
      59             :    * pool.
      60             :    */
      61             :   public synchronized Handle get() {
      62          93 :     if (ts.isEmpty()) {
      63          93 :       return new Handle(tCreator.get());
      64             :     }
      65          93 :     return new Handle(ts.remove(ts.size() - 1));
      66             :   }
      67             : 
      68             :   private synchronized boolean discard(T t) {
      69          93 :     if (ts != null) {
      70          93 :       ts.add(t);
      71          93 :       return true;
      72             :     }
      73           0 :     return false;
      74             :   }
      75             : 
      76             :   @Override
      77             :   public synchronized void close() {
      78          93 :     for (T t : ts)
      79             :       try {
      80          93 :         t.close();
      81           0 :       } catch (Exception e) {
      82           0 :         logger.atWarning().withCause(e).log(
      83             :             "Failed to close resource %s in CloseablePool %s", t, this);
      84          93 :       }
      85          93 :     ts = null;
      86          93 :   }
      87             : 
      88             :   /**
      89             :    * Wrapper around an {@link AutoCloseable}. Will try to return the resource to the pool and close
      90             :    * it in case the pool was already closed.
      91             :    */
      92             :   public class Handle implements AutoCloseable {
      93             :     private final T t;
      94             : 
      95          93 :     private Handle(T t) {
      96          93 :       this.t = t;
      97          93 :     }
      98             : 
      99             :     /** Returns the managed instance. */
     100             :     public T get() {
     101          93 :       return t;
     102             :     }
     103             : 
     104             :     @Override
     105             :     public void close() {
     106          93 :       if (!discard(t)) {
     107             :         try {
     108           0 :           t.close();
     109           0 :         } catch (Exception e) {
     110           0 :           logger.atWarning().withCause(e).log(
     111             :               "Failed to close resource %s in CloseablePool %s", this, CloseablePool.this);
     112           0 :         }
     113             :       }
     114          93 :     }
     115             :   }
     116             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750