Notes for the Serial Board API


Event Callback issues

     As is discussed in the documentation for the ser_sr24_set_event_handler() function, there are a few different types of event-notification mechanisms that can be used. Type 1 is probably the most common mechanism used, the callback mechanism, where the API calls one of your functions every time a hardware event occurs on the serial I/O board. Because the serial board API is multithreaded, (multithreaded means that a task in the API is executing in parallel with your main application, or virtually simultaneously) and this callback is made from the API's own thread, it could cause problems for some programs. One example of this is that Visual Basic applications cannot handle multithreaded callbacks. This isn't terribly surprising because of all that goes on behind the programmer's back in Visual Basic. This is why the included Visual Basic class module for the API internally uses the Type 3 event-notification method, which makes callbacks in a thread-safe way.

If you are programming in C or C++, there should be no problems caused directly by the language as there are in Visual Basic, but there are still several problems that you could run into just from what you do in your code. For example, if your event-handling callback and your main program both write to the same variable or data structure, then there is always a possibility that both could write to the same data structure at almost the same time. While this isn't a problem in itself, in many cases it could mean, for instance, that the value recently written by the main program was unintentionally overwritten by the callback. As an example, consider what might happen if both the main program and the callback try to add 10 to a variable at the same time (Let's call the variable X). If everything works out right, X will be 20 greater when both are done adding. However, this situation could occur:

  1. Main program reads current value of X (say 100) into temporary storage.
  2. Main program adds 10 to value in temporary storage (now 110).

    --- Kernel briefly interrupts the main program and switches to the callback thread ---

  3. Callback reads current value of X (100) into its own temporary storage.
  4. Callback adds 10 to value in its own temporary storage (now 110)
  5. Callback writes the value in its own temporary storage (110) back into X.

    --- Kernel switches back to main program ---

  6. Main program writes the value in temporary storage (110) back into X.
  7. The final value of X is now 110, when it should have been 120.
There are many more possible types of problems that can be introduced in a multithreaded program. All of the possible problems can't be dealt with here, so if you will be dealing with possible problem points, you should seek out a book or a reference site for multithreaded programming.

Possible Solutions

First, it should be pointed out that not everything done in a callback is necessarily going to cause problems. For example, if the callback is the only function writing or incrementing a variable, and the main program only reads it, there should not be a problem.

In situations where there is a definite problem, there are some definite possible solutions. First, one of the most common solutions are thread synchronization solutions such as mutexes (available on both Linux and Windows). A mutex is used to prevent two threads (such as the main program and the callback) from accessing and modifying the same variable or structure at the same time. This prevents situations like the example described above. Another possible solution is to create a pipe (CreatePipe() on Windows or pipe() on Linux) for communication between the callback and the main program. Using this technique, the callback can write a message into the pipe, and the main program can read the message from the pipe whenever it has a chance. Also, on the Windows platform, you might want to look into event-notification Types 2 or 3. But once again remember, in many applications there will be very few or no problems caused by multithreading issues in the callback.

Event Callbacks and Setting the Event Handler

There is one limitation on what you can do inside your event-handler callback. This limitation is that you should never make a call to the ser_sr24_set_event_handler() function from inside your callback function. The ser_sr24_set_event_handler() function is not designed to be called from an event callback. The inner details of why this should not be done won't be discussed, but basically what happens is that the callback thread is waiting for itself to terminate, resulting in a deadlock. This would probably not even be an issue for a vast majority of applications, but it is mentioned here for completeness. The better alternative to disabling the event-handler would be to simply ignore subsequent events in the callback.

Troubleshooting

During testing, we had a problem with one of our computers, a Pentium 133 running Windows 95. The test program we were using was set up to constantly poll an analog channel. The program would intermittently hang, and this was eventually traced back to a problem writing to the serial port. The exact reason for this problem was never determined, but we ultimately solved the problem by replacing the serial port card in the computer. So, if you run across strange problems which just don't seem to make sense, you may want to replace the serial port card in your computer. If your serial ports are built onto your motherboard and you are experiencing problems, you may want to try a plugin card instead.


Back to Contents Winford Engineering (2000)