<commit_before>/*
  Crystal Space Shared Class Facility (SCF)
  This header contains the parts of SCF that is needed when creating
  new classes which implements SCF interfaces.

  Copyright (C) 2005 by <NAME>
            (C) 2005 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 __CSUTIL_SCF_IMPLEMENTATION_H__
#define __CSUTIL_SCF_IMPLEMENTATION_H__

#include "csextern.h"

#include "csutil/array.h"
#include "csutil/customallocated.h"
#include "csutil/ref.h"
#include "csutil/reftrackeraccess.h"
#include "csutil/threading/atomicops.h"
#include "csutil/threading/mutex.h"
#include "csutil/weakreferenced.h"

// Needs to have iBase etc
#include "csutil/scf_interface.h"

// Control if we want to use preprocessed file or run generation each time
#define SCF_IMPLGEN_PREPROCESSED
// Track some simple SCF-related stats
//#define SCF_TRACK_STATS

#ifndef CS_TYPENAME
  #ifdef CS_REF_TRACKER
   #include <typeinfo>
   #define CS_TYPENAME(x)		    typeid(x).name()
  #else
   #define CS_TYPENAME(x)		    0
  #endif
#endif

/**\file
 * Crystal Space Shared Class Facility (SCF) - implementation creation 
 * support.
 */

/**
 * \addtogroup scf
 * @{ */
 
/**\page SCFExamples Some examples
 * \code
 * struct iFoo : virtual public iBase {
 *   SCF_INTERFACE(iFoo,0,0,1);
 * };
 * 
 * struct iBar : virtual public iBase {
 *   SCF_INTERFACE(iFoo,0,0,1);
 * };
 * 
 * class Foo : public scfImplementation1<Foo,iFoo>
 * {
 * public:
 *   Foo() : scfImplementationType(this) {}
 *   Foo(int, int) : scfImplementationType(0,0) {}
 * };
 * 
 * class Bar : public scfImplementationExt1<Bar,Foo,iBar>
 * {
 * public:
 *   Bar() : scfImplementationType(0) {}
 *   Bar(int x, int y) : scfImplementationType(0,x,y) {}
 * };
 * \endcode
*/


/**
* Fugly helper to resolve some bad situations. ;)
* Basically, it adds a new entry to QueryInterface() without adding another 
* class to inheritance.
*
* Consider the following case:
*
* \code
* struct iA : public virtual iBase {};
* struct iB : public iA {};
*
* class myB : public scfImplementation1<myB, iB> {..}.
* \endcode
*
* Querying iA from myB will then fail even though myB inherits from iA
* (through iB). By changing the declaration to
*
* \code
* class myB : public scfImplementation2<myB, iB, scfFakeInterface<iA> > {..}
* \endcode
*
* you make sure you can query iA from myB.
* \warning This is potentially dangerous as you can add whatever interface
* to another. USE WITH CARE!
*/
template<class If>
class scfFakeInterface
{
public:
  struct InterfaceTraits 
  {
    typedef If InterfaceType;
    CS_FORCEINLINE_TEMPLATEMETHOD 
    static scfInterfaceVersion GetVersion()
    { return If::InterfaceTraits::GetVersion(); }
    CS_FORCEINLINE_TEMPLATEMETHOD static char const * GetName() 
    { return If::InterfaceTraits::GetName(); }
  };
};

/// Various helpers for scfImplementation
class CS_CRYSTALSPACE_EXPORT scfImplementationHelper
{
protected:
  enum
  {
    scfstatTotal,
    scfstatParented,
    scfstatWeakreffed,
    scfstatMetadata,
    scfstatIncRef,
    scfstatDecRef,

    scfstatsNum
  };
  static uint64 stats[scfstatsNum];
  static CS::Threading::Mutex statsLock;

  CS_FORCEINLINE void BumpStat (int stat)
  {
#ifdef SCF_TRACK_STATS
    CS::Threading::ScopedLock<CS::Threading::Mutex> l (statsLock);
    stats[stat]++;
#endif
  }

  struct ScfImplAuxData : public CS::Memory::CustomAllocated,
			  public CS::Utility::AtomicRefCount,
			  public CS::Utility::Implementation::WeakReferenced
  {
    CS::Threading::Mutex lock;
    iBase *scfParent;
    scfInterfaceMetadataList* metadataList;

    ScfImplAuxData () : scfParent (0), metadataList (0) {}
    
    bool HasWeakRefOwners() const { return weakref_owners != nullptr; }
  };
  ScfImplAuxData* scfAuxData;

  CS_FORCEINLINE bool HasAuxData()
  {
    // Double-cast to cheat strict-aliasing rules
    return CS::Threading::AtomicOperations::Read ((void**)(void*)&scfAuxData) != 0; 
  }
  void EnsureAuxData();
  void FreeAuxData();

  //-- Metadata handling
  void AllocMetadata (size_t numEntries);
  void CleanupMetadata ();

  iBase* GetSCFParent() { return HasAuxData() ? scfAuxData->scfParent : 0; }

  // Some virtual helpers for the metadata registry
  virtual size_t GetInterfaceMetadataCount () const;

  scfImplementationHelper() : scfAuxData (0) {}
  virtual ~scfImplementationHelper() { if (HasAuxData()) FreeAuxData(); }
};

/**
 * Baseclass for the SCF implementation templates.
 * Provides common methods such as reference counting and handling of<commit_msg>Compile fix.<commit_after>/*
  Crystal Space Shared Class Facility (SCF)
  This header contains the parts of SCF that is needed when creating
  new classes which implements SCF interfaces.

  Copyright (C) 2005 by <NAME>
            (C) 2005 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 __CSUTIL_SCF_IMPLEMENTATION_H__
#define __CSUTIL_SCF_IMPLEMENTATION_H__

#include "csextern.h"

#include "csutil/array.h"
#include "csutil/customallocated.h"
#include "csutil/ref.h"
#include "csutil/reftrackeraccess.h"
#include "csutil/threading/atomicops.h"
#include "csutil/threading/mutex.h"
#include "csutil/weakreferenced.h"

// Needs to have iBase etc
#include "csutil/scf_interface.h"

// Control if we want to use preprocessed file or run generation each time
#define SCF_IMPLGEN_PREPROCESSED
// Track some simple SCF-related stats
//#define SCF_TRACK_STATS

#ifndef CS_TYPENAME
  #ifdef CS_REF_TRACKER
   #include <typeinfo>
   #define CS_TYPENAME(x)		    typeid(x).name()
  #else
   #define CS_TYPENAME(x)		    0
  #endif
#endif

/**\file
 * Crystal Space Shared Class Facility (SCF) - implementation creation 
 * support.
 */

/**
 * \addtogroup scf
 * @{ */
 
/**\page SCFExamples Some examples
 * \code
 * struct iFoo : virtual public iBase {
 *   SCF_INTERFACE(iFoo,0,0,1);
 * };
 * 
 * struct iBar : virtual public iBase {
 *   SCF_INTERFACE(iFoo,0,0,1);
 * };
 * 
 * class Foo : public scfImplementation1<Foo,iFoo>
 * {
 * public:
 *   Foo() : scfImplementationType(this) {}
 *   Foo(int, int) : scfImplementationType(0,0) {}
 * };
 * 
 * class Bar : public scfImplementationExt1<Bar,Foo,iBar>
 * {
 * public:
 *   Bar() : scfImplementationType(0) {}
 *   Bar(int x, int y) : scfImplementationType(0,x,y) {}
 * };
 * \endcode
*/


/**
* Fugly helper to resolve some bad situations. ;)
* Basically, it adds a new entry to QueryInterface() without adding another 
* class to inheritance.
*
* Consider the following case:
*
* \code
* struct iA : public virtual iBase {};
* struct iB : public iA {};
*
* class myB : public scfImplementation1<myB, iB> {..}.
* \endcode
*
* Querying iA from myB will then fail even though myB inherits from iA
* (through iB). By changing the declaration to
*
* \code
* class myB : public scfImplementation2<myB, iB, scfFakeInterface<iA> > {..}
* \endcode
*
* you make sure you can query iA from myB.
* \warning This is potentially dangerous as you can add whatever interface
* to another. USE WITH CARE!
*/
template<class If>
class scfFakeInterface
{
public:
  struct InterfaceTraits 
  {
    typedef If InterfaceType;
    CS_FORCEINLINE_TEMPLATEMETHOD 
    static scfInterfaceVersion GetVersion()
    { return If::InterfaceTraits::GetVersion(); }
    CS_FORCEINLINE_TEMPLATEMETHOD static char const * GetName() 
    { return If::InterfaceTraits::GetName(); }
  };
};

/// Various helpers for scfImplementation
class CS_CRYSTALSPACE_EXPORT scfImplementationHelper
{
protected:
  enum
  {
    scfstatTotal,
    scfstatParented,
    scfstatWeakreffed,
    scfstatMetadata,
    scfstatIncRef,
    scfstatDecRef,

    scfstatsNum
  };
  static uint64 stats[scfstatsNum];
  static CS::Threading::Mutex statsLock;

  CS_FORCEINLINE void BumpStat (int stat)
  {
#ifdef SCF_TRACK_STATS
    CS::Threading::ScopedLock<CS::Threading::Mutex> l (statsLock);
    stats[stat]++;
#endif
  }

  struct ScfImplAuxData : public CS::Memory::CustomAllocated,
			  public CS::Utility::AtomicRefCount,
			  public CS::Utility::Implementation::WeakReferenced
  {
    CS::Threading::Mutex lock;
    iBase *scfParent;
    scfInterfaceMetadataList* metadataList;

    ScfImplAuxData () : scfParent (0), metadataList (0) {}
    
    bool HasWeakRefOwners() const { return weakref_owners != 0; }
  };
  ScfImplAuxData* scfAuxData;

  CS_FORCEINLINE bool HasAuxData()
  {
    // Double-cast to cheat strict-aliasing rules
    return CS::Threading::AtomicOperations::Read ((void**)(void*)&scfAuxData) != 0; 
  }
  void EnsureAuxData();
  void FreeAuxData();

  //-- Metadata handling
  void AllocMetadata (size_t numEntries);
  void CleanupMetadata ();

  iBase* GetSCFParent() { return HasAuxData() ? scfAuxData->scfParent : 0; }

  // Some virtual helpers for the metadata registry
  virtual size_t GetInterfaceMetadataCount () const;

  scfImplementationHelper() : scfAuxData (0) {}
  virtual ~scfImplementationHelper() { if (HasAuxData()) FreeAuxData(); }
};

/**
 * Baseclass for the SCF implementation templates.
 * Provides common methods such as reference counting and handling of
{'fraction_non_alphanumeric': 0.10213547202628273, 'fraction_numerical': 0.007633587786259542, 'mean_word_length': 4.012106537530267, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, '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': '3380253', 'n_tokens_mistral': 3500, 'n_tokens_neox': 3357, 'n_words': 1014}