text: /*
   * (C) Copyright 1996- ECMWF.
   *
   * This software is licensed under the terms of the Apache Licence Version 2.0
   * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
   * In applying this licence, ECMWF does not waive the privileges and immunities
   * granted to it by virtue of its status as an intergovernmental organisation
   * nor does it submit to any jurisdiction.
   */
  
  /// @author Tiago Quintino
  /// @date Dec 2015
  
  
  #ifndef eckit_io_FilePool_h
  #define eckit_io_FilePool_h
  
  #include "eckit/memory/NonCopyable.h"
  #include "eckit/thread/MutexCond.h"
  #include "eckit/container/CacheLRU.h"
  
  namespace eckit {
      class DataHandle;
      class PathName;
  }
  
  namespace eckit {
  
  //----------------------------------------------------------------------------------------------------------------------
  
  /// Pool of a maximum number of open files.
  /// Open files manipulated via DataHandle interface.
  /// Handles are kept open as long as possible following LRU algorithm
  /// Handles must be checked-out before usage, should be checked back in once writing finished.
  /// No limit to number of checked out handles.
  /// Handles are closed when purged from pool due to LRU or when pool is destroyed.
  ///
  /// @note this class is thread-safe
  ///
  class FilePool : private eckit::NonCopyable {
  
  public:
  
      FilePool(size_t capacity);
  
      ~FilePool();
  
      /// Checkout a DataHandle for use
      /// Ownership is passed from FilePool to the client
      /// @post DataHandle is marked in use and should not be closed by client
      /// @invariant If handle is in use, it assumes is from another thread and it will wait() for a checkin()
      DataHandle * checkout(const PathName& path);
  
      /// Return a DataHandle after use
      /// Ownership is passed back from the client to FilePool
      /// @post DataHandle is marked out of use and may now be closed by FilePool
      void checkin(DataHandle* handle);
  
      /// Remove a DataHandle from the pool
      /// @invariant If handle is in use, it assumes is from another thread and it will wait() for a checkin()
      bool remove(const PathName& path);
  
      /// Current size of pool
      size_t size() const;
  
      /// Resize pool capacity
      void capacity( size_t size );
  
      /// Returns max size of pool
      size_t capacity() const;
  
      /// Returns number of checked-out DataHandles
      size_t usage() const;
  
      /// Lists the contents of the Pool both in use and cached DataHandle's
      void print(std::ostream& os) const;
  
      friend std::ostream& operator<<(std::ostream& s, const FilePool& p) { p.print(s); return s; }
  
  private:
  
      std::map< PathName, DataHandle* > inUse_;
  
      eckit::CacheLRU< PathName, DataHandle* > cache_;
  
      mutable eckit::MutexCond cond_;
  };
  
  //----------------------------------------------------------------------------------------------------------------------
  
  } // namespace eckit
  
  #endif
  
  