INFORMIX
Informix-ESQL/C Programmer's Manual
Chapter 13: Using Informix Libraries
Home Contents Index Master Index New Book
UNIX

Creating a Dynamic Thread Library on UNIX Operating Systems

To create a dynamic thread library, you must define routines for every threaded operation that ESQL/C performs and you must register those functions with ESQL/C. The following list shows all of the functions that a multithreaded ESQL/C application requires and describes what each function must do.

1. int ifxOS_th_once(ifxOS_th_once_t *pblock, ifxOS_th_initroutine_t pfn, int *init_data)

if (!*init_data)
{
mutex_lock(pblock);
if (!*init_data)
{
(*pfn)();
*init_data = 1;
}
mutex_unlock(pblock);
}
return(0);

    2. int ifxOS_th_mutexattr_create(ifxOS_th_mutexattr_t *mutex_attr)

    This function creates a mutex attributes object that specifies the attributes of mutexes when they are created. The mutex attributes object is initialized with the default value for all of the attributes defined by the user's implementation. This routine is equivalent to the DCE pthread_mutexattr_create(), or the POSIX pthread_mutexattr_init() routines. If a thread package does not support mutex attribute objects, the mutex attribute routines can be no-ops.

    3. int ifxOS_th_mutexattr_setkind_np(ifxOS_th_mutexattr_t *mutex_attr, int kind)

    This routine sets the mutex type attribute that is used when a mutex is created. The mutex attribute mutex_attr is set to type kind. For DCE, this routine is pthread_mutexattr_setkind_np().

    4. int ifxOS_th_mutexattr_delete(ifxOS_th_mutexattr_t *mutex_attr)

    This routine deletes the mutex attribute object mutex_attr. This routine should have the same functionality as the DCE pthread_mutexattr_delete(), or the POSIX pthread_mutexattr_destroy() routines.

    5. int ifxOS_th_mutex_init(ifxOS_th_mutex_t *mutexp, ifxOS_th_mutexattr_t mutex_attr)

    This routine creates a mutex and initializes it to the unlocked state. This routine should have the same functionality as the DCE pthread_mutex_init(), or the POSIX pthread_mutex_init() routines.

    6. int ifxOS_th_mutex_destroy(ifxOS_th_mutex_t *mutexp)

    This routine deletes a mutex. The mutex must be unlocked before it is deleted. This routine should have the same functionality as the DCE pthread_mutex_destroy(), or the POSIX pthread_mutex_destroy() routines.

    7. int ifxOS_th_mutex_lock(ifxOS_th_mutex_t *mutexp)

    This routine locks an unlocked mutex. If the mutex is already locked, the calling thread should wait until the mutex becomes unlocked. This routine should have the same functionality as the DCE pthread_mutex_lock(), or the POSIX pthread_mutex_lock() routines.

    8. int ifxOS_th_mutex_trylock(ifxOS_th_mutex_t *mutexp)

    If the mutex is successfully locked, it returns the value 1, if the mutex is locked by another thread, it returns the value 0.

    9. int ifxOS_th_mutex_unlock(ifxOS_th_mutex_t *mutexp)

    This routine unlocks the mutex mutexp. If threads are waiting to lock this mutex, the implementation defines which thread receives the mutex. This routine should have the same functionality as the DCE pthread_mutex_unlock(), or the POSIX pthread_mutex_unlock() routines.

    10. int ifxOS_th_condattr_create(ifxOS_th_condattr_t *cond_attr)

    This routine creates an object that is used to specify the attributes of condition variables when they are created. Initialize the object with the default value for all of the attributes defined by the user's implementation. This routine should have the same functionality as the DCE pthread_condattr_create(), or the POSIX pthread_condattr_init() routines.

    11. int ifxOS_th_cond_init(ifxOS_th_cond_t *condp, ifxOS_th_condattr_t cond_attr)

    This routine creates and initializes a condition variable. It should have the same functionality as the DCE pthread_cond_init(), or the POSIX pthread_cond_init() routines.

    12. int ifxOS_th_condattr_delete(ifxOS_th_condattr_t *cond_attr)

    This routine deletes the condition variable attribute object cond_attr. The routine should have the same functionality as the DCE pthread_condattr_delete(), or POSIX pthread_condattr_destroy() routines.

    13. int ifxOS_th_cond_destroy(ifxOS_th_cond_t *condp)

    This routine deletes the condition variable condp. The routine should have the same functionality as the DCE pthread_cond_destroy(), or the POSIX pthread_cond_destroy() routines.

    14. int ifxOS_th_cond_timedwait(ifxOS_th_cond_t *sleep_cond, ifxOS_th_mutex_t *sleep_mutex, ifxOS_th_timespec_t *t)

    This routine causes a thread to wait until either the condition variable sleep_cond is signaled or broadcast, or the current system clock time becomes greater than or equal to the time specified in t. The routine should have the same functionality as the DCE pthread_cond_timedwait(), or the POSIX pthread_cond_timedwait() routines.

    15. int ifxOS_th_keycreate(ifxOS_th_key_t *allkey, ifxOS_th_destructor_t AllDestructor)

    This routine generates a unique value that identifies a thread-specific data value. The routine should have the same functionality as the DCE pthread_keycreate(), or the POSIX pthread_key_create() routines.

    16. int ifxOS_th_getspecific(ifxOS_th_key_t key, ifxOS_th_addr_t *tcb)

    This routine obtains the thread-specific data associated with the key key. The routine should have the same functionality as the DCE pthread_getspecific(), or the POSIX pthread_getspecific() routines.

    17. int ifxOS_th_setspecific(ifxOS_th_key_t key, ifxOS_th_addr_t tcb)

    This routine sets the thread-specific data in tcb associated with the key key for the current thread. If a value is already defined for key in the current thread, the new value is substituted for the existing value. The routine should have the same functionality as the DCE pthread_setspecific(), or the POSIX pthread_setspecific() routines.

Data Types

You can create typedefs for the data types in the preceding functions to the equivalent data types in your thread package, or you can use the appropriate data type from the thread package instead of the ifxOS_ version. The following list includes all the data types that the preceding functions use:

    This structure defines a mutex object: pthread_mutex_t in DCE and POSIX.

    This structure defines a mutex attributes object called pthread_mutexattr_t in DCE and POSIX. If mutex attribute objects are unsupported in your thread package (for instance, Solaris Kernel Threads), you can assign them a data type of int.

    This structure allows client initialization operations to guarantee mutually exclusive access to the initialization routine, and to guarantee that each initialization is executed only once. The routine should have the same functionality as the pthread_once_t structure in DCE and POSIX.

    This structure defines an object that specifies the attributes of a condition variable: pthread_condattr_t in DCE and POSIX. If this object is unsupported in your thread package (for instance, Solaris Kernel Threads), you can assign it a data type of int.

    This structure defines a condition variable called pthread_cond_t in DCE and POSIX.

    This structure defines an absolute time at which the ifxOS_th_cond_timedwait() function should time out if a condition variable has not been signaled or broadcast. This structure is timespec_t in DCE and POSIX.

    This structure defines a thread-specific data key used in the ifxOS_th_keycreate(), ifxOS_th_setspecific() and ifxOS_getspecific() routines. This structure is pthread_key_t in DCE and POSIX.

    This structure defines an address that contains data to be associated with a thread-specific data key of type ifxOS_th_key_t. The ifxOS_th_addr_t structure is equivalent to pthread_addr_t in DCE. You can specify void * as an alternative that can be used for thread packages (such as POSIX) that do not define such a structure.

UNIX
The following example uses the Solaris Kernel Threads package to demonstrate how to set up a dynamic-thread library. The first task is to define the 17 dynamic-thread functions that the shared and/or static library needs. In this example, the file is called dynthr.c:

Registering the Dynamic Thread Functions

Your ESQL/C application must use the ifxOS_set_thrfunc() function to register the dynamic thread functions with ESQL/C. The following declaration describes the ifxOS_set_thrfunc() function.

The first parameter, func, is an integer that indexes the function being registered. The second parameter is the name of the function that is being registered.

You must call ifxOS_set_thrfunc() once for each of the 17 ifxOS functions listed in step 1.

The ifxOS_set_thrfunc() function returns 0 if it successfully registers the function and -1 if it fails to register the function. For example, to register the user-defined function my_mutex_lock() as the ifxOS_th_mutex_lock routine, you use the following call:

TH_MUTEX_LOCK is defined in sqlhdr.h and tells the client to call my_mutex_lock() whenever it needs to lock a mutex.

The following list shows the indexes and the functions they register.

Index Function

TH_ONCE

ifxOS_th_once

TH_MUTEXATTR_CREATE

ifxOS_th_mutexattr_create()

TH_MUTEXATTR_SETKIND

ifxOS_th_mutexattr_setkind_np()

TH_MUTEXATTR_DELETE

ifxOS_th_mutexattr_delete()

TH_MUTEX_INIT

ifxOS_th_mutex_init()

TH_MUTEX_DESTROY

ifxOS_th_mutex_destroy()

TH_MUTEX_LOCK

ifxOS_th_mutex_lock()

TH_MUTEX_UNLOCK

ifxOS_th_mutex_unlock()

TH_MUTEX_TRYLOCK

ifxOS_th_mutex_trylock()

TH_CONDATTR_CREATE

ifxOS_th_condattr_create()

TH_CONDATTR_DELETE

ifxOS_th_condattr_delete()

TH_COND_INIT

ifxOS_th_cond_init()

TH_COND_DESTROY

ifxOS_th_cond_destroy()

TH_COND_TIMEDWAIT

ifxOS_th_cond_timedwait()

TH_KEYCREATE

ifxOS_th_keycreate()

TH_GETSPECIFIC

ifxOS_th_getspecific()

TH_SETSPECIFIC

ifxOS_th_setspecific()

The following function, dynthr_init(), which is also defined in dynthr.c, registers the 17 functions defined in step 1. FUNCFAIL is defined to be -1.

Setting the $THREADLIB Environment Variable

The following C-shell command sets THREADLIB to specify a user-defined thread package:

Creating the Shared Library

You must compile dynthr.c into a shared or static library. The following example illustrates how to compile a shared or static library on a workstation running the Solaris operating system:

You can also use the $LD_LIBRARY_PATH environment variable:

To compile dynthr.c into a static library, perform the following tasks (on Solaris):

You must update your application, test.ec, to call the dynthr_init() routine first, or none of the thread functions will be registered.

Compiling with the -thread and -l Preprocessor Options

You must compile the application using the -thread and the -l preprocessor options. The -thread option indicates that you are linking thread-safe libraries instead of the default Informix shared libraries. The -l option allows you to specify system libraries that you want to link. Finally, you compile your application, link libdynthr.so and run it, as shown in the following example:




Informix-ESQL/C Programmer's Manual, version 9.1
Copyright © 1998, Informix Software, Inc. All rights reserved.