Subversion Repositories HomeAutomation

Rev

Rev 270 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /***************************************************************************
  2.                            wthread.c  -  description
  3.                               -------------------
  4.      begin                : Sun Jan 02 2000
  5.      copyright            : (C) 2001 by Rainer Lehrig
  6.      email                : lehrig@t-online.de
  7.   ***************************************************************************/
  8.  
  9.  /***************************************************************************
  10.   *                                                                         *
  11.   *   This library is free software; you can redistribute it and/or modify  *
  12.   *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
  13.   *   published by the Free Software Foundation                             *
  14.   *                                                                         *
  15.   ***************************************************************************/
  16.  /***********************************************************************************
  17.  
  18.  Wrapper for posix threads (UNIX,VMS,windows)
  19.  
  20.  (C) Rainer Lehrig 2000                                       lehrig@t-online.de
  21.  
  22.  ***********************************************************************************/
  23.  #include <errno.h>
  24.  #include "rlwthread.h"
  25.  #ifdef unix
  26.  #include <sys/time.h>
  27.  #include <sys/socket.h>
  28.  #include <netinet/in.h>
  29.  #include <netdb.h>
  30.  #include <pthread.h>
  31.  #endif
  32.  
  33.  /***************************************/
  34.  /* init attributes with default values */
  35.  /***************************************/
  36.  int rlwthread_attr_init(pthread_attr_t *attr)
  37.  {
  38.  #ifdef _WIN32
  39.    memset(attr,0,sizeof(pthread_attr_t));
  40.    return 0;
  41.  #else
  42.    return pthread_attr_init(attr);
  43.  #endif
  44.  }
  45.  
  46.  /* #pdoku headerlevel 2 ^^wthread_create */
  47.  /*******************************************/
  48.  /* create a thread                         */
  49.  /* tid:  returned thread_id                */
  50.  /* attr: thread creation attributes        */
  51.  /* func: thread start routine              */
  52.  /* arg:  parameter to thread start routine */
  53.  /*******************************************/
  54.  int rlwthread_create(pthread_t *tid, const pthread_attr_t *attr,
  55.                        void *(*func)(void*), void *arg)
  56.  {
  57.  #ifdef _WIN32
  58.    HANDLE handle;
  59.    int ThreadId;
  60.    int dwStackSize = 0;
  61.    if(attr != NULL) dwStackSize = attr->__stacksize;
  62.    handle = CreateThread( NULL,                    /* pointer to thread security attributes */
  63.                           dwStackSize,             /* initial thread stack size, in bytes   */
  64.   (LPTHREAD_START_ROUTINE)func,                    /* pointer to thread function            */
  65.                           arg,                     /* argument for new thread               */
  66.                           0,                       /* creation flags                        */
  67.         (unsigned long *) &ThreadId                /* pointer to returned thread identifier */
  68.                         );
  69.    *tid = (pthread_t) handle;
  70.    if(handle == NULL) return -1;
  71.    else               return 0;
  72.  #else
  73.    return pthread_create(tid,attr,func,arg);
  74.  #endif
  75.  }
  76.  
  77.  void rlwthread_close_handle(pthread_t *tid)
  78.  {
  79.  #ifdef _WIN32
  80.    CloseHandle((HANDLE) *tid);
  81.  #else
  82.    if(tid == NULL) return;
  83.  #endif
  84.  }
  85.  
  86.  /**************************************************************/
  87.  /* terminate a thread                                         */
  88.  /* call this function within a thread to terminate the thead  */
  89.  /* or return from the thread start routine                    */
  90.  /* status: return value from the thread (see wthread_join)    */
  91.  /**************************************************************/
  92.  void rlwthread_exit(void *status)
  93.  {
  94.  #ifdef _WIN32
  95.    DWORD *ptr;
  96.    ptr = (DWORD *) status;
  97.    if(status == NULL) ExitThread((DWORD) 0);
  98.    else               ExitThread(*ptr);
  99.  #else
  100.    pthread_exit(status);
  101.  #endif
  102.  }
  103.  
  104.  /* #pdoku headerlevel 2 ^^wthread_join */
  105.  /************************************/
  106.  /* wait for termination of thread   */
  107.  /* tid:    thread id                */
  108.  /* status: return value from thread */
  109.  /************************************/
  110.  int rlwthread_join(pthread_t tid, void **status)
  111.  {
  112.  #ifdef _WIN32
  113.    DWORD exitcode;
  114.    while(1)
  115.    {
  116.      GetExitCodeThread((HANDLE) tid,&exitcode);
  117.      if(exitcode != STILL_ACTIVE) return exitcode;
  118.      Sleep(10); /* sleep 10 msec */
  119.    }
  120.  #else
  121.    return pthread_join(tid,status);
  122.  #endif
  123.  }
  124.  
  125.  /**************************/
  126.  /* init a mutex           */
  127.  /* mptr: pointer to mutex */
  128.  /* atrr: mutex atrributes */
  129.  /**************************/
  130.  int rlwthread_mutex_init(pthread_mutex_t *mptr,
  131.                            const pthread_mutexattr_t *attr)
  132.  {
  133.  #ifdef _WIN32
  134.    HANDLE handle = CreateMutex(NULL, FALSE, NULL);
  135.    if(handle) *mptr = handle;
  136.    //old InitializeCriticalSection(mptr);
  137.    return 0;
  138.  #else
  139.    return pthread_mutex_init(mptr,attr);
  140.  #endif
  141.  }
  142.  
  143.  /**************************/
  144.  /* destroy a mutex        */
  145.  /* mptr: pointer to mutex */
  146.  /**************************/
  147.  int rlwthread_mutex_destroy(pthread_mutex_t *mptr)
  148.  {
  149.  #ifdef _WIN32
  150.    CloseHandle(*mptr);
  151.    //old DeleteCriticalSection(mptr);
  152.    return 0;
  153.  #else
  154.    return pthread_mutex_destroy(mptr);
  155.  #endif
  156.  }
  157.  
  158.  /**************************/
  159.  /* lock a mutex           */
  160.  /* mptr: pointer to mutex */
  161.  /**************************/
  162.  int rlwthread_mutex_lock(pthread_mutex_t *mptr)
  163.  {
  164.  #ifdef _WIN32
  165.    if(WaitForSingleObject(*mptr, INFINITE) == WAIT_OBJECT_0) return 0;
  166.    //old EnterCriticalSection(mptr); // pointer to critical section object
  167.    return 0;
  168.  #else
  169.    return pthread_mutex_lock(mptr);
  170.  #endif
  171.  }
  172.  
  173.  /********************************/
  174.  /* try to lock a mutex          */
  175.  /* mptr: pointer to mutex       */
  176.  /* return 0 if already locked   */
  177.  /* return !0 if lock sucessfull */
  178.  /********************************/
  179.  
  180.  #ifdef _WIN32
  181.  WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection);
  182.  #endif
  183.  
  184.  int rlwthread_mutex_trylock(pthread_mutex_t *mptr)
  185.  {
  186.  #ifdef _WIN32
  187.    DWORD ret;
  188.  
  189.    ret = WaitForSingleObject(*mptr, 0);
  190.    if(ret == WAIT_OBJECT_0) return 1;
  191.    return 0;
  192.    //old ret = TryEnterCriticalSection(mptr); // pointer to critical section object
  193.    return ret;
  194.  #else
  195.    int ret;
  196.  
  197.    ret = pthread_mutex_trylock(mptr);
  198.    if(ret == EBUSY) return 0;
  199.    return 1;
  200.  #endif
  201.  }
  202.  
  203.  /**************************/
  204.  /* unlock a mutex         */
  205.  /* mptr: pointer to mutex */
  206.  /**************************/
  207.  int rlwthread_mutex_unlock(pthread_mutex_t *mptr)
  208.  {
  209.  #ifdef _WIN32
  210.    ReleaseMutex(*mptr);
  211.    //old LeaveCriticalSection(mptr);
  212.    return 0;
  213.  #else
  214.    return pthread_mutex_unlock(mptr);
  215.  #endif
  216.  }
  217.  
  218.  /**************************/
  219.  /* kill a thread          */
  220.  /* tid handel of thread   */
  221.  /**************************/
  222.  int rlwthread_cancel(pthread_t tid)
  223.  {
  224.  #ifdef _WIN32
  225.    return (int) CloseHandle((HANDLE) tid);
  226.  #else
  227.    return pthread_cancel(tid);
  228.  #endif
  229.  }
  230.  
  231.  /***********************************************/
  232.  /* initialize a semaphore                      */
  233.  /* s is a pointer to a WSEMAPHORE struct       */
  234.  /* cmax is the maximum number of the semaphore */
  235.  /* return 0                                    */
  236.  /***********************************************/
  237.  int rlwrapinit_semaphore(WSEMAPHORE *s, int cmax)
  238.  {
  239.  /* Create a semaphore with initial count=0 max. counts of cmax. */
  240.  #ifdef _WIN32
  241.  
  242.    s->cmax = cmax;
  243.    s->hSemaphore = CreateSemaphore(
  244.      NULL,   /* no security attributes */
  245.      0,      /* initial count */
  246.      cmax,   /* maximum count */
  247.      NULL);  /* unnamed semaphore */
  248.  
  249.    if(s->hSemaphore == NULL) return -1; /* Check for error. */
  250.    return 0;
  251.  
  252.  #else
  253.  
  254.    s->cmax   = cmax;
  255.    s->nready = 0;
  256.    rlwthread_mutex_init(&s->mutex, NULL);
  257.    pthread_cond_init(&s->cond, NULL);
  258.    return 0;
  259.  
  260.  #endif
  261.  }
  262.  
  263.  int rlwrapdestroy_semaphore(WSEMAPHORE *s)
  264.  {
  265.  #ifdef _WIN32
  266.    CloseHandle(s->hSemaphore);
  267.  #else
  268.    rlwthread_mutex_destroy(&s->mutex);
  269.  #endif
  270.    return 0;
  271.  }
  272.  
  273.  /***********************************************************************/
  274.  /* increment a semaphore                                               */
  275.  /* s is a pointer to a WSEMAPHORE struct                               */
  276.  /* the producer will call this function whenever new data is available */
  277.  /* return 0=OK -1=error                                                */
  278.  /***********************************************************************/
  279.  int rlwrapincrement_semaphore(WSEMAPHORE *s)
  280.  {
  281.  /* Increment the count of the semaphore. */
  282.  #ifdef _WIN32
  283.  
  284.    if(!ReleaseSemaphore(
  285.          s->hSemaphore,  /* handle of semaphore */
  286.          1,              /* increase count by one */
  287.          NULL) )         /* not interested in previous count */
  288.    {
  289.      return -1; /* Deal with the error. */
  290.    }
  291.    return 0;
  292.  
  293.  #else
  294.  
  295.    pthread_mutex_lock(&s->mutex);
  296.    if(s->nready == 0) pthread_cond_signal(&s->cond);
  297.    s->nready++;
  298.    pthread_mutex_unlock(&s->mutex);
  299.    return 0;
  300.  
  301.  #endif
  302.  }
  303.  
  304.  /*********************************************************************************/
  305.  /* wait for a semaphore                                                          */
  306.  /* s is a pointer to a WSEMAPHORE struct                                         */
  307.  /* the consumer will call this function to wait for new data to become available */
  308.  /* return 0                                                                      */
  309.  /*********************************************************************************/
  310.  int rlwrapwait_semaphore(WSEMAPHORE *s)
  311.  {
  312.  #ifdef _WIN32
  313.  
  314.    int ret;
  315.    ret = WaitForSingleObject(
  316.          s->hSemaphore,   /* handle of semaphore */
  317.          INFINITE);       /* infinite time-out interval */
  318.    if(ret) return 0;
  319.    return 0;
  320.  
  321.  #else
  322.  
  323.    pthread_mutex_lock(&s->mutex);
  324.    while(s->nready == 0)
  325.    {
  326.      pthread_cond_wait(&s->cond,&s->mutex);
  327.    }  
  328.    s->nready--;
  329.    pthread_mutex_unlock(&s->mutex);
  330.    return 0;
  331.  
  332.  #endif
  333.  }
  334.  
  335.  int rlwthread_sleep(long msec)
  336.  {
  337.  #ifdef _WIN32
  338.    Sleep(msec);
  339.    return 0;
  340.  #endif
  341.  
  342.  #ifdef unix
  343.    fd_set wset,rset,eset;
  344.    struct timeval timeout;
  345.  
  346.    FD_ZERO(&rset);
  347.    FD_ZERO(&wset);
  348.    FD_ZERO(&eset);
  349.    timeout.tv_sec  = msec / 1000;
  350.    timeout.tv_usec = (msec % 1000) * 1000;
  351.    select(1,&rset,&wset,&eset,&timeout);
  352.    return 0;
  353.  #endif
  354.  
  355.  #ifdef __VMS
  356.    struct timespec interval;
  357.  
  358.    interval.tv_sec  =  msec / 1000;
  359.    interval.tv_nsec = (msec % 1000) * 1000 * 1000; /* wait msec msec */
  360.    pthread_delay_np(&interval);
  361.    return 0;
  362.  #endif
  363.  }
  364.  
  365.  void rlsleep(long msec)
  366.  {
  367.    rlwthread_sleep(msec);
  368.  }
  369.  /*** test routine ***/
  370.  /**************************************************************/
  371.  /* This is an example how to use the wthread_xxx functions    */
  372.  /**************************************************************/
  373.  #define TESTINGx
  374.  #ifdef  TESTING
  375.  #include "stdio.h"
  376.  #include "stdlib.h"
  377.  #ifndef _WIN32
  378.  #include "unistd.h"
  379.  #endif
  380.  
  381.  /******************************************/
  382.  /* here we define 2 mutexes (semaphores)  */
  383.  /* the mutexes are global two all threads */
  384.  /******************************************/
  385.  pthread_mutex_t mutex1, mutex2;
  386.  WSEMAPHORE semaphore;
  387.  
  388.  /************************************************************************/
  389.  /* this is the tread function                                           */
  390.  /* it's name is given as parameter to wthread_create                    */
  391.  /* *arg is an argument given by the last parameter of wthread_create    */
  392.  /* you can get the return value by pthread_join (status)                */
  393.  /************************************************************************/
  394.  void *thread(void *arg)
  395.  {
  396.    int i=0;
  397.    printf("thread start : %s\n",(const char *) arg);
  398.    while(i++ < 50)
  399.    {
  400.      rlwrapwait_semaphore(&semaphore);
  401.      printf("thread %d\n",i);
  402.      /* sleep(1); */
  403.    }
  404.    return NULL;
  405.  }
  406.  
  407.  int main()
  408.  {
  409.    pthread_t tid; /* this is the thread_id */
  410.    void *status;  /* this is the return value of the tread */
  411.    int i;
  412.  
  413.    /*****************************************************************************/
  414.    /* here we initialize 2 mutexes                                              */
  415.    /* the mutexes are defined global to all threads                             */
  416.    /* for compatibility with MSWINDOWS the second parameter should be NULL      */
  417.    /*                                                                           */
  418.    /* in order to mark critical sections we can now use the following functions */
  419.    /* wthread_mutex_lock                                                        */
  420.    /* wthread_mutex_unlock                                                      */
  421.    /* if a mutex is locked by a thread and an other thread is calling           */
  422.    /* wthread_mutex_lock it will be blocked until the first thread calls        */
  423.    /* the wthread_mutex_unlock function                                         */
  424.    /*                                                                           */
  425.    /* this function is the reverse of wthread_mutex_init                        */
  426.    /* wthread_mutex_destroy                                                     */
  427.    /*****************************************************************************/
  428.    rlwthread_mutex_init(&mutex1, NULL);
  429.    rlwthread_mutex_init(&mutex2, NULL);
  430.  
  431.    rlwrapinit_semaphore(&semaphore, 1000);
  432.    printf("create a thread\n");
  433.    /****************************************************************/
  434.    /* this call will create a new thread                           */
  435.    /* tid is the returned thread_id                                */
  436.    /*     you can use this id for example in wthread_join          */
  437.    /* in this example the second parameter is NULL                 */
  438.    /*     you can call wthread_attr_init(pthread_attr_t *attr)     */
  439.    /*     to initialize the start attributes                       */
  440.    /*     pthread_attr_t attr;                                     */
  441.    /*     wthread_attr_init(&attr);                                */
  442.    /*     wthread_create(&tid, &attr, thread, "hello thread");     */
  443.    /* thread is the name of the thread function (see above)        */
  444.    /* the last parameter is given to the thread function           */
  445.    /****************************************************************/
  446.    rlwthread_create(&tid, NULL, thread, "hello thread");
  447.  
  448.    i=0;
  449.    while(i++ < 50)
  450.    {
  451.      printf("main %d\n",i);
  452.      rlwrapincrement_semaphore(&semaphore);
  453.      if(i%4 == 0) Sleep(10);
  454.    }
  455.  
  456.    printf("waiting for thread\n");
  457.    /*****************************************************/
  458.    /* this call waits for the termination of thread tid */
  459.    /* the return value of the thread is given to status */
  460.    /*****************************************************/
  461.    rlwthread_join(tid, &status);
  462.    printf("finish\n");
  463.    return 0;
  464.  }
  465.  #endif
  466.