Composite.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. #if STRESS
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Reactive.Disposables;
  7. using System.Reflection;
  8. using System.Threading;
  9. namespace ReactiveTests.Stress.Disposables
  10. {
  11. public class Composite
  12. {
  13. /// <summary>
  14. /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
  15. /// The CompositeDisposable is disposed either at the start, at the end, or at a random time.
  16. /// </summary>
  17. public static void Potpourri()
  18. {
  19. Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
  20. for (int i = 1; i <= 100; i++)
  21. {
  22. for (int j = 0; j < 10; j++)
  23. {
  24. DisposeBeforeAddRemove();
  25. DisposeDuringAddRemove();
  26. DisposeDuringAddRemove();
  27. DisposeDuringAddRemove();
  28. DisposeAfterAddRemove();
  29. }
  30. Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
  31. }
  32. }
  33. /// <summary>
  34. /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
  35. /// The CompositeDisposable is disposed at the start.
  36. /// </summary>
  37. public static void DisposeBeforeAddRemove()
  38. {
  39. Impl(0);
  40. }
  41. /// <summary>
  42. /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
  43. /// The CompositeDisposable is disposed at a random time.
  44. /// </summary>
  45. public static void DisposeDuringAddRemove()
  46. {
  47. Impl(1);
  48. }
  49. /// <summary>
  50. /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
  51. /// The CompositeDisposable is disposed at the end.
  52. /// </summary>
  53. public static void DisposeAfterAddRemove()
  54. {
  55. Impl(2);
  56. }
  57. static void Impl(int disposeAt)
  58. {
  59. var rand = new Random();
  60. var g = new CompositeDisposable();
  61. Console.Write("Dispose @ = {0} - ", disposeAt);
  62. if (disposeAt == 0)
  63. {
  64. g.Dispose();
  65. Console.Write("{GD} ");
  66. }
  67. if (disposeAt == 1)
  68. {
  69. var sleep = rand.Next(0, 5) > 1 /* 60% chance */ ? rand.Next(2, 1000) : 0;
  70. ThreadPool.QueueUserWorkItem(_ =>
  71. {
  72. Helpers.SleepOrSpin(sleep);
  73. g.Dispose();
  74. Console.Write("{GD} ");
  75. });
  76. }
  77. var n = rand.Next(0, 1000);
  78. var cd = new CountdownEvent(n);
  79. var ds = Enumerable.Range(0, n).Select(_ => Disposable.Create(() => cd.Signal())).ToArray();
  80. var m = rand.Next(1, 100);
  81. var jobs = ds.GroupBy(_ => rand.Next() % m).Select(Enumerable.ToList).ToList();
  82. Console.Write("N = {0}, M = {1} - ", n, m);
  83. var done = new CountdownEvent(jobs.Count);
  84. foreach (var job in jobs)
  85. {
  86. var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
  87. var sleepAt = Enumerable.Range(0, rand.Next(0, job.Count) / rand.Next(1, 100)).ToArray();
  88. var sleeps = sleepAt.Select(_ => rand.Next(0, 50)).ToArray();
  89. var rem = rand.Next(0, 3) == 0; /* 33% chance */
  90. var remAt = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
  91. var mine = job;
  92. ThreadPool.QueueUserWorkItem(_ =>
  93. {
  94. Helpers.SleepOrSpin(sleep);
  95. var j = 0;
  96. foreach (var d in mine)
  97. {
  98. var dd = d;
  99. if (sleepAt.Contains(j))
  100. Helpers.SleepOrSpin(sleeps[j]);
  101. g.Add(dd);
  102. Console.Write("+");
  103. if (rem)
  104. {
  105. ThreadPool.QueueUserWorkItem(__ =>
  106. {
  107. Helpers.SleepOrSpin(remAt);
  108. g.Remove(dd);
  109. Console.Write("-");
  110. });
  111. }
  112. j++;
  113. }
  114. done.Signal();
  115. });
  116. }
  117. done.Wait();
  118. if (disposeAt == 2)
  119. {
  120. g.Dispose();
  121. Console.Write("{GD} ");
  122. }
  123. cd.Wait();
  124. Console.WriteLine(".");
  125. }
  126. }
  127. }
  128. #endif