I've never written a multithreaded application that shares variables across threads but now I've been asked to write a server control application and have found my efforts being thwarted at every turn by mysterious timing-specific bugs which I've traced to threads trying to work with one memory location all at once.
Specifically, I have a singly linked list that describes the clients connected to the server. Each of these client structs also has a singly linked list containing the parameters of the client.
I also have at least three threads. There is the GUI thread, responsible for pumping messages. There is the server thread, which verifies client connections and creates worker threads. And there is one or more worker threads (one thread per client).
The GUI thread does not modify the client list, but it does read it and the parameters of each client in order to display them in a window.
The server thread adds and removes clients from the client list. When signalled to terminate, it signals each worker thread and gives them three seconds to terminate gracefully. If by then they are still running they are killed and the client's parameter list is freed by the server.
The worker thread adds to, removes from and modifies the client parameters list.
To combat the problems that I'm encountering, I've given thought to creating a critical section object and getting each thread to enter it whenever they want to do anything involving the client list or any of the parameter lists. While any one thread is reading or modifying the lists the other threads will have to wait.
But... should this one CS object apply to both the client list and all the parameter lists, or should I add a CS object handle to the client's struct and have a CS object per client for the parameter list?
Safe multithreading is sooo tricky...