mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-26 22:42:50 -05:00
core/wayland: thread-safety meta fixes + cleanups + hypr workaround
- fork go-wayland/client and modify to make it thread-safe internally - use sync.Map and atomic values in many places to cut down on mutex boilerplate - do not create extworkspace client unless explicitly requested
This commit is contained in:
@@ -47,10 +47,9 @@ func TestHandleRequest(t *testing.T) {
|
||||
mockDevice.EXPECT().ReadOne().Return(nil, errors.New("test")).Maybe()
|
||||
|
||||
m := &Manager{
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: true},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: true},
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
conn := newMockNetConn()
|
||||
@@ -77,10 +76,9 @@ func TestHandleRequest(t *testing.T) {
|
||||
mockDevice.EXPECT().ReadOne().Return(nil, errors.New("test")).Maybe()
|
||||
|
||||
m := &Manager{
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
conn := newMockNetConn()
|
||||
@@ -107,10 +105,9 @@ func TestHandleGetState(t *testing.T) {
|
||||
mockDevice.EXPECT().ReadOne().Return(nil, errors.New("test")).Maybe()
|
||||
|
||||
m := &Manager{
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
conn := newMockNetConn()
|
||||
|
||||
@@ -35,8 +35,7 @@ type Manager struct {
|
||||
monitoredPaths map[string]bool
|
||||
state State
|
||||
stateMutex sync.RWMutex
|
||||
subscribers map[string]chan State
|
||||
subMutex sync.RWMutex
|
||||
subscribers sync.Map
|
||||
closeChan chan struct{}
|
||||
closeOnce sync.Once
|
||||
watcher *fsnotify.Watcher
|
||||
@@ -69,9 +68,9 @@ func NewManager() (*Manager, error) {
|
||||
devices: devices,
|
||||
monitoredPaths: monitoredPaths,
|
||||
state: State{Available: true, CapsLock: initialCapsLock},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
watcher: watcher,
|
||||
|
||||
closeChan: make(chan struct{}),
|
||||
watcher: watcher,
|
||||
}
|
||||
|
||||
for i, device := range devices {
|
||||
@@ -332,37 +331,26 @@ func (m *Manager) GetState() State {
|
||||
}
|
||||
|
||||
func (m *Manager) Subscribe(id string) chan State {
|
||||
m.subMutex.Lock()
|
||||
defer m.subMutex.Unlock()
|
||||
|
||||
ch := make(chan State, 16)
|
||||
m.subscribers[id] = ch
|
||||
m.subscribers.Store(id, ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
func (m *Manager) Unsubscribe(id string) {
|
||||
m.subMutex.Lock()
|
||||
defer m.subMutex.Unlock()
|
||||
|
||||
ch, ok := m.subscribers[id]
|
||||
if !ok {
|
||||
return
|
||||
if val, ok := m.subscribers.LoadAndDelete(id); ok {
|
||||
close(val.(chan State))
|
||||
}
|
||||
|
||||
close(ch)
|
||||
delete(m.subscribers, id)
|
||||
}
|
||||
|
||||
func (m *Manager) notifySubscribers(state State) {
|
||||
m.subMutex.RLock()
|
||||
defer m.subMutex.RUnlock()
|
||||
|
||||
for _, ch := range m.subscribers {
|
||||
m.subscribers.Range(func(key, value interface{}) bool {
|
||||
ch := value.(chan State)
|
||||
select {
|
||||
case ch <- state:
|
||||
default:
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Manager) Close() {
|
||||
@@ -384,12 +372,12 @@ func (m *Manager) Close() {
|
||||
}
|
||||
m.devicesMutex.Unlock()
|
||||
|
||||
m.subMutex.Lock()
|
||||
for id, ch := range m.subscribers {
|
||||
m.subscribers.Range(func(key, value interface{}) bool {
|
||||
ch := value.(chan State)
|
||||
close(ch)
|
||||
delete(m.subscribers, id)
|
||||
}
|
||||
m.subMutex.Unlock()
|
||||
m.subscribers.Delete(key)
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,9 @@ func TestManager_Creation(t *testing.T) {
|
||||
mockDevice.EXPECT().ReadOne().Return(nil, errors.New("test")).Maybe()
|
||||
|
||||
m := &Manager{
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
assert.NotNil(t, m)
|
||||
@@ -32,10 +31,9 @@ func TestManager_Creation(t *testing.T) {
|
||||
mockDevice.EXPECT().ReadOne().Return(nil, errors.New("test")).Maybe()
|
||||
|
||||
m := &Manager{
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: true},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: true},
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
assert.NotNil(t, m)
|
||||
@@ -52,7 +50,6 @@ func TestManager_GetState(t *testing.T) {
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
monitoredPaths: make(map[string]bool),
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
@@ -69,13 +66,17 @@ func TestManager_Subscribe(t *testing.T) {
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
monitoredPaths: make(map[string]bool),
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
ch := m.Subscribe("test-client")
|
||||
assert.NotNil(t, ch)
|
||||
assert.Len(t, m.subscribers, 1)
|
||||
count := 0
|
||||
m.subscribers.Range(func(key, value interface{}) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, 1, count)
|
||||
}
|
||||
|
||||
func TestManager_Unsubscribe(t *testing.T) {
|
||||
@@ -86,15 +87,24 @@ func TestManager_Unsubscribe(t *testing.T) {
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
monitoredPaths: make(map[string]bool),
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
ch := m.Subscribe("test-client")
|
||||
assert.Len(t, m.subscribers, 1)
|
||||
count := 0
|
||||
m.subscribers.Range(func(key, value interface{}) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, 1, count)
|
||||
|
||||
m.Unsubscribe("test-client")
|
||||
assert.Len(t, m.subscribers, 0)
|
||||
count = 0
|
||||
m.subscribers.Range(func(key, value interface{}) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, 0, count)
|
||||
|
||||
select {
|
||||
case _, ok := <-ch:
|
||||
@@ -112,7 +122,6 @@ func TestManager_UpdateCapsLock(t *testing.T) {
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
monitoredPaths: make(map[string]bool),
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
@@ -148,7 +157,6 @@ func TestManager_Close(t *testing.T) {
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
monitoredPaths: make(map[string]bool),
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
@@ -171,7 +179,12 @@ func TestManager_Close(t *testing.T) {
|
||||
t.Error("channel 2 should be closed")
|
||||
}
|
||||
|
||||
assert.Len(t, m.subscribers, 0)
|
||||
count := 0
|
||||
m.subscribers.Range(func(key, value interface{}) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, 0, count)
|
||||
|
||||
m.Close()
|
||||
}
|
||||
@@ -230,10 +243,9 @@ func TestManager_MonitorDevice(t *testing.T) {
|
||||
mockDevice.EXPECT().Close().Return(nil).Maybe()
|
||||
|
||||
m := &Manager{
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
state: State{Available: true, CapsLock: false},
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
ch := m.Subscribe("test")
|
||||
@@ -276,7 +288,6 @@ func TestNotifySubscribers(t *testing.T) {
|
||||
devices: []EvdevDevice{mockDevice},
|
||||
monitoredPaths: make(map[string]bool),
|
||||
state: State{Available: true, CapsLock: false},
|
||||
subscribers: make(map[string]chan State),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user