<commit_before>/*
    Copyright (C) 2006 by <NAME>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __CS_CSUTIL_COWWRAPPER_H__
#define __CS_CSUTIL_COWWRAPPER_H__

#include "csutil/custom_new_disable.h"

#include "csutil/allocator.h"

/**\file
 * Copy-on-write wrapper for arbitrary types.
 */

namespace CS
{

  /**
   * Copy-on-write wrapper for arbitrary types.
   * <pre>
   *  _________________________________________
   * / Instances transparently maintain a      \
   * | reference-counted pointer to the actual |
   * | data; if an instance is copied, merely  |
   * | this pointer is copied.                 |
   * |                                         |
   * | As long as all access to the data is    |
   * | constant, the data is shared between    |
   * | instances. Only if non-const access is  |
   * | requested the data is duplicated.       |
   * |                                         |
   * \ The wrapper itself acts like a pointer. /
   *  -----------------------------------------
   *         \   ^__^
   *          \  (oo)\\_______
   *             (__)\       )\/\
   *                 ||----w |
   *                 ||     ||
   * </pre>
   *
   * \remarks Contained types must have a proper copy constructor.
   * \remarks Care should be taken that the data is accessed with proper 
   *   const-ness, since only the then data can be shared. Otherwise, data
   *   may be duplicated needlessly.
   */
  template<typename T, class MemoryAllocator = Memory::AllocatorMalloc>
  class CowWrapper
  {
    /// Helper class wrapping the actual data
    struct WrappedData
    {
      int refcount;
  
      void IncRef () { refcount++; }
      void DecRef () 
      { 
	refcount--; 
        if (refcount == 0) 
        {
          this->~WrappedData();
          MemoryAllocator::Free (this);
        }
      }
      int GetRefCount () const { return refcount; }
      
      T data;
    public:
      WrappedData (const T& other) : refcount (1), data (other) {}
      WrappedData (const WrappedData& other) : refcount (1), data (other.data) {}
    };
  public:
    static const size_t allocSize = sizeof (WrappedData);
  private:
    csRef<WrappedData> data;
    inline WrappedData* NewData (const T& other)
    {
      WrappedData* p = (WrappedData*)MemoryAllocator::Alloc (allocSize);
      new (p) WrappedData (other);
      return p;
    }
  public:
    /// Copy reference to data from \p other.
    CowWrapper (const CowWrapper& other) : data (other.data) {}
    /// Create a new wrapper and initialize with \p other.
    CowWrapper (const T& other)
    {
      data.AttachNew (NewData (other));<commit_msg>Doc tweak<commit_after>/*
    Copyright (C) 2006 by <NAME>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __CS_CSUTIL_COWWRAPPER_H__
#define __CS_CSUTIL_COWWRAPPER_H__

#include "csutil/custom_new_disable.h"

#include "csutil/allocator.h"

/**\file
 * Copy-on-write wrapper for arbitrary types.
 */

namespace CS
{

  /**
   * Copy-on-write wrapper for arbitrary types.
   * <pre>
   *  _________________________________________
   * / Instances transparently maintain a      \
   * | reference-counted pointer to the actual |
   * | data; if an instance is copied, merely  |
   * | this pointer is copied.                 |
   * |                                         |
   * | As long as all access to the data is    |
   * | constant, the data is shared between    |
   * | instances. Only if non-const access is  |
   * | requested the data is duplicated.       |
   * |                                         |
   * \ The wrapper itself acts like a pointer. /
   *  -----------------------------------------
   *         \   ^__^
   *          \  (oo)\\_______
   *             (__)\       )\/\
   *                 ||----w |
   *                 ||     ||
   * </pre>
   *
   * \remarks Contained types must have a proper copy constructor.
   * \remarks Care should be taken that the data is accessed with proper 
   *   const-ness, since only the then data can be shared. Otherwise, data
   *   may be duplicated needlessly.
   */
  template<typename T, class MemoryAllocator = Memory::AllocatorMalloc>
  class CowWrapper
  {
    /// Helper class wrapping the actual data
    struct WrappedData
    {
      int refcount;
  
      void IncRef () { refcount++; }
      void DecRef () 
      { 
	refcount--; 
        if (refcount == 0) 
        {
          this->~WrappedData();
          MemoryAllocator::Free (this);
        }
      }
      int GetRefCount () const { return refcount; }
      
      T data;
    public:
      WrappedData (const T& other) : refcount (1), data (other) {}
      WrappedData (const WrappedData& other) : refcount (1), data (other.data) {}
    };
  public:
    /**
     * This is the size of the memory block the wrapper internally uses to
     * store the actual data. It is published to make fixed-size allocators
     * possible.
     */
    static const size_t allocSize = sizeof (WrappedData);
  private:
    csRef<WrappedData> data;
    inline WrappedData* NewData (const T& other)
    {
      WrappedData* p = (WrappedData*)MemoryAllocator::Alloc (allocSize);
      new (p) WrappedData (other);
      return p;
    }
  public:
    /// Copy reference to data from \p other.
    CowWrapper (const CowWrapper& other) : data (other.data) {}
    /// Create a new wrapper and initialize with \p other.
    CowWrapper (const T& other)
    {
      data.AttachNew (NewData (other));
{'fraction_non_alphanumeric': 0.0995032144944477, 'fraction_numerical': 0.004675628287551139, 'mean_word_length': 2.038171327119396, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4596695', 'n_tokens_mistral': 1923, 'n_tokens_neox': 1880, 'n_words': 711}