I'm trying to identify or understand an appropriate technique, idiom, whatever for a specific concurrent programming problem I'm having.
For simplicity's sake, assume I have a real-time graphical user interface (UI) that is redrawn on screen at 10Hz always and forever.
I would like to display a "Busy" indicator on this UI whenever at least one instance of a group of different threads are running, and I want that indicator to stop displaying when precisely 0 of these threads are running. These threads could feasibly be started and stopped at any time as long as the UI is up.
I'm currently implementing this in golang (with relevant snippets further below). But in general, I'm solving this as follows:
Keep R+W access to a counter int
waitCount
(number of threads requesting we indicate "Busy") protected via mutexwaitLock
.-
function
drawStatus()
: Redraw the entire UI (occurs every 100ms):- acquire mutex
waitLock
- if int
waitCount
> 0:- draw the "Busy" indicator
- release mutex
waitLock
- acquire mutex
-
function
startWait()
: When a thread needs to indicate busy:- acquire mutex
waitLock
- increment int
waitCount
- release mutex
waitLock
- acquire mutex
-
function
stopWait()
: When a thread no longer needs to indicate busy:- acquire mutex
waitLock
- decrement int
waitCount
- release mutex
waitLock
- acquire mutex
To me, it feels like I'm not taking full advantage of golang's concurrency facilities and resorting to the mutexes I'm familiar with. But even still, there is a bug in this code wherein the "Busy" indicator gets dismissed prematurely.
I'm honestly not looking for anyone to help identify that bug, but rather I'm trying to convey the specific logic I'm interested in. Is there a more idiomatic golang way to approach this problem? Or is there a more general programming pattern that I should investigate? Does this technique I'm using have any particular name? And suggestions or pointers on doing this properly would be great. Thanks.
And here's some doctor'd up snippets that implement the above logic
var WaitCycle = [...]rune{'