Skip to content

Commit

Permalink
Removed unnecessary cache locking
Browse files Browse the repository at this point in the history
  • Loading branch information
jstedfast committed Mar 1, 2024
1 parent b46a0f7 commit d705764
Showing 1 changed file with 44 additions and 46 deletions.
90 changes: 44 additions & 46 deletions MailKit/Net/Imap/ImapTokenCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,62 +59,60 @@ public ImapTokenCache ()

public ImapToken AddOrGet (ImapTokenType type, ByteArrayBuilder builder)
{
lock (cache) {
// lookupKey is a pre-allocated key used for lookups
lookupKey.Init (decoders, chars, type, builder.GetBuffer (), builder.Length, out var decoder, out int charsNeeded);
// lookupKey is a pre-allocated key used for lookups
lookupKey.Init (decoders, chars, type, builder.GetBuffer (), builder.Length, out var decoder, out int charsNeeded);

if (cache.TryGetValue (lookupKey, out var node)) {
// move the node to the head of the list
list.Remove (node);
list.AddFirst (node);
node.Value.Count++;
if (cache.TryGetValue (lookupKey, out var node)) {
// move the node to the head of the list
list.Remove (node);
list.AddFirst (node);
node.Value.Count++;

return node.Value.Token;
}
return node.Value.Token;
}

string value;

if (charsNeeded <= chars.Length) {
// If the number of needed chars is <= the length of our temp buffer, then it should all be contained.
value = new string (chars, 0, charsNeeded);
} else {
var buffer = ArrayPool<char>.Shared.Rent (charsNeeded);
try {
// Note: This conversion should go flawlessly, so we'll just Debug.Assert() our expectations.
decoder.Convert (builder.GetBuffer (), 0, builder.Length, buffer, 0, buffer.Length, true, out var bytesUsed, out var charsUsed, out var completed);
Debug.Assert (bytesUsed == builder.Length);
Debug.Assert (charsUsed == charsNeeded);
Debug.Assert (completed);
value = new string (buffer, 0, charsUsed);
} finally {
ArrayPool<char>.Shared.Return (buffer);
decoder.Reset ();
}
string value;

if (charsNeeded <= chars.Length) {
// If the number of needed chars is <= the length of our temp buffer, then it should all be contained.
value = new string (chars, 0, charsNeeded);
} else {
var buffer = ArrayPool<char>.Shared.Rent (charsNeeded);
try {
// Note: This conversion should go flawlessly, so we'll just Debug.Assert() our expectations.
decoder.Convert (builder.GetBuffer (), 0, builder.Length, buffer, 0, buffer.Length, true, out var bytesUsed, out var charsUsed, out var completed);
Debug.Assert (bytesUsed == builder.Length);
Debug.Assert (charsUsed == charsNeeded);
Debug.Assert (completed);
value = new string (buffer, 0, charsUsed);
} finally {
ArrayPool<char>.Shared.Return (buffer);
decoder.Reset ();
}
}

var token = new ImapToken (type, value);
var token = new ImapToken (type, value);

if (cache.Count >= capacity) {
// remove the least recently used token
node = list.Last;
list.RemoveLast ();
cache.Remove (node.Value.Key);
if (cache.Count >= capacity) {
// remove the least recently used token
node = list.Last;
list.RemoveLast ();
cache.Remove (node.Value.Key);

// re-use the node, item and key to avoid allocations
node.Value.Key.Init (type, (string) token.Value);
node.Value.Token = token;
} else {
var key = new ImapTokenKey (type, (string) token.Value);
var item = new ImapTokenItem (key, token);
// re-use the node, item and key to avoid allocations
node.Value.Key.Init (type, (string) token.Value);
node.Value.Token = token;
} else {
var key = new ImapTokenKey (type, (string) token.Value);
var item = new ImapTokenItem (key, token);

node = new LinkedListNode<ImapTokenItem> (item);
}
node = new LinkedListNode<ImapTokenItem> (item);
}

cache.Add (node.Value.Key, node);
list.AddFirst (node);
cache.Add (node.Value.Key, node);
list.AddFirst (node);

return token;
}
return token;
}

class ImapTokenKey
Expand Down

0 comments on commit d705764

Please sign in to comment.