// This test is for the case where two different clusters are racing, // trying to activate the same grain. // This function takes two arguments, a list of client configurations, and an integer. The list of client configurations is used to // create multiple clients that concurrently call the grains in range [0, numGrains). We run the experiment in a series of barriers. // The clients all invoke grain "g", in parallel, and then wait on a signal by the main thread (this function). The main thread, then // wakes up the clients, after which they invoke "g+1", and so on. private Task CreationRace() { WriteLog("Starting ConcurrentCreation"); var offset = random.Next(); // take inventory now so we can exclude pre-existing entries from the validation var baseline = GetGrainActivations(); // We use two objects to coordinate client threads and the main thread. coordWakeup is an object that is used to signal the coordinator // thread. toWait is used to signal client threads. var coordWakeup = new object(); var toWait = new object(); // We keep a list of client threads. var clientThreads = new List <Tuple <Thread, ClientThreadArgs> >(); var rand = new Random(); var results = new List <Tuple <int, int> > [clients.Length]; threadsDone = results.Length; int index = 0; // Create a client thread corresponding to each client // The client thread will execute ThreadFunc function. foreach (var client in clients) { // A client thread takes a list of tupes<int, int> as argument. The list is an ordered sequence of grains to invoke. tuple.item2 // is the grainId. tuple.item1 is never used (this should probably be cleaned up, but I don't want to break anything :). var args = new List <Tuple <int, int> >(); for (int j = 0; j < numGrains; ++j) { var waitTime = rand.Next(16, 100); args.Add(Tuple.Create(waitTime, j)); } // Given a config file, create client starts a client in a new appdomain. We also create a thread on which the client will run. // The thread takes a "ClientThreadArgs" as argument. var thread = new Thread(ThreadFunc); var threadFuncArgs = new ClientThreadArgs { client = client, args = args, resultIndex = index, numThreads = clients.Length, coordWakeup = coordWakeup, toWait = toWait, results = results, offset = offset }; clientThreads.Add(Tuple.Create(thread, threadFuncArgs)); index += 1; } // Go through the list of client threads, and start each of the threads with the appropriate arguments. foreach (var threadNArg in clientThreads) { var thread = threadNArg.Item1; var arg = threadNArg.Item2; thread.Start(arg); } // We run numGrains iterations of the experiment. The coordinator thread calls the function "WaitForWorkers" in order to wait // for the client threads to finish concurrent calls to a single grain. for (int i = 0; i < numGrains; ++i) { WaitForWorkers(clients.Length, coordWakeup, toWait); } // Once the clients threads have finished calling the grain the appropriate number of times, we wait for them to write out their results. foreach (var threadNArg in clientThreads) { var thread = threadNArg.Item1; thread.Join(); } var grains = GetGrainActivations(baseline); ValidateClusterRaceResults(results, grains); return(TaskDone.Done); }
// This test is for the case where two different clusters are racing, // trying to activate the same grain. // This function takes two arguments, a list of client configurations, and an integer. The list of client configurations is used to // create multiple clients that concurrently call the grains in range [0, numGrains). We run the experiment in a series of barriers. // The clients all invoke grain "g", in parallel, and then wait on a signal by the main thread (this function). The main thread, then // wakes up the clients, after which they invoke "g+1", and so on. private Task CreationRace() { WriteLog("Starting ConcurrentCreation"); var offset = random.Next(); // take inventory now so we can exclude pre-existing entries from the validation var baseline = GetGrainActivations(); // We use two objects to coordinate client threads and the main thread. coordWakeup is an object that is used to signal the coordinator // thread. toWait is used to signal client threads. var coordWakeup = new object(); var toWait = new object(); // We keep a list of client threads. var clientThreads = new List<Tuple<Thread, ClientThreadArgs>>(); var rand = new Random(); var results = new List<Tuple<int, int>>[clients.Length]; threadsDone = results.Length; int index = 0; // Create a client thread corresponding to each client // The client thread will execute ThreadFunc function. foreach (var client in clients) { // A client thread takes a list of tupes<int, int> as argument. The list is an ordered sequence of grains to invoke. tuple.item2 // is the grainId. tuple.item1 is never used (this should probably be cleaned up, but I don't want to break anything :). var args = new List<Tuple<int, int>>(); for (int j = 0; j < numGrains; ++j) { var waitTime = rand.Next(16, 100); args.Add(Tuple.Create(waitTime, j)); } // Given a config file, create client starts a client in a new appdomain. We also create a thread on which the client will run. // The thread takes a "ClientThreadArgs" as argument. var thread = new Thread(ThreadFunc); var threadFuncArgs = new ClientThreadArgs { client = client, args = args, resultIndex = index, numThreads = clients.Length, coordWakeup = coordWakeup, toWait = toWait, results = results, offset = offset }; clientThreads.Add(Tuple.Create(thread, threadFuncArgs)); index += 1; } // Go through the list of client threads, and start each of the threads with the appropriate arguments. foreach (var threadNArg in clientThreads) { var thread = threadNArg.Item1; var arg = threadNArg.Item2; thread.Start(arg); } // We run numGrains iterations of the experiment. The coordinator thread calls the function "WaitForWorkers" in order to wait // for the client threads to finish concurrent calls to a single grain. for (int i = 0; i < numGrains; ++i) { WaitForWorkers(clients.Length, coordWakeup, toWait); } // Once the clients threads have finished calling the grain the appropriate number of times, we wait for them to write out their results. foreach (var threadNArg in clientThreads) { var thread = threadNArg.Item1; thread.Join(); } var grains = GetGrainActivations(baseline); ValidateClusterRaceResults(results, grains); return TaskDone.Done; }