<commit_before>#pragma once

#include "Object.h"
#include "ObjectPoolMonitor.h"
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <set>
#include RVALUE_HEADER
#include MEMORY_HEADER

template<class T>
struct NoOp {
  void operator()(T& op) const {}
};

template<class T>
struct Create {
  T* operator()() const { return new T(); }
};

/// <summary>
/// Templated base class for implementors who wish to have more direct control over Reset and Allocate
/// </summary>
template<class T>
class ObjectPoolBase
{
public:
  ObjectPoolBase(size_t limit = ~0, size_t maxPooled = ~0) :
    m_monitor(new ObjectPoolMonitor),
    m_limit(limit),
    m_maxPooled(maxPooled),
    m_outstanding(0)
  {}

  ~ObjectPoolBase(void) {
    // Transition the pool to the abandoned state:
    m_monitor->Abandon();

    for(auto q = m_objs.begin(); q != m_objs.end(); q++)
      delete *q;
  }

protected:
  std::shared_ptr<ObjectPoolMonitor> m_monitor;
  boost::condition_variable m_setCondition;

  typedef std::set<T*> t_stType;
  t_stType m_objs;

  size_t m_maxPooled;
  size_t m_limit;
  size_t m_outstanding;

  void Return(std::shared_ptr<ObjectPoolMonitor> monitor, T* ptr) {
    {
      boost::lock_guard<boost::mutex> lk(*monitor);
      if(!monitor->IsAbandoned()) {
        m_outstanding--;
        if(m_objs.size() < m_maxPooled) {
          // Reset, insert, return
          Reset(*ptr);
          m_objs.insert(ptr);
          m_setCondition.notify_one();
          return;
        }
      }

      m_setCondition.notify_one();
    }

    // Object wasn't added.  Destroy it.
    delete ptr;
  }

  /// <summary>
  /// Actually performs a reset of the passed object
  /// </summary>
  virtual void Reset(T& ptr) = 0;

  /// <summary>
  /// Creates a new instance of type T
  /// </summary>
  virtual T* Allocate(void) const = 0;

  /// <summary>
  /// Obtains an element from the object queue, assumes exterior synchronization<commit_msg>Returned entities should wake up all waiters<commit_after>#pragma once

#include "Object.h"
#include "ObjectPoolMonitor.h"
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <set>
#include RVALUE_HEADER
#include MEMORY_HEADER

template<class T>
struct NoOp {
  void operator()(T& op) const {}
};

template<class T>
struct Create {
  T* operator()() const { return new T(); }
};

/// <summary>
/// Templated base class for implementors who wish to have more direct control over Reset and Allocate
/// </summary>
template<class T>
class ObjectPoolBase
{
public:
  ObjectPoolBase(size_t limit = ~0, size_t maxPooled = ~0) :
    m_monitor(new ObjectPoolMonitor),
    m_limit(limit),
    m_maxPooled(maxPooled),
    m_outstanding(0)
  {}

  ~ObjectPoolBase(void) {
    // Transition the pool to the abandoned state:
    m_monitor->Abandon();

    for(auto q = m_objs.begin(); q != m_objs.end(); q++)
      delete *q;
  }

protected:
  std::shared_ptr<ObjectPoolMonitor> m_monitor;
  boost::condition_variable m_setCondition;

  typedef std::set<T*> t_stType;
  t_stType m_objs;

  size_t m_maxPooled;
  size_t m_limit;
  size_t m_outstanding;

  void Return(std::shared_ptr<ObjectPoolMonitor> monitor, T* ptr) {
    // Ensure the object gets destroyed if we don't add it:
    std::unique_ptr<T> lcl(ptr);

    boost::lock_guard<boost::mutex> lk(*monitor);
    if(monitor->IsAbandoned())
      // Nothing we can do, monitor object abandoned already, just destroy the object
      return;
    
    // One fewer outstanding count:
    m_outstanding--;
    if(m_objs.size() < m_maxPooled) {
      // Reset, insert, return
      Reset(*ptr);
      m_objs.insert(ptr);
    }

    // If the new outstanding count is less than or equal to the limit, wake up any waiters:
    if(m_outstanding <= m_limit)
      m_setCondition.notify_all();
  }

  /// <summary>
  /// Actually performs a reset of the passed object
  /// </summary>
  virtual void Reset(T& ptr) = 0;

  /// <summary>
  /// Creates a new instance of type T
  /// </summary>
  virtual T* Allocate(void) const = 0;

  /// <summary>
  /// Obtains an element from the object queue, assumes exterior synchronization
{'fraction_non_alphanumeric': 0.1272770853307766, 'fraction_numerical': 0.0023969319271332696, 'mean_word_length': 3.253822629969419, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5846933', 'n_tokens_mistral': 1401, 'n_tokens_neox': 1368, 'n_words': 378}