<commit_before>#ifndef __boxed_value_hpp__
#define __boxed_value_hpp__

#include "type_info.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>

class Boxed_Value
{
  private:
    struct Data
    {
      Data(const Type_Info &ti,
           const boost::any &to,
           bool tr,
           const boost::function<bool ()> &t_unique = &Boxed_Value::Data::get_false)
        : m_type_info(ti), m_obj(to), 
          m_is_ref(tr)
      {
      }

      Data &operator=(const Data &rhs)
      {
        m_type_info = rhs.m_type_info;
        m_obj = rhs.m_obj;
        m_is_ref = rhs.m_is_ref;

        return *this;
      }

      static bool get_false()
      {
        return false;
      }

      Type_Info m_type_info;
      boost::any m_obj;
      bool m_is_ref;
    };

  public:
    struct Void_Type
    {
    };

    template<typename T>
      explicit Boxed_Value(boost::shared_ptr<T> obj)
       : m_data(new Data(
           Get_Type_Info<T>()(), 
           boost::any(obj), 
           false)
         )
      {
        boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj);

        std::map<void *, boost::shared_ptr<Data> >::iterator itr
          = m_ptrs.find(ptr->get());

        if (itr != m_ptrs.end())
        {
          m_data = (itr->second);
        } else {
          m_ptrs[ptr->get()] = m_data;
        }
      }

    template<typename T>
      explicit Boxed_Value(boost::reference_wrapper<T> obj)
       : m_data(new Data(
             Get_Type_Info<T>()(),
             boost::any(obj), 
             true)
           )
      {
        void *ptr = boost::any_cast<boost::reference_wrapper<T> >(m_data->m_obj).get_pointer();

        std::map<void *, boost::shared_ptr<Data> >::iterator itr
          = m_ptrs.find(ptr);

        if (itr != m_ptrs.end())
        {
//          std::cout << "Reference wrapper ptr found, using it" << std::endl;
          m_data = (itr->second);
        } 
      }

    template<typename T>
      explicit Boxed_Value(const T& t)
       : m_data(new Data(
             Get_Type_Info<T>()(), 
             boost::any(boost::shared_ptr<T>(new T(t))), 
             false)
           )
      {
        boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj);

        m_ptrs[ptr->get()]
          = m_data;
      }

    Boxed_Value(Boxed_Value::Void_Type)
      : m_data(new Data(
            Get_Type_Info<void>()(),
            boost::any(), 
            false)
          )
    {
    }

    Boxed_Value(const Boxed_Value &t_so)
      : m_data(t_so.m_data)
    {
    }

    Boxed_Value()
      : m_data(new Data(
            Type_Info(),
            boost::any(),
            false)
          )
    {
    }

    ~Boxed_Value()
    {
      cleanup_ptrs(m_ptrs);
    }

    Boxed_Value assign(const Boxed_Value &rhs)
    {
      (*m_data) = (*rhs.m_data);
      return *this;
    }

    Boxed_Value &operator=(const Boxed_Value &rhs)
    {
      m_data = rhs.m_data;
      return *this;
    }

    const Type_Info &get_type_info() const
    {
      return m_data->m_type_info;
    }

    bool is_unknown() const
    {
      return m_data->m_type_info.m_is_unknown;
    }

    boost::any get() const
    {
      return m_data->m_obj;
    }

    bool is_ref() const
    {
      return m_data->m_is_ref;
    }

  private:
    boost::shared_ptr<Data> m_data;
    static std::map<void *, boost::shared_ptr<Data> > m_ptrs;

    void cleanup_ptrs(std::map<void *, boost::shared_ptr<Data> > &m_ptrs)
    {
      std::map<void *, boost::shared_ptr<Data> >::iterator itr = m_ptrs.begin();
      
      while (itr != m_ptrs.end())
      {
        if (itr->second.unique())
        {
          std::map<void *, boost::shared_ptr<Data> >::iterator todel = itr;
//          std::cout << "Releasing unique ptr " << std::endl;
          ++itr;
          m_ptrs.erase(todel);
        } else {
          ++itr;
        }
      }

//      std::cout << "References held: " << m_ptrs.size() << std::endl;
    }
};

std::map<void *, boost::shared_ptr<Boxed_Value::Data> > Boxed_Value::m_ptrs;

//cast_help specializations
template<typename Result>
struct Cast_Helper
{
  typename boost::reference_wrapper<typename boost::add_const<Result>::type > operator()(Boxed_Value ob)
  {
    if (ob.is_ref())
    {<commit_msg>Reference counting working for reals now. Previously it was counting the wrong thing (but was almost good enough)<commit_after>#ifndef __boxed_value_hpp__
#define __boxed_value_hpp__

#include "type_info.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>

class Boxed_Value
{
  private:
    struct Data
    {
      struct Shared_Ptr_Proxy
      {
        virtual ~Shared_Ptr_Proxy()
        {
        }

        virtual bool unique(boost::any *) = 0;
        virtual long use_count(boost::any *) = 0;
      };

      template<typename T>
        struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
        {
          virtual ~Shared_Ptr_Proxy_Impl()
          {
          }

          virtual bool unique(boost::any *a)
          {
            boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
            return ptr->unique();
          }

          virtual long use_count(boost::any *a)
          {
            boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
            return ptr->use_count();
          }
         };

      Data(const Type_Info &ti,
           const boost::any &to,
           bool tr,
           const boost::shared_ptr<Shared_Ptr_Proxy> &t_proxy = boost::shared_ptr<Shared_Ptr_Proxy>())
        : m_type_info(ti), m_obj(to), 
          m_is_ref(tr), m_ptr_proxy(t_proxy)
      {
      }

      Data &operator=(const Data &rhs)
      {
        m_type_info = rhs.m_type_info;
        m_obj = rhs.m_obj;
        m_is_ref = rhs.m_is_ref;
        m_ptr_proxy = rhs.m_ptr_proxy;

        return *this;
      }

      static bool get_false()
      {
        return false;
      }

      Type_Info m_type_info;
      boost::any m_obj;
      bool m_is_ref;
      boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy;
    };

  public:
    struct Void_Type
    {
    };

    template<typename T>
      explicit Boxed_Value(boost::shared_ptr<T> obj)
       : m_data(new Data(
           Get_Type_Info<T>()(), 
           boost::any(obj), 
           false,
           boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
         )
      {
        boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj);

        std::map<void *, Data >::iterator itr
          = m_ptrs.find(ptr->get());

        if (itr != m_ptrs.end())
        {
          (*m_data) = (itr->second);
        } else {
          m_ptrs.insert(std::make_pair(ptr->get(), *m_data));
        }
      }

    template<typename T>
      explicit Boxed_Value(boost::reference_wrapper<T> obj)
       : m_data(new Data(
             Get_Type_Info<T>()(),
             boost::any(obj), 
             true)
           )
      {
        void *ptr = boost::any_cast<boost::reference_wrapper<T> >(m_data->m_obj).get_pointer();

        std::map<void *, Data >::iterator itr
          = m_ptrs.find(ptr);

        if (itr != m_ptrs.end())
        {
          std::cout << "Reference wrapper ptr found, using it" << std::endl;
          (*m_data) = (itr->second);
        } 
      }

    template<typename T>
      explicit Boxed_Value(const T& t)
       : m_data(new Data(
             Get_Type_Info<T>()(), 
             boost::any(boost::shared_ptr<T>(new T(t))), 
             false,
             boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
            )
      {
        boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj);

        m_ptrs.insert(std::make_pair(ptr->get(), *m_data));
      }

    Boxed_Value(Boxed_Value::Void_Type)
      : m_data(new Data(
            Get_Type_Info<void>()(),
            boost::any(), 
            false)
          )
    {
    }

    Boxed_Value(const Boxed_Value &t_so)
      : m_data(t_so.m_data)
    {
    }

    Boxed_Value()
      : m_data(new Data(
            Type_Info(),
            boost::any(),
            false)
          )
    {
    }

    ~Boxed_Value()
    {
      cleanup_ptrs(m_ptrs);
    }

    Boxed_Value assign(const Boxed_Value &rhs)
    {
      (*m_data) = (*rhs.m_data);
      return *this;
    }

    Boxed_Value &operator=(const Boxed_Value &rhs)
    {
      m_data = rhs.m_data;
      return *this;
    }

    const Type_Info &get_type_info() const
    {
      return m_data->m_type_info;
    }

    bool is_unknown() const
    {
      return m_data->m_type_info.m_is_unknown;
    }

    boost::any get() const
    {
      return m_data->m_obj;
    }

    bool is_ref() const
    {
      return m_data->m_is_ref;
    }

  private:
    boost::shared_ptr<Data> m_data;
    static std::map<void *, Data > m_ptrs;

    void cleanup_ptrs(std::map<void *, Data > &m_ptrs)
    {
      std::map<void *, Data >::iterator itr = m_ptrs.begin();
      
      while (itr != m_ptrs.end())
      {
        if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
        {
          std::map<void *, Data >::iterator todel = itr;
//          std::cout << "Releasing unique ptr " << std::endl;
          ++itr;
          m_ptrs.erase(todel);
        } else {
          ++itr;
        }
      }

//      std::cout << "References held: " << m_ptrs.size() << std::endl;
    }
};

std::map<void *, Boxed_Value::Data > Boxed_Value::m_ptrs;

//cast_help specializations
template<typename Result>
struct Cast_Helper
{
  typename boost::reference_wrapper<typename boost::add_const<Result>::type > operator()(Boxed_Value ob)
  {
    if (ob.is_ref())
    {
{'fraction_non_alphanumeric': 0.1407116218123173, 'fraction_numerical': 0.0003023888720895071, 'mean_word_length': 2.0021180030257186, 'pattern_counts': {'":': 0, '<': 121, '<?xml version=': 0, '>': 123, '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': '1433319', 'n_tokens_mistral': 3500, 'n_tokens_neox': 3441, 'n_words': 566}