\"\" \"\" \"\"
Go up to Top
Go forward to Tutorial
RISC-Linz logo

Introduction

This report describes RT++(2), a software package that provides higher-order threads for the programming language C++. "Yet another thread package" you may think but this is only partially true.

Of course RT++ performs what can be expected from any decent thread package. It gives the programmer the possibility to create threads, i.e. concurrent units of control or light-weight processes, and thus to write parallel (or at least pseudo-parallel) programs. The RT++ runtime system schedules these threads on one or several Unix processes which in turn are scheduled by the operating system. If the underlying hardware is a multi-processor, processes and thus threads are executed truly in parallel.

There exists a variety of thread packages that do the same (e.g. PRESTO [BLLW88], FastThreads [And90], uC++ [BDS92], Pthreads [Mue93], Chant [HCM94], Solaris threads [Sun96], see also the "Threads Page" [Thr96]). Still it is surprisingly difficult to find a package that has been ported to a larger portion of the of workstation and multi-processor brands that are in use today.

One of the most portable systems is QuickThreads [Kep93] which is actually a toolkit for building thread packages. QuickThreads provides for a variety of processor types the core routines for thread initialization and context switching and thus frees the poor thread package developer from the nasty task of assembler programming. RT++ is based on these routines and can thus be easily ported to any machine with a processor type supported by QuickThreads(3).

The main goal of RT++ however is to provide a programming interface which is considerably higher-level than that of comparable packages. RT++ considers threads as an abstract datatype with a functional interface i.e. threads communicate only via arguments (which are provided when the thread is defined) and results (which are delivered when the thread has terminated). Threads can be used like objects of any other type i.e. they can be stored in data structures, passed as thread arguments, and returned as thread results. Functional programming languages are called higher-order if they treat functions as first-order objects; we call RT++ higher-order because it treats threads in this way.

However, an abstract thread interface only makes sense if programmers need not be aware of such low-level issues as allocating and freeing thread resources. In most packages, the resources for a thread are allocated when the thread is created and are freed when the thread result is delivered to another (typically the parent) thread. This is a very low-level view of threads because (among other issues) it does not allow two retrieve twice the result of a thread (because the first result delivery destroys the thread) and, if a thread is forgotten, its resources remain allocated forever.

RT++ provides a thread/memory management system where programmers need not care about these low-level issues. Thread resources are implicitly allocated as late as possible and implicitly freed as early as possible regardless whether or how often the thread result is retrieved. Threads are subject to garbage collection and automatically reclaimed when not referenced any more. RT++ also provides type constructors for arrays, lists, and general pointer structures whose objects can be passed by reference among threads and that are subject to automatic garbage collection. A high-level notion of non-determinism is supported via thread bags which retrieve their result in the order in which they become available and thus allow to write more abstract (and sometimes more efficient) parallel programs.

RT++ has been developed as a successor of the PACLIB kernel [HNS95] which served as the C-based runtime system of a parallel computer algebra package [SH93] and of a parallel functional programming language [Sch96]. RT++ owes to PACLIB its central ideas of thread scheduling [Sch94] which are based on "virtual threads" [KW92] respectively "lazy threads" [MKHJ91]. PACLIB was built upon the μSystem package [BS90]; the contents of this thread package taught us the essential concepts of multi-threading. The RT++ assembly code for mutual exclusion was mainly taken from the μSystem respectively its successor μC++ [BDS92].

RT++ considerably owes to the development group of the symbolic computation package STURM [HNS94] for communicating their experience with C++, in particular with the features and deficiencies of the "template" construct on which RT++ is heavily based. STURM uses reference counting for memory management and provides a parallel programming interface in the spirit of PACLIB. RT++ emerged as an attempt to provide a small and self-contained parallel programming package which seamlessly and efficiently integrates multi-threading and garbage collection within a type-safe C++ framework.

RT++ has been written and tested using the GNU g++ compiler (versions 2.6.3 and 2.7.2). While no GNU-specific extensions have been used, we have not verified that the system works with other C++ compilers. RT++ has been ported to and tested on the following architectures:

Ports to other architectures using processors supported by the QuickThreads package (in particular the DEC AXP (Alpha) family) should be easy. However, in particular the IBM PowerRISC line is not yet supported.

The package is available under the GNU GPL on the World Wide Web at

http://www.risc.uni-linz.ac.at/software/rt++
Comments and bug reports can be sent to the the author under the email address Wolfgang.Schreiner@risc.uni-linz.ac.at.
Author: Wolfgang Schreiner
Last Modification: April 12, 1997