2015-01-07 08:59:35 +08:00
|
|
|
package pfs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2015-01-07 21:24:56 +08:00
|
|
|
type PFS struct {
|
2015-01-08 08:35:15 +08:00
|
|
|
// listeners are listener functions.
|
|
|
|
listeners []reflect.Value
|
|
|
|
lmu *sync.RWMutex
|
|
|
|
|
|
|
|
filters []reflect.Value
|
|
|
|
fmu *sync.RWMutex
|
2015-01-07 08:59:35 +08:00
|
|
|
}
|
|
|
|
|
2015-01-07 21:24:56 +08:00
|
|
|
func New() *PFS {
|
|
|
|
return &PFS{
|
2015-01-08 08:35:15 +08:00
|
|
|
listeners: make([]reflect.Value, 0),
|
|
|
|
lmu: &sync.RWMutex{},
|
|
|
|
filters: make([]reflect.Value, 0),
|
|
|
|
fmu: &sync.RWMutex{},
|
2015-01-07 21:24:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PFS) Pub(args ...interface{}) {
|
2015-01-08 08:35:15 +08:00
|
|
|
p.lmu.Lock()
|
|
|
|
defer p.lmu.Unlock()
|
2015-01-07 21:24:56 +08:00
|
|
|
|
|
|
|
arguments := make([]reflect.Value, 0, len(args))
|
|
|
|
for _, v := range args {
|
|
|
|
arguments = append(arguments, reflect.ValueOf(v))
|
|
|
|
}
|
|
|
|
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
|
2015-01-08 08:35:15 +08:00
|
|
|
wg.Add(len(p.listeners))
|
|
|
|
for _, fn := range p.listeners {
|
2015-01-07 21:24:56 +08:00
|
|
|
go func(f reflect.Value) {
|
|
|
|
defer wg.Done()
|
|
|
|
f.Call(arguments)
|
|
|
|
}(fn)
|
|
|
|
}
|
2015-01-07 08:59:35 +08:00
|
|
|
|
2015-01-07 21:24:56 +08:00
|
|
|
wg.Wait()
|
2015-01-07 08:59:35 +08:00
|
|
|
}
|
|
|
|
|
2015-01-07 21:24:56 +08:00
|
|
|
func (p *PFS) Sub(f interface{}) error {
|
2015-01-08 08:35:15 +08:00
|
|
|
p.lmu.Lock()
|
|
|
|
defer p.lmu.Unlock()
|
2015-01-07 08:59:35 +08:00
|
|
|
|
|
|
|
fn := reflect.ValueOf(f)
|
|
|
|
|
|
|
|
if reflect.Func != fn.Kind() {
|
|
|
|
return fmt.Errorf("Argument should be a function")
|
|
|
|
}
|
|
|
|
|
2015-01-08 08:35:15 +08:00
|
|
|
if len(p.listeners) != 0 {
|
2015-01-07 08:59:35 +08:00
|
|
|
// TODO: check fn arguments
|
|
|
|
}
|
|
|
|
|
2015-01-08 09:04:30 +08:00
|
|
|
p.fmu.RLock()
|
|
|
|
if len(p.filters) != 0 {
|
|
|
|
// TODO: check fn arguments
|
|
|
|
}
|
|
|
|
p.fmu.RUnlock()
|
|
|
|
|
2015-01-08 08:35:15 +08:00
|
|
|
p.listeners = append(p.listeners, fn)
|
2015-01-07 08:59:35 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-01-07 21:24:56 +08:00
|
|
|
func (p *PFS) Off() {
|
2015-01-07 08:59:35 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-01-08 08:35:15 +08:00
|
|
|
func (p *PFS) Filter(f interface{}) error {
|
2015-01-08 09:04:30 +08:00
|
|
|
p.fmu.Lock()
|
|
|
|
defer p.fmu.Unlock()
|
|
|
|
|
|
|
|
// TODO: DRY
|
|
|
|
fn := reflect.ValueOf(f)
|
|
|
|
|
|
|
|
if reflect.Func != fn.Kind() {
|
|
|
|
return fmt.Errorf("Argument should be a function")
|
|
|
|
}
|
|
|
|
|
|
|
|
p.lmu.RLock()
|
|
|
|
if len(p.listeners) != 0 {
|
|
|
|
// TODO: check fn arguments
|
|
|
|
}
|
|
|
|
p.lmu.RUnlock()
|
|
|
|
|
|
|
|
if len(p.filters) != 0 {
|
|
|
|
// TODO: check fn arguments
|
|
|
|
}
|
|
|
|
|
|
|
|
p.filters = append(p.filters, fn)
|
2015-01-07 08:59:35 +08:00
|
|
|
|
2015-01-08 08:35:15 +08:00
|
|
|
return nil
|
2015-01-07 08:59:35 +08:00
|
|
|
}
|