Ignore:
Timestamp:
01/12/10 08:05:29 (4 years ago)
Author:
lowjoel
Message:

Thread-safe the ChainedProgressManager? classes by locking the task list before modifying or accessing them. This may introduce lock contention performance penalties but we'll stick with this first (fix it with a writer lock afterward if it turns out to be a performance bottleneck.) The ProgressManager? class is not locked at all since it deals with integers only.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eraser6/SpeedMeter/Eraser.Manager/ProgressManager.cs

    r1506 r1510  
    262262            { 
    263263                List = new List<Step>(); 
     264                ListLock = manager.ListLock; 
    264265                Manager = manager; 
    265266            } 
     
    269270            public int IndexOf(Step item) 
    270271            { 
    271                 return List.IndexOf(item); 
     272                lock (ListLock) 
     273                    return List.IndexOf(item); 
    272274            } 
    273275 
    274276            public void Insert(int index, Step item) 
    275277            { 
    276                 List.Insert(index, item); 
    277                 TotalWeights += item.Weight; 
     278                lock (ListLock) 
     279                { 
     280                    List.Insert(index, item); 
     281                    TotalWeights += item.Weight; 
     282                } 
    278283            } 
    279284 
    280285            public void RemoveAt(int index) 
    281286            { 
    282                 TotalWeights -= List[index].Weight; 
    283                 List.RemoveAt(index); 
     287                lock (ListLock) 
     288                { 
     289                    TotalWeights -= List[index].Weight; 
     290                    List.RemoveAt(index); 
     291                } 
    284292            } 
    285293 
     
    288296                get 
    289297                { 
    290                     return List[index]; 
     298                    lock (ListLock) 
     299                        return List[index]; 
    291300                } 
    292301                set 
    293302                { 
    294                     TotalWeights -= List[index].Weight; 
    295                     List[index] = value; 
    296                     TotalWeights += value.Weight; 
     303                    lock (ListLock) 
     304                    { 
     305                        TotalWeights -= List[index].Weight; 
     306                        List[index] = value; 
     307                        TotalWeights += value.Weight; 
     308                    } 
    297309                } 
    298310            } 
     
    304316            public void Add(Step item) 
    305317            { 
    306                 List.Add(item); 
    307                 TotalWeights += item.Weight; 
     318                lock (ListLock) 
     319                { 
     320                    List.Add(item); 
     321                    TotalWeights += item.Weight; 
     322                } 
    308323            } 
    309324 
    310325            public void Clear() 
    311326            { 
    312                 List.Clear(); 
    313                 TotalWeights = 0; 
     327                lock (ListLock) 
     328                { 
     329                    List.Clear(); 
     330                    TotalWeights = 0; 
     331                } 
    314332            } 
    315333 
    316334            public bool Contains(Step item) 
    317335            { 
    318                 return List.Contains(item); 
     336                lock (ListLock) 
     337                    return List.Contains(item); 
    319338            } 
    320339 
    321340            public void CopyTo(Step[] array, int arrayIndex) 
    322341            { 
    323                 List.CopyTo(array, arrayIndex); 
     342                lock (ListLock) 
     343                    List.CopyTo(array, arrayIndex); 
    324344            } 
    325345 
    326346            public int Count 
    327347            { 
    328                 get { return List.Count; } 
     348                get 
     349                { 
     350                    lock (ListLock)  
     351                        return List.Count; 
     352                } 
    329353            } 
    330354 
     
    366390            /// The total weights of all the steps. 
    367391            /// </summary> 
    368             public float TotalWeights 
     392            private float TotalWeights 
    369393            { 
    370394                get 
     
    372396                    return totalWeights; 
    373397                } 
    374                 private set 
     398                set 
    375399                { 
    376400                    if (value >= 1.1f || value < 0.0f) 
     
    388412 
    389413            /// <summary> 
     414            /// The lock object guarding the list against parallel writes. 
     415            /// </summary> 
     416            private object ListLock; 
     417 
     418            /// <summary> 
    390419            /// The <see cref="SteppedProgressManager"/> instance which owns this list. 
    391420            /// </summary> 
     
    404433        { 
    405434            Steps = new StepsList(this); 
     435            ListLock = new object(); 
    406436        } 
    407437 
     
    411441            { 
    412442                float result = 0.0f; 
    413                 foreach (Step step in Steps) 
    414                     result += step.Progress.Progress * step.Weight; 
     443                lock (ListLock) 
     444                    foreach (Step step in Steps) 
     445                        result += step.Progress.Progress * step.Weight; 
    415446 
    416447                return result; 
     
    457488            get 
    458489            { 
    459                 if (Steps.Count == 0) 
    460                     return null; 
    461  
    462                 foreach (Step step in Steps) 
    463                     if (step.Progress.Progress < 1.0f) 
    464                         return step; 
    465  
    466                 //Return the last step since we don't have any 
    467                 return Steps[Steps.Count - 1]; 
    468             } 
    469         } 
     490                lock (ListLock) 
     491                { 
     492                    if (Steps.Count == 0) 
     493                        return null; 
     494 
     495                    foreach (Step step in Steps) 
     496                        if (step.Progress.Progress < 1.0f) 
     497                            return step; 
     498 
     499                    //Return the last step since we don't have any 
     500                    return Steps[Steps.Count - 1]; 
     501                } 
     502            } 
     503        } 
     504 
     505        /// <summary> 
     506        /// The lock object guarding the list of steps against concurrent read and write. 
     507        /// </summary> 
     508        private object ListLock; 
    470509    } 
    471510 
     
    481520        public class SubTasksList : IList<ProgressManagerBase> 
    482521        { 
    483             public SubTasksList() 
     522            public SubTasksList(ParallelProgressManager manager) 
    484523            { 
    485524                List = new List<ProgressManagerBase>(); 
     525                ListLock = manager.TaskLock; 
    486526            } 
    487527 
     
    490530            public int IndexOf(ProgressManagerBase item) 
    491531            { 
    492                 return List.IndexOf(item); 
     532                lock (ListLock) 
     533                    return List.IndexOf(item); 
    493534            } 
    494535 
    495536            public void Insert(int index, ProgressManagerBase item) 
    496537            { 
    497                 List.Insert(index, item); 
     538                lock (ListLock) 
     539                    List.Insert(index, item); 
    498540            } 
    499541 
    500542            public void RemoveAt(int index) 
    501543            { 
    502                 List.RemoveAt(index); 
     544                lock (ListLock) 
     545                    List.RemoveAt(index); 
    503546            } 
    504547 
     
    507550                get 
    508551                { 
    509                     return List[index]; 
     552                    lock (ListLock) 
     553                        return List[index]; 
    510554                } 
    511555                set 
    512556                { 
    513                     List[index] = value; 
     557                    lock (ListLock) 
     558                        List[index] = value; 
    514559                } 
    515560            } 
     
    521566            public void Add(ProgressManagerBase item) 
    522567            { 
    523                 List.Add(item); 
     568                lock (ListLock) 
     569                    List.Add(item); 
    524570            } 
    525571 
    526572            public void Clear() 
    527573            { 
    528                 List.Clear(); 
     574                lock (ListLock) 
     575                    List.Clear(); 
    529576            } 
    530577 
     
    536583            public void CopyTo(ProgressManagerBase[] array, int arrayIndex) 
    537584            { 
    538                 List.CopyTo(array, arrayIndex); 
     585                lock (ListLock) 
     586                    List.CopyTo(array, arrayIndex); 
    539587            } 
    540588 
    541589            public int Count 
    542590            { 
    543                 get { return List.Count; } 
     591                get 
     592                { 
     593                    lock (ListLock)  
     594                        return List.Count; 
     595                } 
    544596            } 
    545597 
     
    551603            public bool Remove(ProgressManagerBase item) 
    552604            { 
    553                 return List.Remove(item); 
     605                lock (ListLock) 
     606                    return List.Remove(item); 
    554607            } 
    555608 
     
    580633 
    581634            /// <summary> 
    582             /// The total weights of all the steps. 
    583             /// </summary> 
    584             public int TotalWeights 
    585             { 
    586                 get; 
    587                 private set; 
    588             } 
     635            /// The lock object guarding the list from concurrent read/writes. 
     636            /// </summary> 
     637            private object ListLock; 
    589638        } 
    590639 
     
    594643        public ParallelProgressManager() 
    595644        { 
    596             Tasks = new SubTasksList(); 
     645            Tasks = new SubTasksList(this); 
     646            TaskLock = new object(); 
    597647        } 
    598648 
     
    602652            { 
    603653                float result = 0.0f; 
    604                 foreach (ProgressManagerBase subTask in Tasks) 
    605                     result += subTask.Progress * (1.0f / Tasks.Count); 
     654                lock (TaskLock) 
     655                    foreach (ProgressManagerBase subTask in Tasks) 
     656                        result += subTask.Progress * (1.0f / Tasks.Count); 
    606657 
    607658                return result; 
     
    614665            { 
    615666                int maxSpeed = 0; 
    616                 foreach (ProgressManagerBase subTask in Tasks) 
    617                     maxSpeed = Math.Max(subTask.Speed, maxSpeed); 
     667                lock (TaskLock) 
     668                    foreach (ProgressManagerBase subTask in Tasks) 
     669                        maxSpeed = Math.Max(subTask.Speed, maxSpeed); 
    618670 
    619671                return maxSpeed; 
     
    626678            { 
    627679                TimeSpan maxTime = TimeSpan.MinValue; 
    628                 foreach (ProgressManagerBase subTask in Tasks) 
    629                     if (maxTime < subTask.TimeLeft) 
    630                         maxTime = subTask.TimeLeft; 
     680                lock (TaskLock) 
     681                    foreach (ProgressManagerBase subTask in Tasks) 
     682                        if (maxTime < subTask.TimeLeft) 
     683                            maxTime = subTask.TimeLeft; 
    631684 
    632685                return maxTime; 
     
    643696            private set; 
    644697        } 
     698 
     699        /// <summary> 
     700        /// The lock object guarding the list of tasks against concurrent read and write. 
     701        /// </summary> 
     702        private object TaskLock; 
    645703    } 
    646704} 
Note: See TracChangeset for help on using the changeset viewer.