DM1 Threads Library

Introduction

The DM1 Thread Library is part of the DM1 project. This library was born out of my need to have a portable C++ Thread library that would be simple to use, and would provide all the necessary Threads functionality I required for the DM1 project. Initially, this library was in C, but when I decided to re-write DM1 in C++, I ported the library to C++. During the port, I enhanced the functionality of the Threads library.

Goals of the DM1 Threads library

The DM1 Threads library aims to be small. It does not try to provide a comprehensive set of functionality, but only what is absolutely essential for a project like DM1. I had the simplicity of the Java Threads package in mind when creating this library.

The constructs provided by the DM1 Thread library are:

Implementation Details

Choice of Programming Language

The DM1 Threads library is written in C++. Originally, it was written in C, but I decided to port the product to C++ primarily for following reasons:

  1. I wanted to use the namespace facility of C++. I was tired of prefixing every global name with dm1_ .
  2. I wanted to use the automatic construction and destruction facility in C++. I think this is one of the coolest features of C++. As an aside, I like Java's finally solution better than C++ destructors because with finally, I am able to control the destruction of objects better.

I was apprehensive about using C++, because I find that C++ is a large and complicated language. In order to keep the DM1 Threads code simple, I made some decisions that are sure to be controversial:

  1. I do not use the C++ standard library, including the STL, at all. This is because I do not like the code bloat that results from its use. I also do not like the idea of using the heap for creating simple objects like strings. I think that C programs are generally more efficient than C++ programs, because they are much more circumspect about using the heap. One advantage of not using the C++ standard library is that it makes DM1 Threads more portable.
  2. I do not use templates other than in a very small way.
  3. I use sparingly or not at all, certain features of C++ language, such as multiple inheritance, operator overloading, new style typecast operators, etc. This is because I feel that none of these features are essential (Java does without them nicely).

I think that Java is a better language than C++, but the lack of certain features (efficient array handling, pointers, etc.) makes it unsuitable for a project like DM1. In many ways, I use C++ as a better Java. C# would have been a good choice, but due to its lack of availability on UNIX platforms, I was unable to use it.

Port Strategy

My goal was to have a library that worked on Win32 as well as POSIX compliant UNIX platform. One way of doing this would have been to use either a pthreads emulation library on Win32, or to emulate Win32 Threads API on UNIX. I decided to do neither. The DM1 Threads package uses native Win32 functionality on Windows, and pthreads functionality on UNIX. It creates abstractions that are neither like Win32, nor like POSIX, but somewhere in between.

In order to keep things simple, I limit myself to a subset of functionality available in Win32 and pthreads. For example, Condition Variables are a powerful feature of pthreads, but hard to implement correctly on Win32. Hence, I do not provide Condition variables as a synchronisation mechanism in DM1 Threads library. Instead, I provide the Monitor object that provides a sub-set of the functionality offered by Condition Variables.

I also provide a sub-set of the Win32 Event type. The sub-set was carefully chosen to ensure portability and reduced complexity.

Design Principles

The DM1 Threads library was designed with the following principles in mind:

1. Implement the bare minimum that is required. This Threads library does not aim to be a comprehensive threads package.

2. Avoid complex algorithms. If a particular construct is hard to implement correctly on all platforms, avoid it.

3. Document the library.

4. Avoid low level code, such as assembler code to implement Spin locks. Rely on the libraries provided by the Operating System.

5. Avoid holding Mutexes beyond function calls. A DM1 Thread library function will not hold any Mutex locks when it returns.

6. Avoid using clever C++ techniques wherever possible. (Unfortunately, some cleverness is required to implement the Thread class correctly).

7. Avoid dependency on external libraries. The DM1 library only requires the standard C library, apart from native Threads functionality.

8. Always report an error as soon as it is discovered.

9. Insert debug messages that can be switched on at run-time.

10. Do not throw exceptions from destructors because these might be executing as a result of an uncaught exception.

11. Never let an error go unreported.

Problems and Issues

I encountered two main problems when implementing this library.

The first problem was that of Error handling. The functionality provided by this library is so essential to the operation of DM1, that if an error occurs, it can be nearly impossible to recover. Perhaps, the best option would be to simply terminate the process. Currently, however, error conditions raise exceptions. When an exception is raised, no guarantees are made about the state of any objects managed by the library.

The second problem was the difficulty in implementing a Thread class to encapsulate the Threads functionality. This difficulty arises because of the nature of Threads. A Thread has a life of its own, quite apart from the C++ Thread object that represents it. There is a possibility that the Thread object will stop representing the true state of an operating system thread. For example, the C++ object may be destroyed before the Thread terminates. I avoid this situation by implementing pseudo garbage collection of Thread objects. You should never deallocate a Thread object. The system will automatically deallocate it after the associated Operating System Thread finishes.

Why another Threads library?

The main reason is that it is the best way to learn. I started the DM1 project mainly in order to learn how a DBMS works. If I use third-party libraries, I could save some time, but an important objective of the DM1 project would remain unfulfilled.

If you are interested in a more general purpose library, please have a look at Zthreads. I came to know about this library after I had completed a large part of the work on DM1 Threads.

How to build DM1 Threads library

I have tested the library on Win32 and on Linux (SUSE 8.1). The build procedure is as follows:

Linux

On Linux, you can simply execute make and it should build the library, and the test programs. To run the test programs, you will need to set LD_LIBRARY_PATH appropriately.

Windows

To build DM1 Threads on Windows, you need MS Visual C++ 6.0 or above. The VC++ 6.0 Workspace file is in the win32-build subdirectory. The README.txt file in the win32-build sub-directory provides more details on the Win32 build process.


Copyright © 2002-2004 by Dibyendu Majumdar