"Fossies" - the Fresh Open Source Software Archive

Member "erltools/pub/library/semaphop.h.old" (20 Jan 2004, 16441 Bytes) of package /linux/misc/old/erltools-4.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 /*! 
    2    \file semaphop.h
    3    \brief Critical section and sempahore library
    4    \author P. MOREL (Dassault Data Services)
    5    \author COPYRIGHT (C) 2002 MITSUBISHI ELECTRIC CORPORATION - ALL RIGHT RESERVED
    6    \version 1.0
    7    $Revision: 1.0 $
    8    \date 09/2002
    9    */
   10 #ifndef SEMPAHOP_HEADER
   11 #define SEMPAHOP_HEADER 
   12 #include "smtoken.h"
   13 #if defined(HAS_POSIX_CRITICAL)
   14 #define HANDLE_CRITICAL pthread_mutex_t  
   15 #define CRITICAL_SECTION HANDLE_CRITICAL *
   16 #define COND_VARIABLE pthread_cond_t
   17 #include <pthread.h>
   18 
   19 inline void InitializeCriticalSection ( HANDLE_CRITICAL **handle )
   20 {
   21     *handle = new pthread_mutex_t ;
   22     
   23     int ret = pthread_mutex_init(*handle, 0);
   24     
   25     if ( ret ) {
   26         fprintf(stderr, "Error in InitializeCriticalSection : %d, in %s, line %d\n", ret, __FILE__, __LINE__);
   27     }
   28 }
   29 
   30 inline void EnterCriticalSection ( HANDLE_CRITICAL **handle )
   31 {
   32     int ret = pthread_mutex_lock(*handle);
   33     
   34     if ( ret ) {
   35         fprintf(stderr, "Error in EnterCriticalSection : %d, in %s, line %d\n", ret, __FILE__, __LINE__);
   36     }
   37 }
   38 
   39 inline void LeaveCriticalSection ( HANDLE_CRITICAL **handle )
   40 {
   41     int ret = pthread_mutex_unlock(*handle);
   42     
   43     if ( ret ) {
   44         fprintf(stderr, "Error in LeaveCriticalSection : %d, in %s, line %d\n", ret, __FILE__, __LINE__);
   45     }
   46 }
   47 
   48 inline void DeleteCriticalSection ( HANDLE_CRITICAL **handle )
   49 {
   50     if ( *handle ) {
   51         int errCode = pthread_mutex_destroy(*handle);
   52         if ( errCode != 0 ) {
   53             fprintf(stderr, "Error in DeleteCriticalSection : %d, in %s, line %d\n", errCode, __FILE__, __LINE__);
   54         }
   55         delete *handle ;
   56         *handle = 0 ;
   57     }
   58 }
   59 
   60 inline int InitCondition ( COND_VARIABLE *pCond )
   61 {
   62     pthread_cond_init(pCond, 0);
   63     return 0 ;
   64 }
   65 
   66 inline int WakeUpOnCondition ( COND_VARIABLE *pCond )
   67 {
   68     pthread_cond_signal(pCond);
   69     return 0 ;
   70 }
   71 
   72 inline int WakeUpOnConditionTime ( COND_VARIABLE *pCond )
   73 {
   74     pthread_cond_signal(pCond);
   75     return 0 ;
   76 }
   77 
   78 inline int SleepUntilCondition ( COND_VARIABLE *pCond, CRITICAL_SECTION *sC, struct timespec *pTime = 0 )
   79 {
   80     int result = 0 ;
   81     
   82     if ( pTime ) 
   83         result = pthread_cond_timedwait(pCond, *sC, pTime);
   84     else 
   85         pthread_cond_wait(pCond, *sC);
   86     return result ;
   87 }
   88 
   89 inline int DeleteCondition ( COND_VARIABLE *pCond )
   90 {
   91     if ( pCond ) {
   92         pthread_cond_destroy(pCond);
   93     }
   94     return 0 ;
   95 }
   96 
   97 inline struct timespec *SetTimeOffset ( struct timeval &tval, struct timespec &sTime )
   98 {
   99     struct timespec *pTime = 0 ;
  100     
  101     if ( tval.tv_sec != 0 || tval.tv_usec != 0 ) {
  102 #if defined(UNDERSCORE_FTIME)
  103         {
  104             struct _timeb tstruct ;
  105             _ftime(&tstruct);
  106             sTime.tv_sec = tstruct.time + tval.tv_sec ;
  107             sTime.tv_nsec = (tstruct.millitm * 1000 + tval.tv_usec) * 1000 ;
  108         }
  109 #else 
  110         {
  111             struct timeb tstruct ;
  112             ::ftime(&tstruct);
  113             sTime.tv_sec = tstruct.time + tval.tv_sec ;
  114             sTime.tv_nsec = (tstruct.millitm * 1000 + tval.tv_usec) * 1000 ;
  115         }
  116 #endif
  117         pTime = &sTime ;
  118     }
  119     return pTime ;
  120 }
  121 #elif defined(ON_W)
  122 #define WaitForSingleObjectU WaitForSingleObject
  123 #define ReleaseSemaphoreU ReleaseSemaphore
  124 typedef HANDLE  MutexVariable ;
  125 typedef HANDLE  EventVariable ;
  126 #define timespec timeval
  127 DWORD   ESignal (HANDLE h1, HANDLE h2, DWORD milli) ;
  128 
  129 inline void InitializeCriticalSection ( MutexVariable *pMutex )
  130 {
  131     
  132     DWORD               ident ;    // ident 
  133     SECURITY_ATTRIBUTES security ; // security
  134     
  135     security.nLength = sizeof(SECURITY_ATTRIBUTES);
  136     security.lpSecurityDescriptor = 0 ;
  137     security.bInheritHandle = true ;
  138     *pMutex = CreateMutex(&security, false, 0);
  139     if ( !*pMutex ) {
  140         fprintf(stderr, "Error in InitializeCriticalSection : %d, in %s, line %d\n", *pMutex, __FILE__, __LINE__);
  141     }
  142 }
  143 
  144 inline void EnterCriticalSection ( MutexVariable *pMutex )
  145 {
  146     DWORD   ret = WaitForSingleObject(*pMutex, INFINITE);
  147     
  148     if ( ret != WAIT_OBJECT_0 ) {
  149         fprintf(stderr, "Error in EnterCriticalSection : %d, in %s, line %d\n", ret, __FILE__, __LINE__);
  150     }
  151 }
  152 
  153 inline void LeaveCriticalSection ( MutexVariable *pMutex )
  154 {
  155     bool    ret = ReleaseMutex(*pMutex);
  156     
  157     if ( !ret ) {
  158         fprintf(stderr, "Error in LeaveCriticalSection : %d, in %s, line %d\n", ret, __FILE__, __LINE__);
  159     }
  160 }
  161 
  162 inline void DeleteCriticalSection ( MutexVariable *pMutex )
  163 {
  164     if ( *pMutex ) {
  165         CloseHandle(*pMutex);
  166         *pMutex = 0 ;
  167     }
  168 }
  169 
  170 inline int InitCondition ( EventVariable *pEvent )
  171 {
  172     
  173     DWORD               ident ;    // ident 
  174     SECURITY_ATTRIBUTES security ; // security
  175     
  176     security.nLength = sizeof(SECURITY_ATTRIBUTES);
  177     security.lpSecurityDescriptor = 0 ;
  178     security.bInheritHandle = true ;
  179     *pEvent = CreateEvent(&security, true, false, 0);
  180     if ( !*pEvent ) {
  181         fprintf(stderr, "Error in InitializeCriticalSection : %d, in %s, line %d\n", *pEvent, __FILE__, __LINE__);
  182     }
  183     return 0 ;
  184 }
  185 
  186 inline int WakeUpOnCondition ( EventVariable *pEvent )
  187 {
  188     int ret = PulseEvent(*pEvent);
  189     
  190     return 0 ;
  191 }
  192 
  193 inline int WakeUpOnConditionTime ( EventVariable *pEvent )
  194 {
  195     int ret = PulseEvent(*pEvent);
  196     
  197     return 0 ;
  198 }
  199 
  200 inline int SleepUntilCondition ( EventVariable *pCond, MutexVariable *pSc, struct timespec *pTime = 0 )
  201 {
  202     int result = 0 ;
  203     
  204     if ( pTime ) 
  205         result = ESignal(*pSc, *pCond, pTime -> tv_sec * 1000 + pTime -> tv_usec / 1000) != WAIT_OBJECT_0 ? 1 : 0 ;
  206     else 
  207         result = ESignal(*pSc, *pCond, INFINITE);
  208     EnterCriticalSection(pSc);
  209     return result ;
  210 }
  211 
  212 inline int DeleteCondition ( EventVariable *pEvent )
  213 {
  214     int ret = CloseHandle(*pEvent);
  215     
  216     return 0 ;
  217 }
  218 
  219 inline struct timespec *SetTimeOffset ( struct timeval &tval, struct timespec &sTime )
  220 {
  221     struct timespec *pTime = 0 ;
  222     
  223     if ( tval.tv_sec != 0 || tval.tv_usec != 0 ) {
  224         sTime.tv_sec = tval.tv_sec ;
  225         sTime.tv_usec = tval.tv_usec ;
  226         pTime = &sTime ;
  227     }
  228     return pTime ;
  229 }
  230 #endif
  231 
  232 /*!
  233    \class Semaphop
  234    \brief management of a stock of nuts (message)
  235    \author P.MOREL
  236    */
  237 
  238 class Semaphop {
  239     
  240     public :
  241     
  242         Semaphop ()
  243             : nbMaxRessource(0),  tooMuchRessources(0),  noRessourcesLeft(0),  nbMaxCurrent(0),  pvOn(true)
  244         {
  245             InitializeCriticalSection(&ressourceSC);
  246             ReInit();
  247             tval.tv_sec = tval.tv_usec = 0 ;
  248         }
  249         
  250         Semaphop ( unsigned int initRessource )
  251             : nbMaxRessource(initRessource),  tooMuchRessources(0),  noRessourcesLeft(0),  nbMaxCurrent(0),  pvOn(true)
  252         {
  253             InitializeCriticalSection(&ressourceSC);
  254             ReInit();
  255             tval.tv_sec = tval.tv_usec = 0 ;
  256         }
  257         
  258         virtual ~Semaphop ()
  259         {
  260             DeleteCriticalSection(&ressourceSC);
  261             DeleteCondition(&condGetRessource);
  262             DeleteCondition(&condPutRessource);
  263         }
  264         
  265         void CreateLimitedRessourceStock ( int iNbMax )
  266         {
  267             nbMaxRessource = iNbMax ;
  268             usedRessources = 0 ;
  269         }
  270         
  271         void ReInit ()
  272         {
  273             InitCondition(&condGetRessource);
  274             InitCondition(&condPutRessource);
  275             usedRessources = 0 ;
  276         }
  277         
  278         /*!
  279            \brief method to be called before sending a message
  280            */
  281         void PutRessourceBegin ( unsigned int nbRessource = 1, bool withTimeVal = false )
  282         {
  283             int timedOut = 0 ;
  284             
  285             if ( !On() ) 
  286                 return ;
  287             
  288             // say "hello mister ressource ..."
  289             EnterCriticalSection(&ressourceSC);
  290             while ( nbMaxRessource > 0 && usedRessources + nbRessource > nbMaxRessource ) {
  291                 
  292                 // wanna stock nut?
  293                 struct timespec *pTime = 0 ;
  294                 struct timespec sTime ;
  295                 
  296                 // set time limit
  297                 if ( withTimeVal ) 
  298                     pTime = SetTimeOffset(tval, sTime);
  299                 
  300                 // wait
  301                 timedOut = SleepUntilCondition(&condPutRessource, &ressourceSC, pTime);
  302                 if ( timedOut ) 
  303                     break ;
  304             }
  305             
  306             // take this nut for winter
  307             if ( !timedOut ) {
  308                 usedRessources += nbRessource ;
  309                 if ( nbMaxRessource > 0 && usedRessources > nbMaxRessource ) {
  310                     PrintRessourceStockInformation();
  311                     fprintf(stderr, "error in %s, line %d\n", __FILE__, __LINE__);
  312                     exit(1);
  313                 }
  314             }
  315             
  316             // update stock info
  317             UpdateRessourceStockInformation();
  318         }
  319         
  320         /*!
  321            \brief method to be called after sending a message
  322            */
  323         void PutRessourceEnd ()
  324         {
  325             if ( !On() ) 
  326                 return ;
  327             
  328             // still some place for stock ?
  329             if ( usedRessources == nbMaxRessource ) {
  330                 tooMuchRessources++ ;
  331             }
  332             
  333             // 
  334             WakeUpOnCondition(&condPutRessource);
  335             
  336             // just one nut, one whisky and one beer
  337             WakeUpOnCondition(&condGetRessource);
  338             
  339             // say "good bye mister squirrel"
  340             LeaveCriticalSection(&ressourceSC);
  341         }
  342         
  343         /*!
  344            \brief method to be called for freeing ressource
  345            */
  346         void FreeRessource ( unsigned int nbRessource = 1, bool withTimeVal = false )
  347         {
  348             PutRessourceBegin(nbRessource, withTimeVal);
  349             PutRessourceEnd();
  350         }
  351         
  352         void PutRessource ( unsigned int nbRessource = 1, bool withTimeVal = false )
  353         {
  354             FreeRessource(nbRessource, withTimeVal);
  355         }
  356         
  357         /*!
  358            \brief method to be called before receiving a message
  359            */
  360         void GetRessourceBegin ( unsigned int nbRessource = 1, bool withTimeVal = false )
  361         {
  362             int timedOut = 0 ;
  363             
  364             if ( !On() ) 
  365                 return ;
  366             
  367             // say "hello mister squirrel"
  368             EnterCriticalSection(&ressourceSC);
  369             while ( usedRessources < nbRessource ) {
  370                 
  371                 // wanna stock nut?
  372                 struct timespec *pTime = 0 ;
  373                 struct timespec sTime ;
  374                 
  375                 // set time limit
  376                 if ( withTimeVal ) 
  377                     pTime = SetTimeOffset(tval, sTime);
  378                 
  379                 // want some nut ?
  380                 timedOut = SleepUntilCondition(&condGetRessource, &ressourceSC, pTime);
  381                 if ( timedOut ) 
  382                     break ;
  383             }
  384             
  385             // if threre is no more nut ... a problem occurs
  386             if ( !timedOut ) {
  387                 if ( usedRessources <= 0 ) {
  388                     PrintRessourceStockInformation();
  389                     fprintf(stderr, "error in %s, line %d\n", __FILE__, __LINE__);
  390                     exit(1);
  391                 }
  392                 
  393                 // hey mister quirrel, you're talking to me, give me a nut !!!
  394                 usedRessources -= nbRessource ;
  395             }
  396             UpdateRessourceStockInformation();
  397         }
  398         
  399         /*!
  400            \brief method to be called after receiving a message
  401            */
  402         void GetRessourceEnd ()
  403         {
  404             if ( !On() ) 
  405                 return ;
  406             
  407             // is there any nut for other ressource ?
  408             // if ( usedRessources > 0 ) {
  409             WakeUpOnCondition(&condGetRessource);
  410             //}
  411             // is there some new available place for stock ??
  412             WakeUpOnCondition(&condPutRessource);
  413             
  414             // say "good bye mister ressource"
  415             LeaveCriticalSection(&ressourceSC);
  416         }
  417         
  418         /*!
  419            \brief method to be called for freeing ressource
  420            */
  421         void GetRessource ( unsigned int nbRessource = 1, bool withTimeVal = false )
  422         {
  423             GetRessourceBegin(nbRessource, withTimeVal);
  424             GetRessourceEnd();
  425         }
  426         
  427         /*!
  428            \brief method to be called for freeing ressource
  429            */
  430         void LookRessource ( unsigned int nbRessource = 1, bool withTimeVal = false )
  431         {
  432             GetRessourceBegin(nbRessource, withTimeVal);
  433             
  434             // hey mister quirrel, you're talking to me, give me back my nut !!!
  435             usedRessources += nbRessource ;
  436             UpdateRessourceStockInformation();
  437             GetRessourceEnd();
  438         }
  439         
  440         void PrintRessourceStockInformation ( void )
  441         {
  442             fprintf(stderr, "max resource %d \t current resource %d \t nb saturated %d \t nb empty stock %d\n", nbMaxRessource, usedRessources
  443                 , tooMuchRessources, noRessourcesLeft);
  444         }
  445         
  446         void UpdateRessourceStockInformation ( void )
  447         {
  448             if ( usedRessources == nbMaxRessource ) 
  449                 tooMuchRessources++ ;
  450             if ( usedRessources > nbMaxCurrent ) 
  451                 nbMaxCurrent = usedRessources ;
  452             if ( usedRessources == 0 ) {
  453                 noRessourcesLeft++ ;
  454             }
  455         }
  456         
  457         int GetStockInfo ()
  458         {
  459             
  460             // say "hello mister ressource"
  461             EnterCriticalSection(&ressourceSC);
  462             
  463             int iNbRessource = usedRessources ;
  464             
  465             // say "good bye mister ressource"
  466             LeaveCriticalSection(&ressourceSC);
  467             return iNbRessource ;
  468         }
  469         
  470         // TimeVal : TimeVal modifier
  471         // parameters :
  472         //               timeVal : new value for timeval
  473         void TimeVal ( struct timeval &val )
  474         {
  475             
  476             // set timeval struct
  477             tval.tv_sec = val.tv_sec ;
  478             tval.tv_usec = val.tv_usec ;
  479         }
  480         
  481         // TimeVal : get time val
  482         struct timeval &TimeVal ()
  483         {
  484             return tval ;
  485         }
  486         
  487         // On : change state of semaphop
  488         Semaphop &On ( bool on )
  489         {
  490             pvOn = on ;
  491             return *this ;
  492         }
  493         
  494         // On : get state of semaphop
  495         bool On ()
  496         {
  497             return pvOn ;
  498         }
  499     
  500     private :
  501     
  502 #if defined(ON_W)
  503         EventVariable   condGetRessource ;
  504         EventVariable   condPutRessource ;
  505         MutexVariable   ressourceSC ;
  506 #else 
  507         COND_VARIABLE       condGetRessource ;
  508         COND_VARIABLE       condPutRessource ;
  509         CRITICAL_SECTION    ressourceSC ;
  510 #endif
  511         
  512         int             nbMaxRessource ;
  513         unsigned int    usedRessources ;
  514         int             tooMuchRessources ;
  515         unsigned int    nbMaxCurrent ;
  516         int             noRessourcesLeft ;
  517         struct timeval   tval ;
  518         bool            pvOn ;
  519 };
  520 
  521 class CNutStock : public Semaphop {
  522     
  523     public :
  524     
  525         CNutStock ()
  526             : Semaphop()
  527         {}
  528         
  529         virtual ~CNutStock () {}
  530         
  531         void createLimitedNutStock ( int iNbMaxNuts )
  532         {
  533             CreateLimitedRessourceStock(iNbMaxNuts);
  534         }
  535         
  536         /*!
  537            \brief method to be called before sending a message
  538            */
  539         void putNutBegin ()
  540         {
  541             PutRessourceBegin();
  542         }
  543         
  544         /*!
  545            \brief method to be called after sending a message
  546            */
  547         void putNutEnd ()
  548         {
  549             PutRessourceEnd();
  550         }
  551         
  552         /*!
  553            \brief method to be called before receiving a message
  554            */
  555         void getNutBegin ()
  556         {
  557             GetRessourceBegin();
  558         }
  559         
  560         /*!
  561            \brief method to be called after receiving a message
  562            */
  563         void getNutEnd ()
  564         {
  565             GetRessourceEnd();
  566         }
  567         
  568         void printNutStockInformation ( void )
  569         {
  570             PrintRessourceStockInformation();
  571         }
  572         
  573         void updateNutStockInformation ( void )
  574         {
  575             UpdateRessourceStockInformation();
  576         }
  577         
  578         int getStockInfo ()
  579         {
  580             return GetStockInfo();
  581         }
  582 };
  583 #endif