I want to provide some library functionality and a reference application, which will run on a fully-featured, POSIX-compliant platform. The app and library will need bi-directional serial port communication, user input from keyboard, user display to text console, and probably timers.
I also want to provide a porting guide so that users of the library can port it (with or without the reference application) to their own platforms, which may be POSIX-compliant or not, and may or may not support multiple threads.
I am taking care of the main platform portability issue by writing portable code for everything as far as possible and providing a self-contained porting layer for platform-specific code. In my porting guide I will tell the user to replace the porting layer functions with implementations for their own platform.
However as far as the threading model goes, I have two choices:
- implement my reference application as a very simple single-threaded program (main loop would poll keyboard, poll serial port, check timer status, and call library functions as needed)
- use the pthreads library and have a main app thread with separate threads for user input, serial port receive, and timer expiry, all of which would post messages to my main app thread for processing.
Whichever model I choose I will have to explain to users how to port it to a platform which may be using a different model.
Even if I use a single-threaded implementation for the reference app, I will make sure any library functionality is re-entrant (or put big caveats around it if that isn’t possible).
What considerations should I bear in mind, in my implementation and the porting guide? What information would you want if you were porting some multi-threaded code to a single threaded system, or vice versa?
5
As with all multi-threaded development, the introduction of multiple threads means the following need to be managed:
- Managing concurrent access to shared resources to ensure consistency
- Design of locking strategy to prevent deadlocks
- Managing of resources that are thread locked. (e.g. can you read your serial port from multiple threads at the same time?)
- Shutdown / Error handling. This can introduce many unexpected code paths, do resources always get properly released, can deadlock occur?
I’m not seeing a particular problem with doing all this on a single thread, as keyboard and serial can be made essentially non-blocking. It all comes down to your library, and how long do the function calls in your library take to complete?
1
There is no reason to introduce multi-threading just because you need to react to multiple input sources. You can wait for the keyboard, serial port, and timer via the POSIX select system call. If you are using C++, then you could use the ACE library Reactor.
1