<commit_before>#pragma once
#include "AutowirableSlot.h"
#include "Decompose.h"
#include "GlobalCoreContext.h"
#include MEMORY_HEADER
#include ATOMIC_HEADER

template<class T>
class Autowired;
class CoreContext;
class GlobalCoreContext;

/// <summary>
/// Provides a simple way to obtain a reference to the current context
/// </summary>
/// <remarks>
/// Users of this class are encouraged not to hold references for longer than needed.  Failing
/// to release a context pointer could prevent resources from being correctly released.
/// </remarks>
class AutoCurrentContext:
  public std::shared_ptr<CoreContext>
{
public:
  AutoCurrentContext(void);
};

/// <summary>
/// Simple way to obtain a reference to the global context
/// </summary>
class AutoGlobalContext:
  public std::shared_ptr<GlobalCoreContext>
{
public:
  AutoGlobalContext(void);
};

/// <summary>
/// Provides a simple way to create a dependent context pointer
/// </summary>
/// <remarks>
/// The newly created context will be created using CoreContext::CurrentContext()->Create().
/// </remarks>
template<typename T>
class AutoCreateContextT:
  public std::shared_ptr<CoreContext>
{
public:
  AutoCreateContextT(void):
    std::shared_ptr<CoreContext>(CoreContext::CurrentContext()->Create<T>())
  {}
  AutoCreateContextT(std::shared_ptr<CoreContext>& ctxt):
    std::shared_ptr<CoreContext>(ctxt->Create<T>())
  {}
};

typedef AutoCreateContextT<void> AutoCreateContext;


/// <summary>
/// Idiom to enable boltable classes
/// </summary>
template<class T>
class AutoEnable
{
public:
  AutoEnable(void) { CoreContext::CurrentContext()->Enable<T>(); }
};

/// <summary>
/// An autowired template class that forms the foundation of the context consumer system
/// </summary>
/// <param name="T">The class whose type is to be found.  Must be an EXACT match.</param>
/// <remarks>
/// The autowired class offers a quick way to import or create an instance of a specified
/// class in the local context.
///
/// This class may be safely used even when the member in question is an abstract type.
/// </remarks>
template<class T>
class Autowired:
  public AutowirableSlot<T>
{
public:
  // !!!!! READ THIS IF YOU ARE GETTING A COMPILER ERROR HERE !!!!!
  // If you are getting an error tracked to this line, ensure that class T is totally
  // defined at the point where the Autowired instance is constructed.  Generally,
  // such errors are tracked to missing header files.  A common mistake, for instance,
  // is to do something like this:
  //
  // class MyClass;
  //
  // struct MyStructure {
  //   Autowired<MyClass> m_member;
  // };
  //
  // At the time m_member is instantiated, MyClass is an incomplete type.  So, when the
  // compiler tries to instantiate AutowiredCreator::Create (the function you're in right
  // now!) it finds that it can't create a new instance of type MyClass because it has
  // no idea how to construct it!
  //
  // This problem can be fixed two ways:  You can include the definition of MyClass before
  // MyStructure is defined, OR, you can give MyStructure a nontrivial constructor, and
  // then ensure that the definition of MyClass is available before the nontrivial
  // constructor is defined.
  //
  // !!!!! READ THIS IF YOU ARE GETTING A COMPILER ERROR HERE !!!!!

  Autowired(const std::shared_ptr<CoreContext>& ctxt = CoreContext::CurrentContext()) :
    AutowirableSlot<T>(ctxt->template ResolveAnchor<T>()),
    m_pFirstChild(nullptr)
  {
    ctxt->Autowire(*this);
  }

  ~Autowired(void) {
    if(m_pFirstChild == this)
      // Tombstoned, nothing to do:
      return;

    // Need to ensure that nobody tries to autowire us while we are tearing down:
    this->CancelAutowiring();

    // And now we destroy our deferrable autowiring collection:
    std::unique_ptr<DeferrableAutowiring> prior;
    for(DeferrableAutowiring* cur = m_pFirstChild; cur; cur = cur->GetFlink())
      prior.reset(cur);
  }

private:
  // The first deferred child known to need registration.  This is distinct from the m_pFlink entry in
  // the base class, which refers to the _next sibling_; by contrast, this type refers to the _first child_
  // which will be the first member registered via NotifyWhenAutowired.
  std::atomic<AutowirableSlot<T>*> m_pFirstChild;

public:
  operator T*(void) const {
    return std::shared_ptr<T>::get();
  }

  operator bool(void) const {
    return (AutowirableSlot<T>&) *this;
  }

  /// <summary>
  /// Allows a lambda function to be called when this slot is autowired
  /// </summary>
  /// <remarks>
  /// In contrast with CoreContext::NotifyWhenAutowired, the specified lambda will only be
  /// called as long as this Autowired slot has not been destroyed.  If this slot is destroyed
  /// beforehand, the lambda will never be invoked.
  /// </remarks>
  template<class Fn>
  void NotifyWhenAutowired(Fn fn) {
    // Trivial initial check:
    if(*this) {
      fn();
      return;
    }

    // We pass a null shared_ptr, because we do not want this slot to attempt any kind of unregistration when
    // it goes out of scope.  Instead, we will manage its entire registration lifecycle, and
    // retain full ownership over the object until we need to destroy it.
    auto newHead = new AutowirableSlotFn<T, Fn>(std::shared_ptr<CoreContext>(), std::forward<Fn>(fn));

    // Append to our list in a lock-free way.  This is a fairly standard way to do a lock-free append to
    // a singly linked list; the only unusual aspect is the use of "this" as a tombstone indicator (IE,
    // to signify that the list should no longer be used).
    AutowirableSlot<T>* pFirstChild;
    do {
      // Obtain the current first child, and keep it here so we know what to exchange out with later:
      pFirstChild = m_pFirstChild;

      // Determine if we've been tombstoned at this piont:
      if(pFirstChild == this) {
        // Trivially satisfy, and then return.  This might look like a leak, but it's not, because we know
        // that Finalize is going to destroy the object.
        newHead->SatisfyAutowiring((shared_ptr<T>*)this);
        newHead->Finalize();
        return;
      }
      
      // Try to set the forward link to the current head, and then update our own flink;
      newHead->SetFlink(pFirstChild);
    } while(!m_pFirstChild.compare_exchange_weak(pFirstChild, newHead, std::memory_order_acquire));
  }

  // Base overrides:
  DeferrableAutowiring* ReleaseDependentChain(void) override {
    // Rip the head off the list, replace it with a tombstone:
    auto pFirstChild = m_pFirstChild.exchange(this, std::memory_order_relaxed);

    // If we got the tombstone back, we have nothing to return.  Otherwise return the element.
    return pFirstChild == this ? nullptr : pFirstChild;
  }
};

/// <summary>
/// Similar to Autowired, but doesn't defer creation if types doesn't already exist
/// </summary><commit_msg>Missed a spot<commit_after>#pragma once
#include "AutowirableSlot.h"
#include "Decompose.h"
#include "GlobalCoreContext.h"
#include MEMORY_HEADER
#include ATOMIC_HEADER

template<class T>
class Autowired;
class CoreContext;
class GlobalCoreContext;

/// <summary>
/// Provides a simple way to obtain a reference to the current context
/// </summary>
/// <remarks>
/// Users of this class are encouraged not to hold references for longer than needed.  Failing
/// to release a context pointer could prevent resources from being correctly released.
/// </remarks>
class AutoCurrentContext:
  public std::shared_ptr<CoreContext>
{
public:
  AutoCurrentContext(void);
};

/// <summary>
/// Simple way to obtain a reference to the global context
/// </summary>
class AutoGlobalContext:
  public std::shared_ptr<GlobalCoreContext>
{
public:
  AutoGlobalContext(void);
};

/// <summary>
/// Provides a simple way to create a dependent context pointer
/// </summary>
/// <remarks>
/// The newly created context will be created using CoreContext::CurrentContext()->Create().
/// </remarks>
template<typename T>
class AutoCreateContextT:
  public std::shared_ptr<CoreContext>
{
public:
  AutoCreateContextT(void):
    std::shared_ptr<CoreContext>(CoreContext::CurrentContext()->Create<T>())
  {}
  AutoCreateContextT(std::shared_ptr<CoreContext>& ctxt):
    std::shared_ptr<CoreContext>(ctxt->Create<T>())
  {}
};

typedef AutoCreateContextT<void> AutoCreateContext;


/// <summary>
/// Idiom to enable boltable classes
/// </summary>
template<class T>
class AutoEnable
{
public:
  AutoEnable(void) { CoreContext::CurrentContext()->Enable<T>(); }
};

/// <summary>
/// An autowired template class that forms the foundation of the context consumer system
/// </summary>
/// <param name="T">The class whose type is to be found.  Must be an EXACT match.</param>
/// <remarks>
/// The autowired class offers a quick way to import or create an instance of a specified
/// class in the local context.
///
/// This class may be safely used even when the member in question is an abstract type.
/// </remarks>
template<class T>
class Autowired:
  public AutowirableSlot<T>
{
public:
  // !!!!! READ THIS IF YOU ARE GETTING A COMPILER ERROR HERE !!!!!
  // If you are getting an error tracked to this line, ensure that class T is totally
  // defined at the point where the Autowired instance is constructed.  Generally,
  // such errors are tracked to missing header files.  A common mistake, for instance,
  // is to do something like this:
  //
  // class MyClass;
  //
  // struct MyStructure {
  //   Autowired<MyClass> m_member;
  // };
  //
  // At the time m_member is instantiated, MyClass is an incomplete type.  So, when the
  // compiler tries to instantiate AutowiredCreator::Create (the function you're in right
  // now!) it finds that it can't create a new instance of type MyClass because it has
  // no idea how to construct it!
  //
  // This problem can be fixed two ways:  You can include the definition of MyClass before
  // MyStructure is defined, OR, you can give MyStructure a nontrivial constructor, and
  // then ensure that the definition of MyClass is available before the nontrivial
  // constructor is defined.
  //
  // !!!!! READ THIS IF YOU ARE GETTING A COMPILER ERROR HERE !!!!!

  Autowired(const std::shared_ptr<CoreContext>& ctxt = CoreContext::CurrentContext()) :
    AutowirableSlot<T>(ctxt->template ResolveAnchor<T>()),
    m_pFirstChild(nullptr)
  {
    ctxt->Autowire(*this);
  }

  ~Autowired(void) {
    if(m_pFirstChild == this)
      // Tombstoned, nothing to do:
      return;

    // Need to ensure that nobody tries to autowire us while we are tearing down:
    this->CancelAutowiring();

    // And now we destroy our deferrable autowiring collection:
    std::unique_ptr<DeferrableAutowiring> prior;
    for(DeferrableAutowiring* cur = m_pFirstChild; cur; cur = cur->GetFlink())
      prior.reset(cur);
  }

private:
  // The first deferred child known to need registration.  This is distinct from the m_pFlink entry in
  // the base class, which refers to the _next sibling_; by contrast, this type refers to the _first child_
  // which will be the first member registered via NotifyWhenAutowired.
  std::atomic<AutowirableSlot<T>*> m_pFirstChild;

public:
  operator T*(void) const {
    return std::shared_ptr<T>::get();
  }

  operator bool(void) const {
    return (AutowirableSlot<T>&) *this;
  }

  /// <summary>
  /// Allows a lambda function to be called when this slot is autowired
  /// </summary>
  /// <remarks>
  /// In contrast with CoreContext::NotifyWhenAutowired, the specified lambda will only be
  /// called as long as this Autowired slot has not been destroyed.  If this slot is destroyed
  /// beforehand, the lambda will never be invoked.
  /// </remarks>
  template<class Fn>
  void NotifyWhenAutowired(Fn fn) {
    // Trivial initial check:
    if(*this) {
      fn();
      return;
    }

    // We pass a null shared_ptr, because we do not want this slot to attempt any kind of unregistration when
    // it goes out of scope.  Instead, we will manage its entire registration lifecycle, and
    // retain full ownership over the object until we need to destroy it.
    auto newHead = new AutowirableSlotFn<T, Fn>(std::shared_ptr<CoreContext>(), std::forward<Fn>(fn));

    // Append to our list in a lock-free way.  This is a fairly standard way to do a lock-free append to
    // a singly linked list; the only unusual aspect is the use of "this" as a tombstone indicator (IE,
    // to signify that the list should no longer be used).
    AutowirableSlot<T>* pFirstChild;
    do {
      // Obtain the current first child, and keep it here so we know what to exchange out with later:
      pFirstChild = m_pFirstChild;

      // Determine if we've been tombstoned at this piont:
      if(pFirstChild == this) {
        // Trivially satisfy, and then return.  This might look like a leak, but it's not, because we know
        // that Finalize is going to destroy the object.
        newHead->SatisfyAutowiring((std::shared_ptr<T>*)this);
        newHead->Finalize();
        return;
      }
      
      // Try to set the forward link to the current head, and then update our own flink;
      newHead->SetFlink(pFirstChild);
    } while(!m_pFirstChild.compare_exchange_weak(pFirstChild, newHead, std::memory_order_acquire));
  }

  // Base overrides:
  DeferrableAutowiring* ReleaseDependentChain(void) override {
    // Rip the head off the list, replace it with a tombstone:
    auto pFirstChild = m_pFirstChild.exchange(this, std::memory_order_relaxed);

    // If we got the tombstone back, we have nothing to return.  Otherwise return the element.
    return pFirstChild == this ? nullptr : pFirstChild;
  }
};

/// <summary>
/// Similar to Autowired, but doesn't defer creation if types doesn't already exist
/// </summary>
{'fraction_non_alphanumeric': 0.10533188248095757, 'fraction_numerical': 0.0, 'mean_word_length': 3.3974481658692186, 'pattern_counts': {'":': 0, '<': 111, '<?xml version=': 0, '>': 133, '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': '853446', 'n_tokens_mistral': 3997, 'n_tokens_neox': 3958, 'n_words': 1549}