1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-29 16:02:51 -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:
bbedward
2025-11-15 14:41:00 -05:00
parent 20f7d60147
commit 91891a14ed
54 changed files with 8610 additions and 698 deletions

View File

@@ -15,10 +15,8 @@ func NewManager() (*Manager, error) {
func NewManagerWithOptions(exponential bool) (*Manager, error) {
m := &Manager{
subscribers: make(map[string]chan State),
updateSubscribers: make(map[string]chan DeviceUpdate),
stopChan: make(chan struct{}),
exponential: exponential,
stopChan: make(chan struct{}),
exponential: exponential,
}
go m.initLogind()
@@ -360,20 +358,14 @@ func (m *Manager) broadcastDeviceUpdate(deviceID string) {
update := DeviceUpdate{Device: *targetDevice}
m.subMutex.RLock()
defer m.subMutex.RUnlock()
if len(m.updateSubscribers) == 0 {
log.Debugf("No update subscribers for device: %s", deviceID)
return
}
log.Debugf("Broadcasting device update: %s at %d%%", deviceID, targetDevice.CurrentPercent)
for _, ch := range m.updateSubscribers {
m.updateSubscribers.Range(func(key, value interface{}) bool {
ch := value.(chan DeviceUpdate)
select {
case ch <- update:
default:
}
}
return true
})
}

View File

@@ -41,13 +41,11 @@ func TestManager_SetBrightness_LogindSuccess(t *testing.T) {
}
m := &Manager{
logindBackend: mockLogind,
sysfsBackend: sysfs,
logindReady: true,
sysfsReady: true,
subscribers: make(map[string]chan State),
updateSubscribers: make(map[string]chan DeviceUpdate),
stopChan: make(chan struct{}),
logindBackend: mockLogind,
sysfsBackend: sysfs,
logindReady: true,
sysfsReady: true,
stopChan: make(chan struct{}),
}
m.state = State{
@@ -115,13 +113,11 @@ func TestManager_SetBrightness_LogindFailsFallbackToSysfs(t *testing.T) {
}
m := &Manager{
logindBackend: mockLogind,
sysfsBackend: sysfs,
logindReady: true,
sysfsReady: true,
subscribers: make(map[string]chan State),
updateSubscribers: make(map[string]chan DeviceUpdate),
stopChan: make(chan struct{}),
logindBackend: mockLogind,
sysfsBackend: sysfs,
logindReady: true,
sysfsReady: true,
stopChan: make(chan struct{}),
}
m.state = State{
@@ -185,13 +181,11 @@ func TestManager_SetBrightness_NoLogind(t *testing.T) {
}
m := &Manager{
logindBackend: nil,
sysfsBackend: sysfs,
logindReady: false,
sysfsReady: true,
subscribers: make(map[string]chan State),
updateSubscribers: make(map[string]chan DeviceUpdate),
stopChan: make(chan struct{}),
logindBackend: nil,
sysfsBackend: sysfs,
logindReady: false,
sysfsReady: true,
stopChan: make(chan struct{}),
}
m.state = State{
@@ -250,13 +244,11 @@ func TestManager_SetBrightness_LEDWithLogind(t *testing.T) {
}
m := &Manager{
logindBackend: mockLogind,
sysfsBackend: sysfs,
logindReady: true,
sysfsReady: true,
subscribers: make(map[string]chan State),
updateSubscribers: make(map[string]chan DeviceUpdate),
stopChan: make(chan struct{}),
logindBackend: mockLogind,
sysfsBackend: sysfs,
logindReady: true,
sysfsReady: true,
stopChan: make(chan struct{}),
}
m.state = State{

View File

@@ -51,9 +51,8 @@ type Manager struct {
stateMutex sync.RWMutex
state State
subscribers map[string]chan State
updateSubscribers map[string]chan DeviceUpdate
subMutex sync.RWMutex
subscribers sync.Map
updateSubscribers sync.Map
broadcastMutex sync.Mutex
broadcastTimer *time.Timer
@@ -121,36 +120,31 @@ type SetBrightnessParams struct {
func (m *Manager) Subscribe(id string) chan State {
ch := make(chan State, 16)
m.subMutex.Lock()
m.subscribers[id] = ch
m.subMutex.Unlock()
m.subscribers.Store(id, ch)
return ch
}
func (m *Manager) Unsubscribe(id string) {
m.subMutex.Lock()
if ch, ok := m.subscribers[id]; ok {
close(ch)
delete(m.subscribers, id)
if val, ok := m.subscribers.LoadAndDelete(id); ok {
close(val.(chan State))
}
m.subMutex.Unlock()
}
func (m *Manager) SubscribeUpdates(id string) chan DeviceUpdate {
ch := make(chan DeviceUpdate, 16)
m.subMutex.Lock()
m.updateSubscribers[id] = ch
m.subMutex.Unlock()
m.updateSubscribers.Store(id, ch)
return ch
}
func (m *Manager) UnsubscribeUpdates(id string) {
m.subMutex.Lock()
if ch, ok := m.updateSubscribers[id]; ok {
close(ch)
delete(m.updateSubscribers, id)
if val, ok := m.updateSubscribers.LoadAndDelete(id); ok {
close(val.(chan DeviceUpdate))
}
m.subMutex.Unlock()
}
func (m *Manager) NotifySubscribers() {
@@ -158,15 +152,14 @@ func (m *Manager) NotifySubscribers() {
state := m.state
m.stateMutex.RUnlock()
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) GetState() State {
@@ -178,16 +171,18 @@ func (m *Manager) GetState() State {
func (m *Manager) Close() {
close(m.stopChan)
m.subMutex.Lock()
for _, ch := range m.subscribers {
m.subscribers.Range(func(key, value interface{}) bool {
ch := value.(chan State)
close(ch)
}
m.subscribers = make(map[string]chan State)
for _, ch := range m.updateSubscribers {
m.subscribers.Delete(key)
return true
})
m.updateSubscribers.Range(func(key, value interface{}) bool {
ch := value.(chan DeviceUpdate)
close(ch)
}
m.updateSubscribers = make(map[string]chan DeviceUpdate)
m.subMutex.Unlock()
m.updateSubscribers.Delete(key)
return true
})
if m.logindBackend != nil {
m.logindBackend.Close()