File: signal.go

package info (click to toggle)
go-dlib 5.6.0.9%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,212 kB
  • sloc: ansic: 4,664; xml: 1,456; makefile: 20; sh: 15
file content (124 lines) | stat: -rw-r--r-- 2,129 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package dbusutil

import (
	"sync"

	"github.com/godbus/dbus"
)

type SignalHandlerId int

type SignalLoop struct {
	conn          *dbus.Conn
	bufSize       int
	ch            chan *dbus.Signal
	mu            sync.Mutex
	handlers      map[SignalHandlerId]SignalHandler
	nextHandlerId SignalHandlerId
}

func NewSignalLoop(conn *dbus.Conn, bufSize int) *SignalLoop {
	pl := &SignalLoop{
		conn:          conn,
		bufSize:       bufSize,
		handlers:      make(map[SignalHandlerId]SignalHandler),
		nextHandlerId: 1,
	}
	return pl
}

func (sl *SignalLoop) Conn() *dbus.Conn {
	return sl.conn
}

func (sl *SignalLoop) Start() {
	ch := make(chan *dbus.Signal, sl.bufSize)
	sl.conn.Signal(ch)
	sl.ch = ch

	go func() {
		for signal := range ch {
			sl.process(signal)
		}
	}()
}

func (sl *SignalLoop) process(signal *dbus.Signal) {
	var cbs []SignalHandlerFunc
	sl.mu.Lock()
	for _, handler := range sl.handlers {
		if handler.rule.match(signal) {
			if handler.cb != nil {
				cbs = append(cbs, handler.cb)
			}
		}
	}
	sl.mu.Unlock()

	for _, cb := range cbs {
		cb(signal)
	}
}

func (sl *SignalLoop) Stop() {
	sl.conn.RemoveSignal(sl.ch)
	close(sl.ch)
}

func (sl *SignalLoop) AddHandler(rule *SignalRule, cb SignalHandlerFunc) SignalHandlerId {
	sl.mu.Lock()
	defer sl.mu.Unlock()

	id := sl.nextHandlerId
	sl.nextHandlerId++

	sl.handlers[id] = SignalHandler{
		rule: rule,
		cb:   cb,
	}
	return id
}

func (sl *SignalLoop) RemoveHandler(id SignalHandlerId) {
	if id < 0 {
		return
	}
	sl.mu.Lock()
	delete(sl.handlers, id)
	sl.mu.Unlock()
}

type SignalHandler struct {
	rule *SignalRule
	cb   SignalHandlerFunc
}

type SignalRule struct {
	Sender string
	Path   dbus.ObjectPath
	Name   string
}

func (m *SignalRule) match(sig *dbus.Signal) bool {
	if m == nil {
		return true
	}

	if m.Sender != "" && m.Sender != sig.Sender {
		// define sender, but not equal
		return false
	}

	if m.Path != "" && m.Path != sig.Path {
		// define path, but not equal
		return false
	}

	if m.Name != "" && m.Name != sig.Name {
		// define name, but not equal
		return false
	}
	return true
}

type SignalHandlerFunc func(sig *dbus.Signal)