diff --git a/filter/filter.go b/filter/filter.go
new file mode 100644
index 0000000000000000000000000000000000000000..9817d5782fadb58c9566570d5024e0099fefa1ec
--- /dev/null
+++ b/filter/filter.go
@@ -0,0 +1,70 @@
+package filter
+
+import "reflect"
+
+type Filter interface {
+	Compare(Filter) bool
+	Trigger(data interface{})
+}
+
+type FilterEvent struct {
+	filter Filter
+	data   interface{}
+}
+
+type Filters struct {
+	id       int
+	watchers map[int]Filter
+	ch       chan FilterEvent
+
+	quit chan struct{}
+}
+
+func New() *Filters {
+	return &Filters{
+		ch:       make(chan FilterEvent),
+		watchers: make(map[int]Filter),
+		quit:     make(chan struct{}),
+	}
+}
+
+func (self *Filters) Start() {
+	go self.loop()
+}
+
+func (self *Filters) Stop() {
+	close(self.quit)
+}
+
+func (self *Filters) Notify(filter Filter, data interface{}) {
+	self.ch <- FilterEvent{filter, data}
+}
+
+func (self *Filters) Install(watcher Filter) int {
+	self.watchers[self.id] = watcher
+	self.id++
+
+	return self.id - 1
+}
+
+func (self *Filters) Uninstall(id int) {
+	delete(self.watchers, id)
+}
+
+func (self *Filters) loop() {
+out:
+	for {
+		select {
+		case <-self.quit:
+			break out
+		case event := <-self.ch:
+			for _, watcher := range self.watchers {
+				if reflect.TypeOf(watcher) == reflect.TypeOf(event.filter) {
+					if watcher.Compare(event.filter) {
+						watcher.Trigger(event.data)
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/filter/filter_test.go b/filter/filter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..815deb63af1934ddc29f80db464249e2cc4078c8
--- /dev/null
+++ b/filter/filter_test.go
@@ -0,0 +1,34 @@
+package filter
+
+import "testing"
+
+func TestFilters(t *testing.T) {
+	var success bool
+	var failure bool
+
+	fm := New()
+	fm.Start()
+	fm.Install(Generic{
+		Str1: "hello",
+		Fn: func(data interface{}) {
+			success = data.(bool)
+		},
+	})
+	fm.Install(Generic{
+		Str1: "hello1",
+		Str2: "hello",
+		Fn: func(data interface{}) {
+			failure = true
+		},
+	})
+	fm.Notify(Generic{Str1: "hello"}, true)
+	fm.Stop()
+
+	if !success {
+		t.Error("expected 'hello' to be posted")
+	}
+
+	if failure {
+		t.Error("hello1 was triggered")
+	}
+}
diff --git a/filter/generic_filter.go b/filter/generic_filter.go
new file mode 100644
index 0000000000000000000000000000000000000000..b04b4801e773a10059a936dc88defed48658b920
--- /dev/null
+++ b/filter/generic_filter.go
@@ -0,0 +1,22 @@
+package filter
+
+type Generic struct {
+	Str1, Str2, Str3 string
+
+	Fn func(data interface{})
+}
+
+func (self Generic) Compare(f Filter) bool {
+	filter := f.(Generic)
+	if (len(self.Str1) == 0 || filter.Str1 == self.Str1) &&
+		(len(self.Str2) == 0 || filter.Str2 == self.Str2) &&
+		(len(self.Str3) == 0 || filter.Str3 == self.Str3) {
+		return true
+	}
+
+	return false
+}
+
+func (self Generic) Trigger(data interface{}) {
+	self.Fn(data)
+}