Click here to Skip to main content
15,887,485 members

The Weird and The Wonderful

   

The Weird and The Wonderful forum is a place to post Coding Horrors, Worst Practices, and the occasional flash of brilliance.

We all come across code that simply boggles the mind. Lazy kludges, embarrassing mistakes, horrid workarounds and developers just not quite getting it. And then somedays we come across - or write - the truly sublime.

Post your Best, your worst, and your most interesting. But please - no programming questions . This forum is purely for amusement and discussions on code snippets. All actual programming questions will be removed.

 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
raddevus6-Feb-18 5:41
mvaraddevus6-Feb-18 5:41 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
Kornfeld Eliyahu Peter6-Feb-18 3:37
professionalKornfeld Eliyahu Peter6-Feb-18 3:37 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
raddevus6-Feb-18 5:37
mvaraddevus6-Feb-18 5:37 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
Richard Deeming6-Feb-18 10:11
mveRichard Deeming6-Feb-18 10:11 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
raddevus6-Feb-18 10:19
mvaraddevus6-Feb-18 10:19 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
Jörgen Andersson9-Feb-18 2:02
professionalJörgen Andersson9-Feb-18 2:02 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
raddevus9-Feb-18 4:16
mvaraddevus9-Feb-18 4:16 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
Richard Deeming9-Feb-18 4:47
mveRichard Deeming9-Feb-18 4:47 
If you can afford the extra memory usage, the simplest option would probably be a custom class to store the data twice - once in a HashSet<T>, and once in a Queue<T>.

You'd obviously need to add your own locking code to ensure it was thread-safe.

Off the top of my head, something like this might work:
C#
public sealed class UniqueQueue<T> : IEnumerable<T>, IDisposable
{
    private readonly Queue<T> _queue = new Queue<T>();
    private readonly HashSet<T> _set = new HashSet<T>();
    private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    
    public int Count
    {
        get
        {
            bool lockTaken = false;
            try
            {
                lockTaken = _lock.TryEnterReadLock(Timeout.Infinite);
                if (!lockTaken) throw new InvalidOperationException();
                
                return _queue.Count;
            }
            finally
            {
                if (lockTaken)
                {
                    _lock.ExitReadLock();
                }
            }
        }
    }
    
    public void Dispose()
    {
        _lock.Dispose();
    }
    
    public T Dequeue()
    {
        bool lockTaken = false;
        try
        {
            lockTaken = _lock.TryEnterWriteLock(Timeout.Infinite);
            if (!lockTaken) throw new InvalidOperationException();
            
            T oldestItem = _queue.Dequeue();
            _set.Remove(oldestItem);
            return oldestItem;
        }
        finally
        {
            if (lockTaken)
            {
                _lock.ExitWriteLock();
            }
        }
    }
    
    public void AddRange(IEnumerable<T> itemsToAdd)
    {
        if (itemsToAdd == null) throw new ArgumentNullException(nameof(itemsToAdd));
        
        bool lockTaken = false;
        try
        {
            lockTaken = _lock.TryEnterWriteLock(Timeout.Infinite);
            if (!lockTaken) throw new InvalidOperationException();
            
            foreach (T item in itemsToAdd)
            {
                if (_set.Add(item))
                {
                    _queue.Enqueue(item);
                }
            }
        }
        finally
        {
            if (lockTaken)
            {
                _lock.ExitWriteLock();
            }
        }
    }
    
    public UniqueQueueEnumerator GetEnumerator()
    {
        T[] copyOfItems = Array.Empty<T>();
        
        bool lockTaken = false;
        try
        {
            lockTaken = _lock.TryEnterReadLock(Timeout.Infinite);
            if (!lockTaken) throw new InvalidOperationException();
            
            copyOfItems = new T[_queue.Count];
            _queue.CopyTo(copyOfItems, 0);
        }
        finally
        {
            if (lockTaken)
            {
                _lock.ExitReadLock();
            }
        }
        
        return new UniqueQueueEnumerator(copyOfItems);
    }
    
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
    
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    
    public struct UniqueQueueEnumerator : IEnumerator<T>
    {
        private readonly T[] _items;
        private int _position;
        
        public UniqueQueueEnumerator(T[] items)
        {
            _items = items;
            _position = -1;
        }
        
        void IDisposable.Dispose()
        {
        }
        
        public void Reset()
        {
            if (_items == null) throw new InvalidOperationException();
            _position = -1;
        }
        
        public bool MoveNext()
        {
            if (_items == null) return false;
            return ++_position < _items.Length;
        }
        
        public T Current
        {
            get
            {
                if (_items == null) throw new InvalidOperationException();
                if (0 > _position || _position >= _items.Length) throw new InvalidOperationException();
                return _items[_position];
            }
        }
        
        object IEnumerator.Current => Current;
    }
}




"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer


GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
raddevus9-Feb-18 8:31
mvaraddevus9-Feb-18 8:31 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
Richard Deeming12-Feb-18 8:19
mveRichard Deeming12-Feb-18 8:19 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
Jörgen Andersson9-Feb-18 6:09
professionalJörgen Andersson9-Feb-18 6:09 
GeneralRe: ConcurrentQueue & FirstOrDefault() and search speed. Pin
patbob19-Feb-18 5:42
patbob19-Feb-18 5:42 
Generalsql maths Pin
kmoorevs27-Jan-18 7:17
kmoorevs27-Jan-18 7:17 
GeneralRe: sql maths Pin
RedDk28-Jan-18 11:12
RedDk28-Jan-18 11:12 
GeneralRe: sql maths Pin
kmoorevs29-Jan-18 2:53
kmoorevs29-Jan-18 2:53 
GeneralRe: sql maths Pin
Tomz_KV29-Jan-18 5:43
Tomz_KV29-Jan-18 5:43 
GeneralRe: sql maths Pin
kmoorevs29-Jan-18 5:52
kmoorevs29-Jan-18 5:52 
GeneralHow to add a single item to an array Pin
Marc Clifton23-Jan-18 3:03
mvaMarc Clifton23-Jan-18 3:03 
GeneralRe: How to add a single item to an array Pin
Ehsan Sajjad23-Jan-18 3:18
professionalEhsan Sajjad23-Jan-18 3:18 
GeneralRe: How to add a single item to an array Pin
BillW3323-Jan-18 3:45
professionalBillW3323-Jan-18 3:45 
GeneralRe: How to add a single item to an array Pin
Nelek23-Jan-18 3:50
protectorNelek23-Jan-18 3:50 
GeneralRe: How to add a single item to an array Pin
Marc Clifton23-Jan-18 3:55
mvaMarc Clifton23-Jan-18 3:55 
GeneralRe: How to add a single item to an array Pin
Nelek23-Jan-18 4:13
protectorNelek23-Jan-18 4:13 
GeneralRe: How to add a single item to an array Pin
Bernhard Hiller23-Jan-18 21:50
Bernhard Hiller23-Jan-18 21:50 
GeneralRe: How to add a single item to an array Pin
Eddy Vluggen24-Jan-18 0:44
professionalEddy Vluggen24-Jan-18 0:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.