PThreadBarrier.c++
上传用户:chinafayin
上传日期:2022-04-05
资源大小:153k
文件大小:5k
源码类别:

并行计算

开发平台:

Visual C++

  1. //
  2. // OpenThread library, Copyright (C) 2002 - 2003  The Open Thread Group
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. // Lesser General Public License for more details.
  13. // 
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. //
  18. //
  19. // PThreadBarrier.c++ - C++ Barrier class built on top of POSIX threads.
  20. // ~~~~~~~~~~~~~~~~~~
  21. //
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. #include "../Barrier"
  25. #include "PThreadBarrierPrivateData.h"
  26. using namespace OpenThreads;
  27. //----------------------------------------------------------------------------
  28. // This cancel cleanup handler is necessary to ensure that the barrier's
  29. // mutex gets unlocked on cancel. Otherwise deadlocks could occur with 
  30. // later joins.
  31. //
  32. void barrier_cleanup_handler(void *arg) {
  33.     pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(arg);
  34.     
  35.     pthread_mutex_unlock(mutex);
  36. }
  37. //----------------------------------------------------------------------------
  38. //
  39. // Decription: Constructor
  40. //
  41. // Use: public.
  42. //
  43. Barrier::Barrier(int numThreads) {
  44.     PThreadBarrierPrivateData *pd = new PThreadBarrierPrivateData();
  45.     pd->cnt = 0;
  46.     pd->phase = 0;
  47.     pd->maxcnt = numThreads;
  48.     pthread_mutexattr_t mutex_attr;
  49.     pthread_mutexattr_init( &mutex_attr );
  50. #ifndef __linux__ // (not available until NPTL) [
  51.     pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
  52. #endif // ] __linux__
  53. #ifdef ALLOW_PRIORITY_SCHEDULING // [
  54. #ifdef __sun // [
  55.     pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_NONE);
  56. #endif // ] __sun
  57.     //-------------------------------------------------------------------------
  58.     // Initialization is a bit tricky, since we have to be able to be aware
  59.     // that on many-to-many execution vehicle systems, we may run into
  60.     // priority inversion deadlocks if a mutex is shared between threads
  61.     // of differing priorities.  Systems that do this should provide the 
  62.     // following protocol attributes to prevent deadlocks.  Check at runtime.
  63.     //
  64.     //  PRIO_INHERIT causes any thread locking the mutex to temporarily become
  65.     //  the same priority as the highest thread also blocked on the mutex. 
  66.     //  Although more expensive, this is the prefered method.
  67.     //
  68.     //  PRIO_PROTECT causes any thread locking the mutex to assume the priority
  69.     //  specified by setprioceiling.  pthread_mutex_lock will fail if
  70.     //  the priority ceiling is lower than the thread's priority.  Therefore,
  71.     //  the priority ceiling must be set to the max priority in order to 
  72.     //  garantee no deadlocks will occur.
  73.     //
  74. #if defined (_POSIX_THREAD_PRIO_INHERIT) || defined (_POSIX_THREAD_PRIO_PROTECT) // [
  75.     if(sysconf(_POSIX_THREAD_PRIO_INHERIT)) {
  76. pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
  77.     } else if (sysconf(_POSIX_THREAD_PRIO_PROTECT)) {
  78. int th_policy;
  79. struct sched_param th_param;
  80. pthread_getschedparam(pthread_self(), &th_policy, &th_param);
  81. pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT);
  82. pthread_mutexattr_setprioceiling(&mutex_attr, 
  83.  sched_get_priority_max(th_policy));
  84.     }
  85. #endif // ] Priority sheduling
  86. #endif // ] ALLOW_PRIORITY_SCHEDULING
  87.     pthread_mutex_init(&(pd->lock), &mutex_attr);
  88.     pthread_cond_init(&(pd->cond), NULL);
  89.     _prvData = static_cast<void *>(pd);
  90. }
  91. //----------------------------------------------------------------------------
  92. //
  93. // Decription: Destructor
  94. //
  95. // Use: public.
  96. //
  97. Barrier::~Barrier() {
  98.     PThreadBarrierPrivateData *pd =
  99.         static_cast<PThreadBarrierPrivateData*>(_prvData);
  100.     pthread_mutex_destroy(&(pd->lock));
  101.     pthread_cond_destroy(&(pd->cond));
  102.     delete pd;
  103. }
  104. //----------------------------------------------------------------------------
  105. //
  106. // Decription: Reset the barrier to its original state
  107. //
  108. // Use: public.
  109. //
  110. void Barrier::reset() {
  111.     
  112.     PThreadBarrierPrivateData *pd =
  113.         static_cast<PThreadBarrierPrivateData*>(_prvData);
  114.     pd->cnt = 0;
  115.     pd->phase = 0;
  116. }
  117. //----------------------------------------------------------------------------
  118. //
  119. // Decription: Block until numThreads threads have entered the barrier.
  120. //
  121. // Use: public.
  122. //
  123. void Barrier::block(unsigned int numThreads) {
  124.     PThreadBarrierPrivateData *pd =
  125.         static_cast<PThreadBarrierPrivateData*>(_prvData);
  126.     if(numThreads != 0) pd->maxcnt = numThreads;
  127.     int my_phase;
  128.     pthread_mutex_lock(&(pd->lock));
  129.     my_phase = pd->phase;
  130.     ++pd->cnt;
  131.     
  132.     if (pd->cnt == pd->maxcnt) {             // I am the last one
  133. pd->cnt = 0;                         // reset for next use
  134. pd->phase = 1 - my_phase;            // toggle phase
  135. pthread_cond_broadcast(&(pd->cond));
  136.     } 
  137.     while (pd->phase == my_phase) {
  138. pthread_cleanup_push(barrier_cleanup_handler, &(pd->lock));
  139. pthread_cond_wait(&(pd->cond), &(pd->lock));
  140. pthread_cleanup_pop(0);
  141.     }
  142.     pthread_mutex_unlock(&(pd->lock));
  143. }