/// <summary>
            /// Version of Intern that gathers statistics
            /// </summary>
            private string InternWithStatistics(IInternable candidate)
            {
                string result;

                _stopwatch.Start();
                bool?interned = TryIntern(candidate, out result);

                _stopwatch.Stop();

                if (interned.HasValue && !interned.Value)
                {
                    // Could not intern.
                    _internMisses++;

                    int priorCount = 0;
                    _missedStrings.TryGetValue(result, out priorCount);
                    _missedStrings[result] = priorCount + 1;

                    return(result);
                }
                else if (interned == null)
                {
                    // Decided not to attempt interning
                    _internRejects++;

                    int priorCount = 0;
                    _rejectedStrings.TryGetValue(result, out priorCount);
                    _rejectedStrings[result] = priorCount + 1;

                    return(result);
                }

                _internHits++;
                if (!candidate.ReferenceEquals(result))
                {
                    // Reference changed so 'candidate' is now released and should save memory.
                    _internEliminatedStrings++;
                    _internEliminatedChars += candidate.Length;
                }

                return(result);
            }
Example #2
0
                /// <summary>
                /// Try to get one element from the list. Upon leaving the function 'candidate' will be at the head of the Mru list.
                /// This function is not thread-safe.
                /// </summary>
                internal bool TryGet(IInternable candidate, out string interned)
                {
                    if (_size == 0)
                    {
                        interned = candidate.ExpensiveConvertToString();
                        return(false);
                    }

                    int  length      = candidate.Length;
                    Node secondPrior = null;
                    Node prior       = null;
                    Node head        = _mru;
                    bool found       = false;
                    int  itemCount   = 0;

                    while (head != null && !found)
                    {
                        if (head.Value.Length == length)
                        {
                            if (candidate.IsOrdinalEqualToStringOfSameLength(head.Value))
                            {
                                found = true;
                            }
                        }

                        if (!found)
                        {
                            secondPrior = prior;
                            prior       = head;
                            head        = head.Next;
                        }

                        itemCount++;
                    }

                    if (found)
                    {
                        // Move it to the top and return the interned version.
                        if (prior != null)
                        {
                            if (!candidate.ReferenceEquals(head.Value))
                            {
                                // Wasn't at the top already, so move it there.
                                prior.Next = head.Next;
                                head.Next  = _mru;
                                _mru       = head;
                                interned   = _mru.Value;
                                return(true);
                            }
                            else
                            {
                                // But don't move it up if there is reference equality so that multiple calls to Intern don't redundantly emphasize a string.
                                interned = head.Value;
                                return(true);
                            }
                        }
                        else
                        {
                            // Found the item in the top spot. No need to move anything.
                            interned = _mru.Value;
                            return(true);
                        }
                    }
                    else
                    {
                        // Not found. Create a new entry and place it at the top.
                        Node old = _mru;
                        _mru = new Node(candidate.ExpensiveConvertToString())
                        {
                            Next = old
                        };

                        // Cache miss. Use this opportunity to discard any element over the max size.
                        if (itemCount >= _size && secondPrior != null)
                        {
                            secondPrior.Next = null;
                        }

                        interned = _mru.Value;
                        return(false);
                    }
                }
            /// <summary>
            /// Version of Intern that gathers statistics
            /// </summary>
            private string InternWithStatistics(IInternable candidate)
            {
                string result;
                _stopwatch.Start();
                bool? interned = TryIntern(candidate, out result);
                _stopwatch.Stop();

                if (interned.HasValue && !interned.Value)
                {
                    // Could not intern.
                    _internMisses++;

                    int priorCount = 0;
                    _missedStrings.TryGetValue(result, out priorCount);
                    _missedStrings[result] = priorCount + 1;

                    return result;
                }
                else if (interned == null)
                {
                    // Decided not to attempt interning
                    _internRejects++;

                    int priorCount = 0;
                    _rejectedStrings.TryGetValue(result, out priorCount);
                    _rejectedStrings[result] = priorCount + 1;

                    return result;
                }

                _internHits++;
                if (!candidate.ReferenceEquals(result))
                {
                    // Reference changed so 'candidate' is now released and should save memory.
                    _internEliminatedStrings++;
                    _internEliminatedChars += candidate.Length;
                }

                return result;
            }
                /// <summary>
                /// Try to get one element from the list. Upon leaving the function 'candidate' will be at the head of the Mru list.
                /// This function is not thread-safe.
                /// </summary>
                internal bool TryGet(IInternable candidate, out string interned)
                {
                    if (_size == 0)
                    {
                        interned = candidate.ExpensiveConvertToString();
                        return false;
                    }

                    int length = candidate.Length;
                    Node secondPrior = null;
                    Node prior = null;
                    Node head = _mru;
                    bool found = false;
                    int itemCount = 0;

                    while (head != null && !found)
                    {
                        if (head.Value.Length == length)
                        {
                            if (candidate.IsOrdinalEqualToStringOfSameLength(head.Value))
                            {
                                found = true;
                            }
                        }

                        if (!found)
                        {
                            secondPrior = prior;
                            prior = head;
                            head = head.Next;
                        }

                        itemCount++;
                    }

                    if (found)
                    {
                        // Move it to the top and return the interned version.
                        if (prior != null)
                        {
                            if (!candidate.ReferenceEquals(head.Value))
                            {
                                // Wasn't at the top already, so move it there. 
                                prior.Next = head.Next;
                                head.Next = _mru;
                                _mru = head;
                                interned = _mru.Value;
                                return true;
                            }
                            else
                            {
                                // But don't move it up if there is reference equality so that multiple calls to Intern don't redundantly emphasize a string.
                                interned = head.Value;
                                return true;
                            }
                        }
                        else
                        {
                            // Found the item in the top spot. No need to move anything.
                            interned = _mru.Value;
                            return true;
                        }
                    }
                    else
                    {
                        // Not found. Create a new entry and place it at the top.
                        Node old = _mru;
                        _mru = new Node(candidate.ExpensiveConvertToString());
                        _mru.Next = old;

                        // Cache miss. Use this opportunity to discard any element over the max size.
                        if (itemCount >= _size && secondPrior != null)
                        {
                            secondPrior.Next = null;
                        }

                        interned = _mru.Value;
                        return false;
                    }
                }