public static void BetShopPoolTest() { int numThreads = 3; int numTickets = 200000; int numEvents = 100; var barrier = new Barrier(2); var betShop = new BetShop(numEvents); var randomizr = new Random(); var bags = new List<Action>[numThreads]; var threads = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { var bag = bags[i] = new List<Action>(); threads[i] = new Thread(() => { foreach (var a in bag) a(); }); } var complete = new Shielded<int>(); IDisposable completeCond = null; completeCond = Shield.Conditional(() => complete == numTickets, () => { barrier.SignalAndWait(); completeCond.Dispose(); }); var reportEvery = 10000; Shielded<int> lastReport = new Shielded<int>(0); Shielded<DateTime> lastTime = new Shielded<DateTime>(DateTime.UtcNow); using (Shield.Conditional( () => betShop.Tickets.Count >= lastReport + reportEvery, () => { DateTime newNow = DateTime.UtcNow; int count = betShop.Tickets.Count; int speed = (count - lastReport) * 1000 / (int)newNow.Subtract(lastTime).TotalMilliseconds; lastTime.Value = newNow; lastReport.Modify((ref int n) => n += reportEvery); Shield.SideEffect(() => Console.Write("\n{0} at {1} item/s", count, speed)); })) { foreach (var i in Enumerable.Range(0, numTickets)) { decimal payIn = (randomizr.Next(10) + 1m) * 1; int event1Id = randomizr.Next(numEvents) + 1; int event2Id = randomizr.Next(numEvents) + 1; int event3Id = randomizr.Next(numEvents) + 1; int offer1Ind = randomizr.Next(3); int offer2Ind = randomizr.Next(3); int offer3Ind = randomizr.Next(3); bags[i % numThreads].Add(() => Shield.InTransaction(() => { var offer1 = betShop.Events[event1Id].BetOffers[offer1Ind]; var offer2 = betShop.Events[event2Id].BetOffers[offer2Ind]; var offer3 = betShop.Events[event3Id].BetOffers[offer3Ind]; betShop.BuyTicket(payIn, offer1, offer2, offer3); complete.Commute((ref int n) => n++); })); } _timer = Stopwatch.StartNew(); for (int i = 0; i < numThreads; i++) threads[i].Start(); barrier.SignalAndWait(); } var time = _timer.ElapsedMilliseconds; var totalCorrect = betShop.VerifyTickets(); Console.WriteLine(" {0} ms with {1} tickets paid in and is {2}.", time, betShop.Tickets.Count, totalCorrect ? "correct" : "incorrect"); }
/// <summary> /// Creates a BetShop, and tries to buy a large number of random tickets. Afterwards it /// checks that the rule limiting same ticket winnings is not violated. /// </summary> public static void BetShopTest() { int numEvents = 100; var betShop = new BetShop(numEvents); var randomizr = new Random(); int reportEvery = 1000; var lastReport = new Shielded<int>(0); var lastTime = new Shielded<DateTime>(DateTime.UtcNow); long time; using (var reportingCond = Shield.Conditional( () => betShop.Tickets.Count >= lastReport + reportEvery, () => { DateTime newNow = DateTime.UtcNow; int count = betShop.Tickets.Count; int speed = (count - lastReport) * 1000 / (int)newNow.Subtract(lastTime).TotalMilliseconds; lastTime.Value = newNow; lastReport.Modify((ref int n) => n += reportEvery); Shield.SideEffect(() => { Console.Write("\n{0} at {1} item/s", count, speed); }); })) { time = mtTest("bet shop w/ " + numEvents, 50000, i => { decimal payIn = (randomizr.Next(10) + 1m) * 1; int event1Id = randomizr.Next(numEvents) + 1; int event2Id = randomizr.Next(numEvents) + 1; int event3Id = randomizr.Next(numEvents) + 1; int offer1Ind = randomizr.Next(3); int offer2Ind = randomizr.Next(3); int offer3Ind = randomizr.Next(3); return Task.Factory.StartNew(() => Shield.InTransaction(() => { var offer1 = betShop.Events[event1Id].BetOffers[offer1Ind]; var offer2 = betShop.Events[event2Id].BetOffers[offer2Ind]; var offer3 = betShop.Events[event3Id].BetOffers[offer3Ind]; betShop.BuyTicket(payIn, offer1, offer2, offer3); })); }); } //} var totalCorrect = betShop.VerifyTickets(); Console.WriteLine(" {0} ms with {1} tickets paid in and is {2}.", time, betShop.Tickets.Count, totalCorrect ? "correct" : "incorrect"); }