示例#1
0
文件: subscribers.go 项目: mm3/Sia
// threadedSendUpdates sends updates to a specific subscriber as they become
// available. One thread is needed per subscriber. A separate function was
// needed due to race conditions; subscribers must receive updates in the
// correct order. Furthermore, a deadlocked subscriber should not interfere
// with consensus; updates cannot make blocking calls from any thread that is
// holding a lock on consensus. The result is a construction where all updates
// are added to a list of updates in the consensus set while the consensus set
// is locked. Then, a separate thread for each subscriber will be notified (via
// the update chan) that there are new updates. The thread will lock the
// consensus set for long enough to get the updates, and then will unlock the
// consensus set while it makes a blocking call to the subscriber. If the
// subscriber deadlocks or has problems, the thread will stall indefinitely,
// but the rest of consensus will not be disrupted.
func (s *State) threadedSendUpdates(update chan struct{}, subscriber modules.ConsensusSetSubscriber) {
	i := 0
	for {
		id := s.mu.RLock()
		updateCount := len(s.consensusChanges)
		s.mu.RUnlock(id)
		for i < updateCount {
			// Get the set of blocks that changed since the previous update.
			id := s.mu.RLock()
			cc := s.consensusChanges[i]
			s.mu.RUnlock(id)

			// Update the subscriber with the changes.
			subscriber.ReceiveConsensusSetUpdate(cc)
			i++
		}

		// Wait until there has been another update.
		<-update
	}
}