Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Challenge: The problem of locking down tasks…

DZone's Guide to

Challenge: The problem of locking down tasks…

· Database Zone
Free Resource

Whether you work in SQL Server Management Studio or Visual Studio, Redgate tools integrate with your existing infrastructure, enabling you to align DevOps for your applications with DevOps for your SQL Server databases. Discover true Database DevOps, brought to you in partnership with Redgate.

The following code has very subtle bug:

    public class AsyncQueue
    {
        private readonly Queue<int> items = new Queue<int>();
        private volatile LinkedList<TaskCompletionSource<object>> waiters = new LinkedList<TaskCompletionSource<object>>();
     
        public void Enqueue(int i)
        {
            lock (items)
            {
               items.Enqueue(i);
               while (waiters.First != null)
               {
                   waiters.First.Value.TrySetResult(null);
                   waiters.RemoveFirst();
               }
           }
       }
    
       public async Task<IEnumerable<int>> DrainAsync()
       {
           while (true)
           {
               TaskCompletionSource<object> taskCompletionSource;
               lock (items)
               {
                   if (items.Count > 0)
                   {
                       return YieldAllItems();
                   }
                   taskCompletionSource = new TaskCompletionSource<object>();
                   waiters.AddLast(taskCompletionSource);
               }
               await taskCompletionSource.Task;
           }
       }
    
       private IEnumerable<int> YieldAllItems()
       {
           while (items.Count > 0)
           {
               yield return items.Dequeue();
           }
    
       }
   }

I’ll even give you a hint, try to run the following client code:

    for (int i = 0; i < 1000 * 1000; i++)
    {
        q.Enqueue(i);
        if (i%100 == 0)
        {
            Task.Factory.StartNew(async () =>
                {
                    foreach (var result in await q.DrainAsync())
                    {
                       Console.WriteLine(result);
                   }
               });
       }
    
   }
Can you figure out what the problem is?







It’s easier than you think to extend DevOps practices to SQL Server with Redgate tools. Discover how to introduce true Database DevOps, brought to you in partnership with Redgate

Topics:

Published at DZone with permission of Oren Eini, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}