Say you want to play audio and video in sync to within ±7ms. You may be wondering why you cannot just do this:
/* Best Effort Approach */ { /* need to do these two quickly */ start_audio(); start_video(); while (1) { /* send audio and video that should go out together */ send_next_video(); send_next_audio(); } }The idea is that you open up an audio port and a video path at the same time, and then you loop around sending corresponding audio and video data to each device. Assume there are plenty of system resources for you to send all the data without dropping anything. This technique will still fail to sync up the audio and video because:
More generally, any attempt to do two operations "at the same time" from an IRIX process will fail because your process may be preempted between the operations. Any attempt to do something "just as soon as" your process wakes up, or "just as soon as" some status you are polling changes, will fail for the same reason.
The only exception to this is if you are using the REACT/Pro real-time support described in (see Seizing Higher Scheduling Priority), and this only provides an upper bound on the amount of time your code can be preempted.
In each case, the library pairs the data is with its UST in memory, so your program can manipulate them together. Essentially, SGI's UST support transforms hardware operations that are atomic in time into software structures that are paired in memory. You can use these primitives to perform a wide range of synchronization tasks (some of which are listed in Introduction to UST and UST/MSC).