decline-cookies / anvil-unity-dots

Unity DOTS and ECS specific additions and extensions to Anvil
MIT License
4 stars 1 forks source link

WrappedAccessControlledValue - Add #239

Closed mbaker3 closed 1 year ago

mbaker3 commented 1 year ago

Provide a type to wrap and transform another ACV in an ACV compatible format.

What is the current behaviour?

If you'd like to expose a variant of an access controlled value it involves implementing a new type that implements at least one of the access controlled value interfaces. Most of this type is generic boilerplate with only the logic transforming the base type to the variant being unique.

What is the new behaviour?

WrappedAccessControlledValue and WrappedReadAccessControlledValue provide generic implementations that allow the developer to pass in the base ACV and a delegate that transforms the type from the base to desired type.

Example

Common
private readonly AccessControlledValue<Dictionary<string, int>> m_MyLookup = new AccessControlledValue<Dictionary<string, int>>(new Dictionary<string, int>());

public readonly struct LookupPresenceReader
{
   private Dictionary<string, int> m_Lookup;

   public bool IsPresent(string key)
      => m_Lookup.Contains(key);

   public LookupPresenceReader(Dictionary<string, int> lookup)
   {
      m_Lookup = lookup;
   }
}
Old
public IReadAccessControlledValue<LookupPresenceReader> IsInLookup { get; } 
   = new PresenceLookup(m_MyLookup);

private class PresenceLookup : AbstractAnvilBase, IReadAccessControlledValue<LookupPresenceReader>
{
   private readonly IReadAccessControlledValue<Dictionary<string, int>> m_Lookup;

    public PresenceLookup(IReadAccessControlledValue<Dictionary<string, int>> lookup)
    {
        m_Lookup = lookup;
    }

    public AccessControlledValue<LookupPresenceReader>.AccessHandle AcquireWithReadHandle()
    {
        var handle = m_Lookup.AcquireWithReadHandle();
        LookupPresenceReader reader = new LookupPresenceReader(handle.Value);

        return AccessControlledValue<LookupPresenceReader>.AccessHandle.CreateDerived(handle, reader);
    }

    public LookupPresenceReader AcquireRead()
    {
        return new LookupPresenceReader(m_Lookup.AcquireRead());
    }

    public JobHandle AcquireReadAsync(out LookupPresenceReader value)
    {
        JobHandle handle = m_Lookup.AcquireReadAsync(out var lookup);
        value = new LookupPresenceReader(lookup);
        return handle;
    }

    public void Release()
    {
        m_Lookup.Release();
    }

    public void ReleaseAsync(JobHandle releaseAccessDependency)
    {
        m_Lookup.ReleaseAsync(releaseAccessDependency);
    }
}
NEW - With wrapped ACV
public IReadAccessControlledValue<LookupPresenceReader> IsInLookup { get; } 
   = new WrappedReadAccessControlledValue<LookupPresenceReader, Dictionary<string, int>>(m_MyLookup);

What issues does this resolve?

What PRs does this depend on?

Does this introduce a breaking change?