The CAVELib splits an application up into several pieces to handle the different tasks involved in displaying a virtual environment, such as different viewports or windows. These pieces may either be separate proceses or separate threads, depending on which CAVELib library an application is linked to. Prior to version 3.1 of the CAVELib threads were not supported, instead the CAVELib only supported a multi-processing paradigm. Multi-processing is inherently more difficult than multi-threading, because of the need for a data passing mechanism to share variables and other data between each process. The mechanism for doing this within the CAVELib is discussed further below. (This document does not go into detail regarding the differences between multi-processing and multi-threading. That is best left to a college-level operating systems course text book.)
Regardless if multi-processing or multi-threading is being used each thread/process is created by CAVEInit(). Only the parent application process will return from CAVEInit(); the child threads/processes start infinite loops that perform the execution of internal library functions and user callbacks. The CAVELib creates one display thread/process per graphics pipe, one thread/process for tracking (if tracking is not enabled to be serial), one thread/process for networking (if networking is enabled), and the main parent process. Even in multi-threading there is still a process, it is the parent/main process, and all threads are spawned from it.
To maintain the highest possible frame rates, the display threads/processes should be implemented to only perform rendering actions. All computations should be done in the main (aka parent) application process if possible. Which leads to the requirement of getting data from the main process to each display thread/process. Furthermore these display threads/processes are running in parallel. Because of this parallel approach, it may be necessary to guarantee that the main process does not modify shared data while the display threads/processes are using it. The best method to eliminate data corruption is by making the data access mutually exclusive between threads/processes. One such way is to use locks or semaphores to limit simultaneous access to shared data. The CAVELib includes several routines for user convenience (CAVENewLock(), CAVEFreeLock(), CAVESetReadLock(), CAVEUnsetReadLock(), CAVESetWriteLock(), CAVEUnsetWriteLock()) which provide two-level access control. If the display threads/processes only read the shared data, setting a read lock will allow any number of them to access the data at the same time, while a write lock will allow exactly one thread/process (like the main process) to change the data at a time.