/* $Id: ncbithr.h,v 5.10 1996/09/04 14:34:44 kans Exp $ */
/*****************************************************************************

    Name: ncbithr.h                                

    Description: Main function definitions for Multi-Thread API library.

    Author: Sergei Shavirin

   ***************************************************************************

                          PUBLIC DOMAIN NOTICE
              National Center for Biotechnology Information

    This software/database is a "United States Government Work" under the
    terms of the United States Copyright Act.  It was written as part of    
    the author's official duties as a United States Government employee
    and thus cannot be copyrighted.  This software/database is freely
    available to the public for use. The National Library of Medicine and
    the U.S. Government have not placed any restriction on its use or
    reproduction.

    Although all reasonable efforts have been taken to ensure the accuracy
    and reliability of the software and data, the NLM and the U.S.
    Government do not and cannot warrant the performance or results that
    may be obtained by using this software or data. The NLM and the U.S.
    Government disclaim all warranties, express or implied, including
    warranties of performance, merchantability or fitness for any
    particular purpose.

    Please cite the author in any work or product based on this material.

   ***************************************************************************

    Modification History:
           20 February of 1996 - Shavirin  -  originaly written

    Bugs and restriction on use:

    Notes:

*****************************************************************************/
#ifndef __NLM_THR__
#define __NLM_THR__ nlm_thr

/****************************************************************************/
/* INCLUDES */
/****************************************************************************/
#include <ncbi.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/****************************************************************************/
/* DEFINES */
/****************************************************************************/

/*
 * thread flags (one word bit mask)
 */

#define THR_RUN          0          /* Immediatly run this thread (default) */ 
#define THR_MIN_PRI      0          /* minimum priority for a thread */ 
#define THR_MAX_PRI      127        /* maximum priority for a thread */

#if   defined(SOLARIS_THREADS_AVAIL) /* just for information */
#define THR_BOUND        0x00000001
#define THR_NEW_LWP      0x00000002
#define THR_DETACHED     0x00000040 /* The new thread created detached  */

	/* these not defined for POSIX */

#define THR_SUSPEND      0x00000080 /* The new thread created suspended */
#define THR_DAEMON       0x00000100 /* The new thread created as daemon */

#elif defined (POSIX_THREADS_AVAIL)

#define PTHREAD_SCOPE_PROCESS 0
#define PTHREAD_SCOPE_SYSTEM  1

#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 1

#define THR_BOUND    PTHREAD_CREATE_JOINABLE
#define THR_DETACHED PTHREAD_CREATE_DETACHED

#elif defined(WIN32)

#define THR_BOUND     0
#define THR_DETACHED         0
#define THR_SUSPEND          CREATE_SUSPENDED
#define MAX_SEMAPHORE_COUNT  1024
#else
#define THR_BOUND     0
#define THR_DETACHED     0
#define THR_SUSPEND      0
#endif


/****************************************************************************/
/* TYPEDEFS */
/****************************************************************************/


typedef VoidPtr TNlmThread;         /* handle (id) of the thread    */
typedef VoidPtr TNlmSemaphore;      /* handle (id) of the semaphore */
typedef VoidPtr TNlmRWlock;         /* handle (id) of the RW lock   */
typedef VoidPtr TNlmMutex;          /* handle (id) of the mutex     */


/* pointer to the thread function */
typedef VoidPtr (*TNlmThreadStart)(VoidPtr arg);

/* pointer to the thread finishing function */
typedef void (*TNlmThreadOnExit)(VoidPtr user_arg);


/****************************************************************************/
/* FINCTION DEFINITIONS */
/****************************************************************************/

/*
 *  Auxiliary function to be used in the NlmThreadAddOnExit()
 *  function call to provide memory deallocation on the thread exit
 */
extern void NlmThreadMemFree PROTO ((VoidPtr ptr));


/* --------------------  NlmThreadAddOnExit  ----------------------
   Purpose:     Adds a function to be called on the thread termination
   Parameters:  The function "func" will be called with the "arg" argument
                when the thread is terminating;  then, the later registered
                "destroying function" will be called earlier (LIFO order)

   Returns:     TRUE on success...
   NOTE:        Must be called from inside the thread
  ------------------------------------------------------------------*/
extern Boolean NlmThreadAddOnExit PROTO ((TNlmThreadOnExit func, VoidPtr arg));


/* --------------------  NlmThreadRemoveOnExit  -------------------
   Purpose:     Removes the thread's termination function(s)
   Description: This function removes all previosly registered(for this
                thread) terminating functions whose attributes
                matches both "func" and "arg"
   NOTE:        Must be called from inside the thread
  ------------------------------------------------------------------*/
extern void NlmThreadRemoveOnExit PROTO ((TNlmThreadOnExit func, VoidPtr arg));


/* --------------------  NlmThreadCreate  ---------------------------
   Purpose:     To create new thread
  
   Parameters:  theStartFunction - address of the thread function
                *arg             - arguments for the new thread
                flags            - attributes for the thread: 
		                   THR_RUN (default) or THR_SUSPEND
   Returns:     New thread handle. Will be used to identify the thread. 
  
   Description: This function creates new thread - independent process
                inside current process, that share most resources of the
                parent thread.
                
   NOTE:         
  ------------------------------------------------------------------*/
TNlmThread NlmThreadCreate  PROTO ((
	       TNlmThreadStart theStartFunction,   /* address of the thread 
						      function */   
	       VoidPtr arg,         /* arguments for the new thread */
	       Int4    flags        /* attributes for the thread */
	   ));


/* --------------------  NlmThreadCreateEx  -------------------------
   Purpose:     To create new thread and register its destructor
  
   Parameters:  "theStartFunction", "arg", "flags"  -- see NlmThreadCreate
                "exit_func", "exit_arg"  -- these two allow one to add a
                function to be called when the thread is exiting -- it's
                the only convenient way to do this from outside of thread
                (see also the NlmThreadAddOnExit() function to get know
                how to do it from the thread's inside).

   Returns:     New thread handle. Will be used to identify the thread. 
  
   Description: This function creates new thread - independent process
                inside current process, that share most resources of the
                parent thread.
                
   NOTE:        It's guaranteed that the "exit_func" (if non-NULL) will
                be called after any other exiting function specified
                from inside the thread
  ------------------------------------------------------------------*/
TNlmThread NlmThreadCreateEx  PROTO ((
         TNlmThreadStart  theStartFunction,
	       VoidPtr          arg,
	       Int4             flags,
         TNlmThreadOnExit exit_func, 
         VoidPtr          exit_arg            
	   ));


/* ----------------------  NlmThreadSelf  --------------------------
   Purpose:     To get thread handle 
  
   Parameters:  None
  
   Returns:     theThread - thread handle NULL if error
                an error
  
   Description: NlmThreadSelf() returns the handle of the calling thread
                
   NOTE:        
  -----------------------------------------------------------------*/
TNlmThread NlmThreadSelf  PROTO ((void));


/* ----------------------  NlmThreadJoin  --------------------------
   Purpose:     Wait for thread termination 
  
   Parameters:  INPUT:  "wait_for" -- thread handle to wait for termination
                OUTPUT: "status"   -- the thread's exit status
   Returns:     zero value on success;  non-zero value on error
  
   Description: Blocks the calling thread until the thread specified by
                wait_for terminates. The specified thread must be in the 
                current process. If wait_for is (TNlmThread)0, then
                NlmThreadJoin() waits for ANY thread in the process to
                terminate.
   NOTE:        Multiple threads cannot wait for the same thread to 
                terminate. One thread will return successfully and the 
                others will fail.
  -----------------------------------------------------------------*/
Int4 NlmThreadJoin  PROTO ((
		   TNlmThread  wait_for, /* handle of the thread to wait */
                   VoidPtr    *status    /* the thread's exit status     */
     ));


/* ----------------  NlmThreadSetConcurrency  ----------------------
   Purpose:     Set thread concurrency level
  
   Parameters:  new_level - concurrency level to set
  
   Returns:     0 is returned when successful. A non-zero value indicates 
                an error
  
   Description: This function permits the application to give the threads 
                system a hint, specified by new_level for the desired level 
		of concurrency. The actual number of simultaneously active
		threads may be larger or smaller than this number.
                
   NOTE:        
  -----------------------------------------------------------------*/
Int4 NlmThreadSetConcurrency(Int4 new_level);


/* ----------------  NlmThreadGetConcurrency  ----------------------
   Purpose:     To get thread handle 
  
   Parameters:  None
  
   Returns:     Current value for the desired concurrency level
  
   Description: returns the current value for the desired concurrency
                level. The actual number of simultaneously active threads 
		may be larger or smaller than this number.
                
   NOTE:        
  -----------------------------------------------------------------*/
Int4 NlmThreadGetConcurrency(void);


/* ----------------------  NlmThreadContinue  -----------------------
   Purpose:     Resume execution of a suspended thread 
  
   Parameters:  theThread - thread handle to continue
  
   Returns:     0 is returned when successful. A non-zero value indicates 
                an error
  
   Description: Resume execution of the thread, that was initially
                started in suspended state
                
   NOTE:        Currently suspending supported only during initial
                creation of the thread
  -----------------------------------------------------------------*/
Int4 NlmThreadContinue(
		      TNlmThread theThread   /* thread handle to continue */
    ); 


/* -------------------  NlmThreadExit  ------------------------------
   Purpose:      To terminate the calling thread    
  
   Parameters:   status - exit code for the calling thread
  
   Returns:      Nothing      
   
   Description:  This function terminates th calling thread. All thread-
                 specific data bindings are released. If the initial thread 
                 returns from main() then the process exits with a status
                 equal to the return value
                
   NOTE:
   -----------------------------------------------------------------*/
void NlmThreadExit PROTO ((
		   VoidPtr status /* exit data of the calling thread */
     ));


/* -------------------  NlmThreadSetPriority  -----------------------
   Purpose:     To set priority of the specified thread   
  
   Parameters:  theThread - thread handle to set priority
                priority  - integer from 0 (the least priority)
                           to 100 (highest priority) 
  
   Returns:     Zero is returned when succesful. A non-zero value
                indicates error.
  
   Description: Each thread has a priority which it inherits from its
                creator. This function changes priority of "theThread" to
                the value specified by "priority".
                
   NOTE:
   -----------------------------------------------------------------*/
Int4 NlmThreadSetPriority(
			 TNlmThread theThread, /* thread handle */
			 Int4 priority         /* priority level */
    );


/* -------------------  NlmThreadGetPriority  -----------------------
   Purpose:      To get priority of the thread
  
   Parameters:   theThread - handle of the thread to get priority
                 priority  - storage for the priority of theThread
   Returns:      Zero is returnen, when succesful. A non-zero value 
                 indicates error
  
   Description:  This function gets current value of priority of theThread
                
   NOTE:
   -----------------------------------------------------------------*/
Int4 NlmThreadGetPriority(
			 TNlmThread theThread,  /* handle of the thread */
			 int *priority       /* storage for priority */
    );

/* ---------------------  NlmThreadKill  ----------------------------
   Purpose:     To terminate thread from another thread    
  
   Parameters:  theThread - handle of the thread to kill
  
   Returns:     Zero is returned when successful. A non-zero value
                indicates an error
  
   Description: This function terminates thread, specified as parameter.
                
   NOTE:        In Solaris we send signal "9" to the thread.
   -----------------------------------------------------------------*/
Int4 NlmThreadKill(
		  TNlmThread theThread   /* handle of the thread to kill */
    );

/********************************************************************/
/*                                                                  */
/* =========== Semaphore support for the thread API library ======= */
/*                                                                  */
/********************************************************************/


/* ---------------------  NlmSemaInit  ------------------------------
   Purpose:     To create new semaphore    
  
   Parameters:  count - number of threads, that may use semaphore
                in parallel
  
   Returns:     Semaphore handle
  
   Description: To create new semaphore with "count" simultaneous accesses.
                
   NOTE:        This semathore can be used to synchronize threads in this
                process only
   -----------------------------------------------------------------*/
TNlmSemaphore NlmSemaInit(
			  Uint4 count
              );


/* ---------------------  NlmSemaDestroy  ---------------------------
   Purpose:     To destroy specified semaphore.
  
   Parameters:  theSemaphore - handle of the semaphore
  
   Returns:     Zero is returned when succesful. A non-zero value 
                indicates an error
  
   Description: destroys any state associated with the semaphore pointed
                to by theSemaphore
                
   NOTE:        The space for storing the semaphore is NOT freed.
   -----------------------------------------------------------------*/
Int4 NlmSemaDestroy(
		   TNlmSemaphore theSemaphore
    );


/* ---------------------  NlmSemaWait  ------------------------------
   Purpose:      To wait until semaphore is not zero.
  
   Parameters:   theSemaphore - handle of the semaphore
  
   Returns:      Zero is returned when successful. A non-zero value
                 indicates an error
  
   Descrription: Blocks the calling thread until the count in the 
                 semaphore pointed by theSemaphore becomes greater than zero
                 and then atomically decrements it  
                
   NOTE:
   -----------------------------------------------------------------*/
Int4 NlmSemaWait(
		TNlmSemaphore theSemaphore
    );


/* ---------------------  NlmSemaTryWait  ---------------------------
   Purpose:      To poll semaphore status    
  
   Parameters:   theSemaphore - handle of the semaphore to poll
  
   Returns:      Zero is returned when successful. A non-zero value
                 indicates an error
  
   Description:  atomically decrements the count in the semaphore 
                 pointed to by theSemaphore if the count is greater
                 than zero. Otherwise it returns an error.
                
   NOTE:
  -----------------------------------------------------------------*/
Int4 NlmSemaTryWait(
		   TNlmSemaphore theSemaphore
    ); 


/* ---------------------  NlmSemaPost  ------------------------------
   Purpose:    To increase the count of semaphore by one
  
   Parameters: theSemaphore - handle of the semaphore to post
  
   Returns:    Zero is returned when succesful. A non-zero value
               indicates an error
  
   Description:  atomically increments the count semaphore pointed to by
                 thSemaphore, one is unblocked.
                
   NOTE
   -----------------------------------------------------------------*/
Int4 NlmSemaPost(
		TNlmSemaphore theSemaphore
    );

/********************************************************************/
/*                                                                  */
/* === Semaphore-like object to keep read/write syncronization ==== */
/*                                                                  */
/********************************************************************/

/* ---------------------  NlmRWlock  --------------------------------
   Purpose:     Initialize readers/writer lock   
  
   Parameters:  None
  
   Returns:     Handle of the new RW - lock or NULL if error occour
  
   Description: Readers/writer locks must be initialized before use. This
                function initialize new lock.
                
   NOTE
   -----------------------------------------------------------------*/
TNlmRWlock NlmRWinit(void);


/* ---------------------  NlmRWdestroy  -----------------------------
   Purpose:      To destroy RW lock
  
   Parameters:   theRWlock - handle of the RW lock to destroy
  
   Returns:      Zero is returned when succesful. A non-zero value
                 indicates an error
  
   Description:  Destroys any state associated with the RW lock
                 pointed to by theRWlock.
                
   NOTE:         The space for storing the RWlock is not freed.
  -----------------------------------------------------------------*/
Int4 NlmRWdestroy(TNlmRWlock theRWlock);


/* ---------------------  NlmRWrdlock  ------------------------------
   Purpose:      To acquire a read lock    
  
   Parameters:   theRWlock - handle of the RW lock
  
   Returns:      Zero is returned when succesful. A non-zero value
                 indicates an error
  
   Description:  Acquires a read lock on the readers/writer lock
                 pointed to by theRWlock. If the RW lock is already
                 locked for writing, the calling thread blocks until 
                 the write lock is released.
                
   NOTE          More than one thread may hold a read lock on a RW lock at any 
                 one time.
  -----------------------------------------------------------------*/
Int4 NlmRWrdlock(TNlmRWlock theRWlock);

        
/* ---------------------  NlmRWwrlock  ------------------------------
   Purpose:      To acquire a write lock 
  
   Parameters:   theRWlock - handle of the RW lock
  
   Returns:      Zero is returned when succesful. A non-zero value
                 indicates an error
  
   Description:  Acquires a write lock on the readers/writer lock
                 pointed to by theRWlock. If the RW lock is already
                 locked for reading or writing, the calling thread blocks 
                 until the lock is released.
                
   NOTE:         Only one thread may hold a write lock on a RW lock at any 
                 one time.
  -----------------------------------------------------------------*/
Int4 NlmRWwrlock(TNlmRWlock theRWlock);

        
/* ---------------------  NlmRWunlock  ------------------------------
   Purpose:      To unlock the RW lock    
  
   Parameters:   theRWlock - handle of the RW lock
  
   Returns:      Zero is returned when succesful. A non-zero value
                 indicates an error
  
   Description:  The RW lock must be locked and the calling thread must 
                 hold the lock either for reading or for writing. If
                 any other threads are waiting for the RW lock to become 
                 available, one of them is unblocked.
               
   NOTE:         If the calling thread does not hold the lock for either 
                 reading or writing no error status is returned and the 
                 behavior of the program is undefined.
   -----------------------------------------------------------------*/
Int4 NlmRWunlock(TNlmRWlock theRWlock);


/* ---------------------  NlmRWtryrdlock  ---------------------------
   Purpose:      To attempt to acquire read lock
  
   Parameters:   theRWlock - handle of the RW lock
  
   Returns:      Zero is returned when succesful. A non-zero value
                 indicates an error
  
   Description:  Attempts to acquire a read lock on the RW lock
                 pointed to by theRWlock. If the RW lock is already
                 locked for writing, it returnes an error. Otherwise
                 the read lock is acquired
                
   NOTE
   -----------------------------------------------------------------*/
Int4 NlmRWtryrdlock(TNlmRWlock);


/* ---------------------  NlmRWtrywrlock  ---------------------------
   Purpose:       To attempt to acquire write lock
  
   Parameters:    theRWlock - handle of the RW lock
  
   Returns:       Zero is returned when succesful. A non-zero value
                  indicates an error
  
   Description:   Attempts to acquire a write lock on the RW lock
                  pointed to by theRWlock. If the RW lock is already
                  locked for reading or writing, it returnes an error. 
                  Otherwise the write lock is acquired
                
   NOTE
   -----------------------------------------------------------------*/
Int4 NlmRWtrywrlock(TNlmRWlock);

/* ---------------------  NlmMutex  ---------------------------------
   Purpose:       To initialize and deal with mutex locks
  
   Parameters:    Mutex ID
  
   Returns:       Zero is returned when succesful. A non-zero value
                  indicates an error
  
   Description:   Mutual exclusion locks (mutexes)  prevent  multiple  
                  threads from  simultaneously  executing  critical  
                  sections  of code which access shared data (i.e., 
                  mutexes are used to  serialize  the execution of threads).  
                  All mutexes must be global.

                
   -----------------------------------------------------------------*/

TNlmMutex NlmMutexInit(void);
Int4 NlmMutexLock(TNlmMutex mp);
Int4 NlmMutexTryLock(TNlmMutex mp);
Int4 NlmMutexUnlock(TNlmMutex mp);
Int4 NlmMutexDestroy(TNlmMutex mp);
Boolean NlmThreadsAvailable(void);

Int4 NlmCPUNumber(void);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __NLM_THR__ */

/*EOF*/

