Serial.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 Serial
  12. {
  13. /// <summary>
  14. /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
  15. /// The SerialDisposable is disposed either at the start, at the end, or at a random time.
  16. /// </summary>
  17. public static void RandomAssignAndDispose()
  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. DisposeBeforeAssign();
  25. DisposeDuringAssign();
  26. DisposeDuringAssign();
  27. DisposeDuringAssign();
  28. DisposeAfterAssign();
  29. }
  30. Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
  31. }
  32. }
  33. /// <summary>
  34. /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
  35. /// The SerialDisposable is disposed at the start.
  36. /// </summary>
  37. public static void DisposeBeforeAssign()
  38. {
  39. Impl(0);
  40. }
  41. /// <summary>
  42. /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
  43. /// The SerialDisposable is disposed at a random time.
  44. /// </summary>
  45. public static void DisposeDuringAssign()
  46. {
  47. Impl(1);
  48. }
  49. /// <summary>
  50. /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
  51. /// The SerialDisposable is disposed at the end.
  52. /// </summary>
  53. public static void DisposeAfterAssign()
  54. {
  55. Impl(2);
  56. }
  57. static void Impl(int disposeAt)
  58. {
  59. var rand = new Random();
  60. var s = new SerialDisposable();
  61. Console.Write("Dispose @ = {0} - ", disposeAt);
  62. if (disposeAt == 0)
  63. {
  64. s.Dispose();
  65. Console.Write("{SD} ");
  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. s.Dispose();
  74. Console.Write("{SD} ");
  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. if (sleepAt.Contains(j))
  99. Helpers.SleepOrSpin(sleeps[j]);
  100. s.Disposable = d;
  101. Console.Write("+");
  102. j++;
  103. }
  104. done.Signal();
  105. });
  106. }
  107. done.Wait();
  108. if (disposeAt == 2)
  109. {
  110. s.Dispose();
  111. Console.Write("{SD} ");
  112. }
  113. cd.Wait();
  114. Console.WriteLine(".");
  115. }
  116. }
  117. }
  118. #endif