Design of a weak reference set of .NET available (can be used for buffer pool usage)

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/WPwalter/article/details/102634869

We have weak references WeakReference<T>can be used to hold an object can be recycled garbage, but also can save the key-value pairs ConditionalWeakTable.

We often consider creating a buffer pool. Although such a design is generally not recommended, but you can use the code in this article and as a design by garbage collection buffer pool cache.


Design ideas

Since the existing WeakReference<T>and ConditionalWeakTablecan help us achieve a weak reference, then we can consider either or both of these two classes to help us complete package weak reference collection.

ConditionalWeakTableJust type internallevel have access to all of the elements in the collection, opening up an interface which is unable to get all the elements in the collection, just to be able to find it based on Value Key. So if you want according ConditionalWeakTableto implement a weak reference collection of records you need to own all of Key set, and so we still need to implement a weak reference to record all Key collection is equivalent to the problem of the chicken egg.

Therefore, we consider the direct use WeakReference<T>to implement a weak reference collection.

Maintain a list of their own List<WeakReference<T>>, opening up the API only access to which is not subject to garbage collection.

Design Principles

In the design of this type, there is a very big factor to consider is the number of elements of this type is uncertain, if poorly designed, so every line of code to write this type of users are likely Bug .

You can refer to my other blog for a design of this type of uncertainty when the API's some guidance:

Summed up:

  • Must provide a single method, can be completed at a time to get some typical scenarios deterministic state
  • Never provide some methods may be called multiple times to obtain the status of

So how this principle is reflected in the weak reference to the collection of this type of design?

Design Practice

Analysis stepped pit

IList<T>

We look at IList<T>whether the interface is feasible:

public class WeakCollection<T> : IList<T> where T : class
{
    public T this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    public int Count => throw new NotImplementedException();
    public bool IsReadOnly => throw new NotImplementedException();
    public void Add(T item) => throw new NotImplementedException();
    public void Clear() => throw new NotImplementedException();
    public bool Contains(T item) => throw new NotImplementedException();
    public void CopyTo(T[] array, int arrayIndex) => throw new NotImplementedException();
    public IEnumerator<T> GetEnumerator() => throw new NotImplementedException();
    public int IndexOf(T item) => throw new NotImplementedException();
    public void Insert(int index, T item) => throw new NotImplementedException();
    public bool Remove(T item) => throw new NotImplementedException();
    public void RemoveAt(int index) => throw new NotImplementedException();
    IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
}

this[], Count, IsReadOnly, Contains, CopyTo, IndexOf, GetEnumeratorThese are acquiring Addstate, Clear, , Removein the modified state, but Insert, RemoveAtreads the status at the same time modified state.

So many ways to access and modify the state, if the offer out, users can also expect normal use, simply a dream! Contrary to the above two principles.

ICollection<T>

Then we look at IList<T>a set of low-level ICollection<T>, does not actually solve the problem, it still can not be ruled out!

    public class WeakCollection<T> : ICollection<T> where T : class
    {
--      public T this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public int Count => throw new NotImplementedException();
        public bool IsReadOnly => throw new NotImplementedException();
        public void Add(T item) => throw new NotImplementedException();
        public void Clear() => throw new NotImplementedException();
        public bool Contains(T item) => throw new NotImplementedException();
        public void CopyTo(T[] array, int arrayIndex) => throw new NotImplementedException();
        public IEnumerator<T> GetEnumerator() => throw new NotImplementedException();
--      public int IndexOf(T item) => throw new NotImplementedException();
--      public void Insert(int index, T item) => throw new NotImplementedException();
        public bool Remove(T item) => throw new NotImplementedException();
--      public void RemoveAt(int index) => throw new NotImplementedException();
        IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
    }

However, Addand Removemethods we might consider to stay, but this is not inherited from ICollection<T>the.

IEnumerable<T>

IEnumerable<T> There are only two ways, seems much less, then we can use it?

public IEnumerator<T> GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

This method is for foreachuse, but would have been if so, the problem is not great, but for IEnumerator<T>there are a lot of Linq extension method, so this is equivalent to weak references to this collection provides a number of methods can be used to read status.

It is still very dangerous!

Wherein a user may at any time use the extension method in which a state has been followed by using another method that its second extended state, for example:

// 判断集合中是否存在 IFoo 类型以及是否存在 IBar 类型。
var hasFoo = weakList.OfType<IFoo>().Any();
var hasBar = weakList.OfType<IBar>().Any();

You have concurrent development experience, the above method can be identified at first glance that this is not the correct wording. However, since it has been open type out for everyone to use, then this is very dangerous. The key is that this is not a concurrency scenarios, so developers may be more difficult to feel the same call in the context of two methods to get inconclusive results. You can use locks for concurrency, but for weak references, there is no correlation method can be used to quickly solve the problem.

Therefore, IEnumerable<T>also it can not be inherited.

object

It seems we can only inherit from a simple objectbase class a. This type of hosting is not visible status, so no one would read the state of uncertainty caused by a number of states.

Therefore, we need to implement their own API under all scenarios.

Start work

We need a set of weak references these usage scenarios:

  • Weak references to add a set of elements 此场景下仅仅修改集合而不需要读取任何状态。
  • Weak references to remove a set of elements 既然可以在参数中传入元素,说明此元素一定没有会垃圾回收;因此只要集合中还存在此元素,一定可以确定地移除,不会出现不确定的状态。
  • References one or more element in the set to meet the requirements found in a weak 一旦满足要求,必须得到完全确定的结果,且在此结果保存的过程中一直生效。

Optional Consider these scenarios:

  • Clear all the elements 通常是为了复用某个缓存池的实例。

We must not allow the following methods:

  • Determine whether there is an element 因为判断是否存在通常不是单独的操作,通常会使用此集合继续下一个操作,因此一定不能直接提供。
  • Other earlier in this article have been sprayed method can not add incoming

So, our API design will look like this:

public class WeakCollection<T> where T : class
{
    public void Add(T item) => throw new NotImplementedException();
    public bool Remove(T item) => throw new NotImplementedException();
    public void Clear() => throw new NotImplementedException();
    public T[] TryGetItems(Func<T, bool> filter) => throw new NotImplementedException();
}

The complete code

This type has been released in the form of source code package to the NuGet, you can install the following packages NuGet read and use its source code:

After installation, you can use in your project, its source code, and can be used directly Ctrl + mouse click to open the way to the type of source code, without the need for decompiling.


My blog will be starting in https://blog.walterlv.com/ , and will be released from CSDN which featured, but it is rarely updated once released.

If you see any do not understand the contents of the blog, please share. I built dotnet Vocational and Technical College welcome to join.

Creative Commons License

This work is Creative Commons Attribution - NonCommercial - ShareAlike 4.0 International License Agreement for licensing. Welcome to reprint, use, repost, but be sure to keep the article signed by Lu Yi (containing links: https://walterlv.blog.csdn.net/ ), shall not be used for commercial purposes, a work based on the article be sure to modify the same license release. If you have any questions, please contact me .

Guess you like

Origin blog.csdn.net/WPwalter/article/details/102634869