<commit_before>package concurrent

//----------------------------------------------------------------------
// This file is part of Gospel.
// Copyright (C) 2011-2020 <NAME>
//
// Gospel is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gospel is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gospel.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------

import (
	"fmt"
)

// Error codes
var (
	ErrSignallerRetired = fmt.Errorf("Signaller retiered")
	ErrUnknownListener  = fmt.Errorf("Unknown signal listener")
)

// Signal can be any object (intrinsic or custom); it is the responsibility of
// the senders and receivers of signals to handle them accordingly.
type Signal interface{}

// ListenerOp codes
var (
	LISTENER_ADD  = 0
	LISTENER_DROP = 1
)

// ListenerOp represents an operation on the listener list:
type ListenerOp struct {
	ch chan Signal // listener channel
	op int         // 0=add, 1=delete
}

// Signaller manages signals send by senders for multiple listeners.
type Signaller struct {
	inCh   chan Signal          // channel for incoming signals
	outChs map[chan Signal]bool // channels for out-going signals

	cmdCh  chan *ListenerOp // internal channel to synchronize maintenance
	resCh  chan interface{} // channel for command results
	active bool             // is the signaller dispatching signals?
}

// NewSignaller instantiates a new signal manager:
func NewSignaller() *Signaller {
	// create a new instance and initialize it.
	s := &Signaller{
		inCh:   make(chan Signal),
		outChs: make(map[chan Signal]bool),
		cmdCh:  make(chan *ListenerOp),
		resCh:  make(chan interface{}),
		active: true,
	}
	// run the dispatch loop as long as the signaller is active.
	go func() {
		for s.active {
			select {
			case cmd := <-s.cmdCh:
				// handle listener list operation
				switch cmd.op {
				case LISTENER_ADD:
					// create a new listener channel
					out := make(chan Signal)
					s.outChs[out] = true
					s.resCh <- out
				case LISTENER_DROP:
					var err error
					if _, ok := s.outChs[cmd.ch]; !ok {
						err = ErrUnknownListener
					} else {
						delete(s.outChs, cmd.ch)
					}
					s.resCh <- err
				}
			case x := <-s.inCh:
				// dispatch received signals
				for out, active := range s.outChs {
					if active {
						out <- x
					}
				}
			default:
			}
		}
	}()<commit_msg>Removed non-blocking from select in dispatch loop.<commit_after>package concurrent

//----------------------------------------------------------------------
// This file is part of Gospel.
// Copyright (C) 2011-2020 <NAME>
//
// Gospel is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gospel is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gospel.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------

import (
	"fmt"
)

// Error codes
var (
	ErrSignallerRetired = fmt.Errorf("Signaller retiered")
	ErrUnknownListener  = fmt.Errorf("Unknown signal listener")
)

// Signal can be any object (intrinsic or custom); it is the responsibility of
// the senders and receivers of signals to handle them accordingly.
type Signal interface{}

// ListenerOp codes
var (
	LISTENER_ADD  = 0
	LISTENER_DROP = 1
)

// ListenerOp represents an operation on the listener list:
type ListenerOp struct {
	ch chan Signal // listener channel
	op int         // 0=add, 1=delete
}

// Signaller manages signals send by senders for multiple listeners.
type Signaller struct {
	inCh   chan Signal          // channel for incoming signals
	outChs map[chan Signal]bool // channels for out-going signals

	cmdCh  chan *ListenerOp // internal channel to synchronize maintenance
	resCh  chan interface{} // channel for command results
	active bool             // is the signaller dispatching signals?
}

// NewSignaller instantiates a new signal manager:
func NewSignaller() *Signaller {
	// create a new instance and initialize it.
	s := &Signaller{
		inCh:   make(chan Signal),
		outChs: make(map[chan Signal]bool),
		cmdCh:  make(chan *ListenerOp),
		resCh:  make(chan interface{}),
		active: true,
	}
	// run the dispatch loop as long as the signaller is active.
	go func() {
		for s.active {
			select {
			case cmd := <-s.cmdCh:
				// handle listener list operation
				switch cmd.op {
				case LISTENER_ADD:
					// create a new listener channel
					out := make(chan Signal)
					s.outChs[out] = true
					s.resCh <- out
				case LISTENER_DROP:
					var err error
					if _, ok := s.outChs[cmd.ch]; !ok {
						err = ErrUnknownListener
					} else {
						delete(s.outChs, cmd.ch)
					}
					s.resCh <- err
				}
			case x := <-s.inCh:
				// dispatch received signals
				for out, active := range s.outChs {
					if active {
						out <- x
					}
				}
			}
		}
	}()
{'fraction_non_alphanumeric': 0.13821422330945307, 'fraction_numerical': 0.004543071815481391, 'mean_word_length': 2.3376093294460643, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7278965', 'n_tokens_mistral': 1871, 'n_tokens_neox': 1605, 'n_words': 653}