Multi-Threaded Applications Rules for Windows (NT, 2000 and XP)Each thread of a multi-threaded application shares common global and static data space. As a result, designers of multi-threaded programs have to be careful at design time to avoid reading and writing global variables, or to carefully structure their code to coordinate global variable access. The Software Group's X.25 library API, libx25.lib, uses global variables in some circumstances; programmers needing to use the library with multi-threaded applications need to be aware of the implications of uncontrolled access to certain data elements within the library.
The library maintains relevant information for each virtual circuit in an internal data structure of type CALLT. X25open() allocates the data structure and x25close() releases it back to the operating system. As this is an internal, undocumented structure, applications do not refer to any CALLT elements directly. The library provides function calls and macros for this.
The library separates the threads' data space from each other. This implies that a CALLT created in one thread should never be accessed in another thread.
The library does not enforce mutual exclusion on CALLT data structures. As a result, the primary rule of writing multi-threaded applications using the X.25 library API is that "Each virtual circuit must be accessed by only one thread." If the programmer composes a program with a reader thread (to collect information from a virtual circuit) and a writer thread (to provide information to that virtual circuit), the application will break.
Designing applications where there is a one-to-one correspondence between threads and virtual circuits (i.e. each thread controls a single virtual circuit) is a valid approach.. There is however no restriction to the number of virtual circuits that a single thread can control (multiple CALLTs), including the use of X25looksel() to monitor those circuits.
The library often returns error codes in a global variable, x25errno, as indicated in the description of the library functions. In a multi-threaded environment, checking x25errno does not guarantee that a thread is referencing the error code related to the last operation it performed. Multi-threaded applications need to call X25geterrorct(). Applications should never use x25errno. x25errno is now defined to be a call to X25geterror(). Note that there are exceptions to this rule.
The routine X25error() may only be used in single-threaded applications as it interprets the internal X.25 internal global error variable. In multi-threaded applications, the replacement routine is:
void X25errorct(CALLT *ct, char *string)
which will interpret and display current error information from the CALLT structure.