github.com/cranelv/ethereum_mpc@v0.0.0-20191031014521-23aeb1415092/consensus_pbft/util/messagefan.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"sync"
    21  
    22  	"github.com/ethereum/go-ethereum/log"
    23  	"github.com/ethereum/go-ethereum/consensus_pbft/pbftTypes"
    24  	"github.com/ethereum/go-ethereum/consensus_pbft/message"
    25  )
    26  
    27  // Message encapsulates an OpenchainMessage with sender information
    28  type Message struct {
    29  	Msg    *message.Message
    30  	Sender *pbftTypes.PeerID
    31  }
    32  
    33  // MessageFan contains the reference to the peer's MessageHandlerCoordinator
    34  type MessageFan struct {
    35  	ins  []<-chan *Message
    36  	out  chan *Message
    37  	lock sync.Mutex
    38  }
    39  
    40  // NewMessageFan will return an initialized MessageFan
    41  func NewMessageFan() *MessageFan {
    42  	return &MessageFan{
    43  		ins: []<-chan *Message{},
    44  		out: make(chan *Message),
    45  	}
    46  }
    47  
    48  // AddFaninChannel is intended to be invoked by Handler to add a channel to be fan-ed in
    49  func (fan *MessageFan) AddFaninChannel(channel <-chan *Message) {
    50  	fan.lock.Lock()
    51  	defer fan.lock.Unlock()
    52  
    53  	for _, c := range fan.ins {
    54  		if c == channel {
    55  			log.Warn("Received duplicate connection")
    56  			return
    57  		}
    58  	}
    59  
    60  	fan.ins = append(fan.ins, channel)
    61  
    62  	go func() {
    63  		for msg := range channel {
    64  			fan.out <- msg
    65  		}
    66  
    67  		fan.lock.Lock()
    68  		defer fan.lock.Unlock()
    69  
    70  		for i, c := range fan.ins {
    71  			if c == channel {
    72  				fan.ins = append(fan.ins[:i], fan.ins[i+1:]...)
    73  			}
    74  		}
    75  	}()
    76  }
    77  
    78  // GetOutChannel returns a read only channel which the registered channels fan into
    79  func (fan *MessageFan) GetOutChannel() <-chan *Message {
    80  	return fan.out
    81  }