Imports DigitalData.Modules.EDMI.API.Client Public Class DocumentResultCache Implements ICollection(Of DocumentResultInfo) Private Const _DefaultCapacity As Long = 1000 Public Shared ReadOnly Property DefaultCapacity As Long Get Return _DefaultCapacity End Get End Property Friend ReadOnly List As New LinkedList(Of DocumentResultInfo) Private ReadOnly Index As New Dictionary(Of String, LinkedListNode(Of DocumentResultInfo)) Private ReadOnly Lock As New Object Public Sub New() Me.New(_DefaultCapacity) End Sub Public Sub New(capacity As Long) If capacity < 0 Then Throw New InvalidOperationException("DocumentResultCache capacity must be positive.") End If Me.Capacity = capacity End Sub Public Event DiscardingOldestItem As EventHandler Public Property Capacity As Long Public Property Count As Integer Implements ICollection(Of DocumentResultInfo).Count Public ReadOnly Property Oldest As DocumentResultInfo Get Return List.First.Value End Get End Property Public Sub Add(item As DocumentResultInfo) Implements ICollection(Of DocumentResultInfo).Add SyncLock Lock If Index.ContainsKey(item.FullPath) Then List.Remove(Index(item.FullPath)) Index(item.FullPath) = List.AddLast(item) Return End If If Count >= Capacity AndAlso Capacity <> 0 Then RaiseEvent DiscardingOldestItem(Me, New EventArgs()) Remove(Oldest) End If Index.Add(item.FullPath, List.AddLast(item)) If item.Contents IsNot Nothing Then Count = Count + item.Contents?.Length End If End SyncLock End Sub Public Function Contains(item As DocumentResultInfo) As Boolean Implements ICollection(Of DocumentResultInfo).Contains Return Index.ContainsKey(item.FullPath) End Function Public Sub CopyTo(array As DocumentResultInfo(), ByVal arrayIndex As Integer) Implements ICollection(Of DocumentResultInfo).CopyTo SyncLock Lock For Each item As DocumentResultInfo In Me array(Math.Min(System.Threading.Interlocked.Increment(arrayIndex), arrayIndex - 1)) = item Next End SyncLock End Sub Public Sub Clear() Implements ICollection(Of DocumentResultInfo).Clear SyncLock Lock List.Clear() Index.Clear() End SyncLock End Sub Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of DocumentResultInfo).IsReadOnly Get Return False End Get End Property Public Function Remove(item As DocumentResultInfo) As Boolean Implements ICollection(Of DocumentResultInfo).Remove SyncLock Lock If Index.ContainsKey(item.FullPath) Then List.Remove(Index(item.FullPath)) Index.Remove(item.FullPath) If item.Contents IsNot Nothing Then Count -= item.Contents.Length End If Return True End If Return False End SyncLock End Function Private Iterator Function GetEnumerator() As IEnumerator(Of DocumentResultInfo) Implements ICollection(Of DocumentResultInfo).GetEnumerator Dim node As LinkedListNode(Of DocumentResultInfo) = List.First While node IsNot Nothing Yield node.Value node = node.[Next] End While End Function Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return DirectCast(List, IEnumerable).GetEnumerator() End Function End Class