crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/Threading/BlockingQueue.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.Collections;
       
    19 using System.Collections.Generic;
       
    20 using System.Text;
       
    21 using System.Threading;
       
    22 
       
    23 namespace SymbianUtils.Threading
       
    24 {
       
    25     public class BlockingQueue<T> : ICollection, IEnumerable 
       
    26     {
       
    27         #region Constructors
       
    28         public BlockingQueue()
       
    29             : this( -1 )
       
    30         {
       
    31         }
       
    32 
       
    33         public BlockingQueue( int aMaxSize )
       
    34         {
       
    35             iMaxSize = aMaxSize;
       
    36             iQueue = new Queue<T>();
       
    37         }
       
    38         #endregion
       
    39 
       
    40         #region API
       
    41         public void Enqueue( T aItem )
       
    42         {
       
    43             lock ( this.SyncRoot )
       
    44             {
       
    45                 // We want to prevent the queue from growing beyond it's own
       
    46                 // bounds, unless the creator requested an unbounded queue.
       
    47                 if ( iMaxSize > 0 )
       
    48                 {
       
    49                     while ( this.Count >= iMaxSize )
       
    50                     {
       
    51                         try
       
    52                         {
       
    53                             Monitor.Wait( this.SyncRoot );
       
    54                         }
       
    55                         catch
       
    56                         {
       
    57                             Monitor.PulseAll( this.SyncRoot );
       
    58                             throw;
       
    59                         }
       
    60                     }
       
    61                 }
       
    62 
       
    63                 // Now it's okay to add the item
       
    64                 iQueue.Enqueue( aItem );
       
    65 
       
    66                 // If the count is now one, then we've just added the first
       
    67                 // item, in which case we must pulse the monitor because
       
    68                 // there could be blocked threads that are stuck inside the Dequeue()
       
    69                 // method, waiting for published content.
       
    70                 int count = this.Count;
       
    71                 if ( count == 1 )
       
    72                 {
       
    73                     Monitor.PulseAll( this.SyncRoot );
       
    74                 }
       
    75             }
       
    76         }
       
    77 
       
    78         public bool TryToDequeue( out T aItem )
       
    79         {
       
    80             bool ret = false;
       
    81             aItem = default( T );
       
    82             //
       
    83             lock ( this.SyncRoot )
       
    84             {
       
    85                 if ( this.Count > 0 )
       
    86                 {
       
    87                     aItem = iQueue.Dequeue();
       
    88                     ret = true;
       
    89                 }
       
    90             }
       
    91             //
       
    92             return ret;
       
    93         }
       
    94 
       
    95         public void Clear()
       
    96         {
       
    97             lock ( this.SyncRoot )
       
    98             {
       
    99                 iQueue.Clear();
       
   100 
       
   101                 // Pulse, since clearing the items might allow a thread blocked
       
   102                 // inside Enqueue() to push something to the head of the list
       
   103                 Monitor.PulseAll( this.SyncRoot );
       
   104             }
       
   105         }
       
   106 
       
   107         public T Dequeue()
       
   108         {
       
   109             lock ( this.SyncRoot )
       
   110             {
       
   111                 // Wait until the queue contains some content.
       
   112                 while ( this.Count == 0 )
       
   113                 {
       
   114                     try
       
   115                     {
       
   116                         Monitor.Wait( this.SyncRoot );
       
   117                     }
       
   118                     catch
       
   119                     {
       
   120                         Monitor.PulseAll( this.SyncRoot );
       
   121                         throw;
       
   122                     }
       
   123                 }
       
   124 
       
   125                 T ret = iQueue.Dequeue();
       
   126 
       
   127                 // We dequeue the item and then check to see if we have
       
   128                 // just opened up the first free slot in the queue.
       
   129                 // If so, we must pulse the monitor because there could be
       
   130                 // threads blocked inside the Enqueue() method that are waiting
       
   131                 // for space to become available.
       
   132                 int count = this.Count;
       
   133                 if ( iMaxSize > 0 && count == iMaxSize - 1 )
       
   134                 {
       
   135                     Monitor.PulseAll( this.SyncRoot );
       
   136                 }
       
   137                 //
       
   138                 return ret;
       
   139             }
       
   140         }
       
   141 
       
   142         public T Peek()
       
   143         {
       
   144             lock ( this.SyncRoot )
       
   145             {
       
   146                 return iQueue.Peek();
       
   147             }
       
   148         }
       
   149 
       
   150         public bool Contains( T aItem )
       
   151         {
       
   152             lock ( this.SyncRoot )
       
   153             {
       
   154                 bool ret = iQueue.Contains( aItem );
       
   155                 return ret;
       
   156             }
       
   157         }
       
   158 
       
   159         public T[] ToArray()
       
   160         {
       
   161             lock ( this.SyncRoot )
       
   162             {
       
   163                 T[] ret = iQueue.ToArray();
       
   164                 return ret;
       
   165             }
       
   166         }
       
   167         #endregion
       
   168 
       
   169         #region From IEnumerable
       
   170         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   171         {
       
   172             throw new NotImplementedException( "You cannot enumerate a Blocking Queue - get the values and enumerate those instead" );
       
   173         }
       
   174         #endregion
       
   175 
       
   176         #region From ICollection
       
   177         public void CopyTo( Array aArray, int aIndex )
       
   178         {
       
   179             lock ( this.SyncRoot )
       
   180             {
       
   181                 ICollection baseCol = (ICollection) iQueue;
       
   182                 baseCol.CopyTo( aArray, aIndex );
       
   183             }
       
   184         }
       
   185 
       
   186         public int Count
       
   187         {
       
   188             get
       
   189             {
       
   190                 lock ( this.SyncRoot )
       
   191                 {
       
   192                     return iQueue.Count;
       
   193                 }
       
   194             }
       
   195         }
       
   196 
       
   197         public bool IsSynchronized
       
   198         {
       
   199             get { return true; }
       
   200         }
       
   201 
       
   202         public object SyncRoot
       
   203         {
       
   204             get 
       
   205             {
       
   206                 if ( this.iSyncRoot == null )
       
   207                 {
       
   208                     Interlocked.CompareExchange( ref this.iSyncRoot, new object(), null );
       
   209                 }
       
   210                 return iSyncRoot; 
       
   211             }
       
   212         }
       
   213         #endregion
       
   214 
       
   215         #region Data members
       
   216         private readonly Queue<T> iQueue;
       
   217         private object iSyncRoot = null;
       
   218         private readonly int iMaxSize;
       
   219         #endregion
       
   220     }
       
   221 }