Paul Vincent Craven
All Rights Reserved
Processes are what most people think of when they are referring to a running program. Processes can have smaller sub-programs called threads. Threads each run independently of each other, concurrently. This allows the program to do multiple things at the same time. The threads share the same memory space as the process that created them, enabling them to use the same data. Not all operating systems support threads, but most modern ones do. Using threads simplified the development of the power management software quite a bit.
There are two important threads which execute all the time while the program is running. These threads run alongside the main process, which handles most of the program's functionality. The two threads control live GPS data gathering (GPSThread) and collecting information received by the radio modems (CommThread). These two threads are started in the TPMS_App constructor that is called when the main process is created.
When the program shuts down, the program sets a previously created signal that tells the threads to shut down. The threads, when idle, are stopped at the operating system function called WaitForMultipleObjects( ). This command allows the task to pause until something important happens, and not take up a lot of CPU time while waiting. The command is given an array that contains handles to the several events we are waiting for. This allows the thread to sit idle until the COM port signals an event, or the program signals a shutdown event. When the thread shuts down it sets yet another event object letting the main process know that it is finished. If this event is not set within a certain time period, the main process will kill the thread assuming that it has gone bad. We can't simply kill the thread under normal circumstances as the thread needs to clean up after itself.
Both the GPSThread and CommThread are quite similar in code and operation. They open pipes created by the GPS and Communications services running under NT. These NT services are much like daemons in the UNIX world. In this case, they are small programs that take data from a COM port and redirect it to several named pipes. A process on any networked computer can open these pipes and access the COM ports remotely. Since Windows NT's security is much more robust than UNIX's security, these pipe operations require some in-depth knowledge of the Windows NT™'s security system. Another user cannot open a pipe without the security system access to the pipe. Information on how to do the security descriptors was gleaned from the Win32 System Services book.
One of the nice things about multi-threaded systems is that you can assign the threads different priorities. So, the communications threads and services are given a high priority, since they obtain data in real-time. I tried giving the threads real-time priority, but this priority pre-empts system actions which I needed when working with the COM port. By dropping the thread priority to just under real-time we have fairly reliable radio communications.
Without the use of threads, this project would have been much more difficult. We would have needed to create our own code which would be able to handle multiple tasks at the same time. One of the simpler ways of doing this without threads is using CPU interrupts. The drawback of this method is that the program becomes directly tied to the hardware, and moving it between different systems is more difficult. When using modern operating systems like UNIX and Windows NT™, using interrupts is strongly discouraged because the program will be performing actions that the operating system was designed to do. Any other method handling several tasks at once would have been very difficult. This was one of the reasons that we did not program under MS-DOS or Windows 3.1, because they do not support multi-threading well.