// threadedSendUpdates sends updates to a specific subscriber as updates become // available. If the subscriber deadlocks, this thread will deadlock, however // that will not affect any of the other threads in the transaction pool. func (tp *TransactionPool) threadedSendUpdates(update chan struct{}, subscriber modules.TransactionPoolSubscriber) { // Updates must be sent in order. This is achieved by having all of the // updates stored in the transaction pool in a specific order, and then // making blocking calls to 'ReceiveTransactionPoolUpates' until all of the // updates have been sent. i := 0 for { // Determine how many total updates there are to send. id := tp.mu.RLock() updateCount := len(tp.consensusChanges) tp.mu.RUnlock(id) // Send each of the updates in order, starting from the first update // that has not yet been sent to the subscriber. for i < updateCount { id := tp.mu.RLock() cc := tp.consensusChanges[i] unconfirmedTransactions := tp.unconfirmedTransactions[i] unconfirmedDiffs := tp.unconfirmedSiacoinDiffs[i] tp.mu.RUnlock(id) subscriber.ReceiveTransactionPoolUpdate(cc, unconfirmedTransactions, unconfirmedDiffs) i++ } // Wait until there has been another update. <-update } }
// TransactionPoolSubscribe adds a subscriber to the transaction pool. // Subscribers will receive all consensus set changes as well as transaction // pool changes, and should not subscribe to both. func (tp *TransactionPool) TransactionPoolSubscribe(subscriber modules.TransactionPoolSubscriber) { lockID := tp.mu.Lock() tp.subscribers = append(tp.subscribers, subscriber) for i := 0; i <= tp.consensusChangeIndex; i++ { cc, err := tp.consensusSet.ConsensusChange(i) if err != nil && build.DEBUG { panic(err) } subscriber.ProcessConsensusChange(cc) // Release the lock between iterations to smooth out performance a bit // - tpool does not need to hold the lock for 15,000 consensus change // objects. tp.mu.Unlock(lockID) runtime.Gosched() lockID = tp.mu.Lock() } // Send the new subscriber the transaction pool set. var txns []types.Transaction var cc modules.ConsensusChange for _, tSet := range tp.transactionSets { txns = append(txns, tSet...) } for _, tSetDiff := range tp.transactionSetDiffs { cc = cc.Append(tSetDiff) } subscriber.ReceiveUpdatedUnconfirmedTransactions(txns, cc) tp.mu.Unlock(lockID) }
// TransactionPoolSubscribe adds a subscriber to the transaction pool. // Subscribers will receive the full transaction set every time there is a // signficant change to the transaction pool. func (tp *TransactionPool) TransactionPoolSubscribe(subscriber modules.TransactionPoolSubscriber) { tp.mu.Lock() defer tp.mu.Unlock() // Add the subscriber to the subscriber list. tp.subscribers = append(tp.subscribers, subscriber) // Send the new subscriber the transaction pool set. var txns []types.Transaction for _, tSet := range tp.transactionSets { txns = append(txns, tSet...) } var cc modules.ConsensusChange for _, tSetDiff := range tp.transactionSetDiffs { cc = cc.Append(tSetDiff) } subscriber.ReceiveUpdatedUnconfirmedTransactions(txns, cc) }
// TransactionPoolSubscribe adds a subscriber to the transaction pool. // Subscribers will receive all consensus set changes as well as transaction // pool changes, and should not subscribe to both. func (tp *TransactionPool) TransactionPoolSubscribe(subscriber modules.TransactionPoolSubscriber) { id := tp.mu.Lock() tp.subscribers = append(tp.subscribers, subscriber) for i := 0; i <= tp.consensusChangeIndex; i++ { cc, err := tp.consensusSet.ConsensusChange(i) if err != nil && build.DEBUG { panic(err) } subscriber.ProcessConsensusChange(cc) } // Send the new subscriber the transaction pool set. var txns []types.Transaction var cc modules.ConsensusChange for _, tSet := range tp.transactionSets { txns = append(txns, tSet...) } for _, tSetDiff := range tp.transactionSetDiffs { cc = cc.Append(tSetDiff) } subscriber.ReceiveUpdatedUnconfirmedTransactions(txns, cc) tp.mu.Unlock(id) }