/// <summary> /// Unregisters a dead slave from the monitor. /// </summary> public virtual void UnregisterSlave(ISlaveConnection slave) { lock (_allSlaves.SyncRoot) { _allSlaves.Remove(slave); NotifyMonitor(_allSlaves); } lock (_availableSlaves.SyncRoot) { _availableSlaves.Remove(slave); NotifyMonitor(_availableSlaves); } }
/// <summary> /// Notifies the monitor that the particular slave has finished performing a job, /// and it (probably) is available for other jobs. /// </summary> public virtual void NotifySlaveAvailability(ISlaveConnection slave, IJob job, IEvolutionState state) { // first announce that a slave in allSlaves has finished, so people blocked on waitForAllSlavesToFinishEvaluating // can wake up and realize it. lock (_allSlaves.SyncRoot) { NotifyMonitor(_allSlaves); } // now announce that we've got a new available slave if someone wants it if (slave.NumJobs < MaxJobsPerSlave) { lock (_availableSlaves.SyncRoot) { if (!_availableSlaves.Contains(slave)) { _availableSlaves.Insert(_availableSlaves.Count, slave); } NotifyMonitor(_availableSlaves); } } Debug("Notify the monitor that the slave is available."); // now announce that we've got a new completed individual if someone is waiting for it if (state is SteadyStateEvolutionState) { // Perhaps we should the individuals by fitness first, so the fitter ones show up later // and don't get immediately wiped out by less fit ones. Or should it be the other way // around? We might revisit that in the future. // At any rate, add ALL the individuals that came back to the evaluatedIndividuals LinkedList lock (_evaluatedIndividuals) { for (var x = 0; x < job.Inds.Length; x++) { _evaluatedIndividuals.Insert(_evaluatedIndividuals.Count, new QueueIndividual(job.Inds[x], job.Subpops[x])); } NotifyMonitor(_evaluatedIndividuals); } } }