0

I am combining GTK+, WinAPI and Winsock to create a graphical client-server interface, a waiting room. nUsers is a variable that determines the number of clients successfully connected.

Within a Windows thread, created by:

CreateThread(NULL, 0, action_to_users, NULL, 0, NULL);

I use the do-nothing while loop so that it freezes until a user connects.

while(!nUsers);

However, it never passes through the loop as if nUsers never becomes > 0.nUsers counts the number of clients connected properly, as I constantly monitor it and use it in a variety of different functions. To prove my point, something even stranger happens. If I make the loop

while(!nUsers) { printf("(%i)\n", nUsers); }

To spam the console with text printed out (doesn't matter what text as long as it is not an empty string) it works as intended.


What could be possibly going on here...

liberforce
  • 11,189
  • 37
  • 48
Corelation
  • 79
  • 7
  • Mark `nUsers` `volatile`. – orhtej2 Sep 17 '17 at 09:45
  • @orhtej2 You are genuis. It worked.. but why.. – Corelation Sep 17 '17 at 09:48
  • I mean I am a qualified C programmer, I know where to use volatile, but now it didn't look like the situation I know of – Corelation Sep 17 '17 at 09:48
  • 'while(!nUsers);' a room heater. Windows has plenty synchro options that require less A/C, (and does not completely waste a core). – Martin James Sep 17 '17 at 10:00
  • @MartinJames what do you mean? I should admit that I am new to windows threading. I rely on the function reference.. and I have entirely read it. – Corelation Sep 17 '17 at 10:05
  • @Corelation You 'do nothing' loop does something. It uses 100% of a complete execution core, and it uses up inter-core memory bandwidth while 'doing nothing'. Besides wasting CPU/memory resources that would be better used 'doing somethig useful', is uses a lot of power and you may well hear your cooling fans speed up a notch, in the manner of a fan heater:( Perhpas not unsurprisingly, your OS provides synchronization mechanisms to allow efficient inter-thread signaling without CPU-looping. You shoud search MSDN/Google for 'events and 'semaphores'. – Martin James Sep 17 '17 at 11:37
  • Incidentally. while it worked 'for you' in this case, 'volatile' is not guaranteed effective even for the (bad) polling operation/s you are doing. Google/MSDN for 'CriticalSection'. – Martin James Sep 17 '17 at 11:39

1 Answers1

1

Regarding the original problem: compiler is free to cache the value of nUsers since the variable is not modified within this loop. Marking the variable volatile prevents this optimization as described here.

Regarding what you're trying to achieve - it looks like a producer-consumer pattern, where the thread(s) handling the sockets are producers and your GUI thread is a consumer. You can slow down your consumer loop to only loop when new data is available using:

  • semaphores as showcased here - producer thread increments count on semaphore while consumer decrements it upon dequeing work item.
  • Events like here - producer thread signals an event while consumer thread waits for it to become signalled. You can queue the work in some queue to allow more than one item being processed.
  • Condition variables (XP+) - here a variable you're waiting for gets signalled upon meeting certain criteria.
orhtej2
  • 2,133
  • 3
  • 16
  • 26
  • 1
    'where the thread(s) handling the sockets are producers and your GUI thread is a consumer' - if that is the case, then neither the OP's original 'loop doing nothing' or our suggestions of events'semas/condvar waits are useful - one cannot wait in a GUI event handler. The go-to API for comms in that case is PostMessage(), or possibly PostThreadMessage(). – Martin James Sep 17 '17 at 15:40