* thread.h (class List): Move inline code inside class
declaration. (List::forEach): Change callback parameter to template class member functionpointer. (pthread_keys::fixup_before_fork): Change to inline. Use List::forEach to fixup keys. (pthread_keys::fixup_after_fork): Ditto. (pthread_keys::runAllDestructors): Ditto. (pthread_key::saveAKey): Remove. (pthread_key::restoreAKey): Ditto. (pthread_key::destroyAKey): Ditto. (pthread_key::run_destructor): Rename to runDestructor. (pthread_mutex::fixup_after_fork): Change to inline. Use List::forEach to fixup mutexes after a fork. (pthread_mutex::FixupAfterFork): New method. (pthread_mutex::mutexes): New member. (pthread_cond::fixup_after_fork): Change to inline. Use List::forEach to fixup conds after a fork. (pthread_cond::FixupAfterFork): New method. (pthread_cond::conds): New member. (pthread_rwlock::fixup_after_fork): Change to inline. Use List::forEach to fixup rwlocks after a fork. (pthread_rwlock::FixupAfterFork): New method. (pthread_rwlock::rwlocks): New member. (semaphore::fixup_after_fork): Change to inline. Use List::forEach to fixup mutexes after a fork. (semaphore::FixupAfterFork): New method. (semaphore::semaphores): New member. (MTinterface::mutexs): Remove. (MTinterface::conds): Ditto. (MTinterface::rwlocks): Ditto. (MTinterface::semaphores): Ditto. (pthread_equal): Add extern "C". (pthread_mutex_lock): Ditto. * thread.cc (MTinterface::fixup_after_fork): Change fixup_after_fork calls for pthread objects. (semaphore::conds): Instantiate. (pthread_cond::pthread_cond): Use List::Insert rather than custom list code. (pthread_cond::~pthread_cond): Use List::Remove rather than custom list code. (pthread_cond::fixup_after_fork): Rename to FixupAfterFork. (pthread_rwlock::rwlocks): Instantiate. (pthread_rwlock::pthread_crwlock): Use List::Insert rather than custom list code. (pthread_rwlock::~pthread_rwlock): Use List::Remove rather than custom list code. (pthread_rwlock::fixup_after_fork): Rename to FixupAfterFork. (pthread_key::saveAKey): Remove. (pthread_key::fixup_before_fork): Ditto. (pthread_key::restoreAKey): Ditto. (pthread_key::fixup_after_fork): Ditto. (pthread_key::destroyAKey): Ditto. (pthread_key::runAllDestructors): Ditto. (pthread_key::run_destructor): Rename to runDestructor. (pthread_mutex::mutexes): Instantiate. (pthread_mutex::pthread_mutex): Use List::Insert rather than custom list code. (pthread_mutex::~pthread_mutex): Use List::Remove rather than custom list code. (pthread_mutex::fixup_after_fork): Rename to FixupAfterFork. (semaphore::conds): Instantiate. (semaphore::semaphore): Use List::Insert rather than custom list code. (semaphores::~semaphore): Use List::Remove rather than custom list code. (semaphore::fixup_after_fork): Rename to FixupAfterFork.
This commit is contained in:
		| @@ -1,3 +1,74 @@ | ||||
| 2003-03-23  Thomas Pfaff  <tpfaff@gmx.net> | ||||
|  | ||||
| 	* thread.h (class List): Move inline code inside class | ||||
| 	declaration. | ||||
| 	(List::forEach): Change callback parameter to template class | ||||
| 	member function	pointer. | ||||
| 	(pthread_keys::fixup_before_fork): Change to inline. Use | ||||
| 	List::forEach to fixup keys. | ||||
| 	(pthread_keys::fixup_after_fork): Ditto. | ||||
| 	(pthread_keys::runAllDestructors): Ditto. | ||||
| 	(pthread_key::saveAKey): Remove. | ||||
| 	(pthread_key::restoreAKey): Ditto. | ||||
| 	(pthread_key::destroyAKey): Ditto. | ||||
| 	(pthread_key::run_destructor): Rename to runDestructor. | ||||
| 	(pthread_mutex::fixup_after_fork): Change to inline. Use | ||||
| 	List::forEach to fixup mutexes after a fork. | ||||
| 	(pthread_mutex::FixupAfterFork): New method. | ||||
| 	(pthread_mutex::mutexes): New member. | ||||
| 	(pthread_cond::fixup_after_fork): Change to inline. Use | ||||
| 	List::forEach to fixup conds after a fork. | ||||
| 	(pthread_cond::FixupAfterFork): New method. | ||||
| 	(pthread_cond::conds): New member. | ||||
| 	(pthread_rwlock::fixup_after_fork): Change to inline. Use | ||||
| 	List::forEach to fixup rwlocks after a fork. | ||||
| 	(pthread_rwlock::FixupAfterFork): New method. | ||||
| 	(pthread_rwlock::rwlocks): New member. | ||||
| 	(semaphore::fixup_after_fork): Change to inline. Use | ||||
| 	List::forEach to fixup mutexes after a fork. | ||||
| 	(semaphore::FixupAfterFork): New method. | ||||
| 	(semaphore::semaphores): New member. | ||||
| 	(MTinterface::mutexs): Remove. | ||||
| 	(MTinterface::conds): Ditto. | ||||
| 	(MTinterface::rwlocks): Ditto. | ||||
| 	(MTinterface::semaphores): Ditto. | ||||
| 	(pthread_equal): Add extern "C". | ||||
| 	(pthread_mutex_lock): Ditto. | ||||
| 	 | ||||
| 	* thread.cc (MTinterface::fixup_after_fork): Change | ||||
| 	fixup_after_fork calls for pthread objects. | ||||
| 	(semaphore::conds): Instantiate. | ||||
| 	(pthread_cond::pthread_cond): Use List::Insert rather than | ||||
| 	custom list code. | ||||
| 	(pthread_cond::~pthread_cond): Use List::Remove rather than | ||||
| 	custom list code. | ||||
| 	(pthread_cond::fixup_after_fork): Rename to FixupAfterFork. | ||||
| 	(pthread_rwlock::rwlocks): Instantiate. | ||||
| 	(pthread_rwlock::pthread_crwlock): Use List::Insert rather than | ||||
| 	custom list code. | ||||
| 	(pthread_rwlock::~pthread_rwlock): Use List::Remove rather than | ||||
| 	custom list code. | ||||
| 	(pthread_rwlock::fixup_after_fork): Rename to FixupAfterFork. | ||||
| 	(pthread_key::saveAKey): Remove. | ||||
| 	(pthread_key::fixup_before_fork): Ditto. | ||||
| 	(pthread_key::restoreAKey): Ditto. | ||||
| 	(pthread_key::fixup_after_fork): Ditto. | ||||
| 	(pthread_key::destroyAKey): Ditto. | ||||
| 	(pthread_key::runAllDestructors): Ditto. | ||||
| 	(pthread_key::run_destructor): Rename to runDestructor. | ||||
| 	(pthread_mutex::mutexes): Instantiate. | ||||
| 	(pthread_mutex::pthread_mutex): Use List::Insert rather than | ||||
| 	custom list code. | ||||
| 	(pthread_mutex::~pthread_mutex): Use List::Remove rather than | ||||
| 	custom list code. | ||||
| 	(pthread_mutex::fixup_after_fork): Rename to FixupAfterFork. | ||||
| 	(semaphore::conds): Instantiate. | ||||
| 	(semaphore::semaphore): Use List::Insert rather than custom list | ||||
| 	code. | ||||
| 	(semaphores::~semaphore): Use List::Remove rather than custom | ||||
| 	list code. | ||||
| 	(semaphore::fixup_after_fork): Rename to FixupAfterFork. | ||||
|  | ||||
| 2003-03-22  Christopher Faylor  <cgf@redhat.com> | ||||
|  | ||||
| 	* pipe.cc (fhandler_pipe::dup): Don't dup input_handle if it doesn't | ||||
|   | ||||
| @@ -217,34 +217,10 @@ MTinterface::fixup_after_fork (void) | ||||
|   threadcount = 1; | ||||
|   pthread::initMainThread (true); | ||||
|  | ||||
|   pthread_mutex *mutex = mutexs; | ||||
|   debug_printf ("mutexs is %x",mutexs); | ||||
|   while (mutex) | ||||
|     { | ||||
|       mutex->fixup_after_fork (); | ||||
|       mutex = mutex->next; | ||||
|     } | ||||
|   pthread_cond *cond = conds; | ||||
|   debug_printf ("conds is %x",conds); | ||||
|   while (cond) | ||||
|     { | ||||
|       cond->fixup_after_fork (); | ||||
|       cond = cond->next; | ||||
|     } | ||||
|   pthread_rwlock *rwlock = rwlocks; | ||||
|   debug_printf ("rwlocks is %x",rwlocks); | ||||
|   while (rwlock) | ||||
|     { | ||||
|       rwlock->fixup_after_fork (); | ||||
|       rwlock = rwlock->next; | ||||
|     } | ||||
|   semaphore *sem = semaphores; | ||||
|   debug_printf ("semaphores is %x",semaphores); | ||||
|   while (sem) | ||||
|     { | ||||
|       sem->fixup_after_fork (); | ||||
|       sem = sem->next; | ||||
|     } | ||||
|   pthread_mutex::fixup_after_fork (); | ||||
|   pthread_cond::fixup_after_fork (); | ||||
|   pthread_rwlock::fixup_after_fork (); | ||||
|   semaphore::fixup_after_fork (); | ||||
| } | ||||
|  | ||||
| /* pthread calls */ | ||||
| @@ -807,6 +783,8 @@ pthread_condattr::~pthread_condattr () | ||||
| { | ||||
| } | ||||
|  | ||||
| List<pthread_cond> pthread_cond::conds; | ||||
|  | ||||
| /* This is used for cond creation protection within a single process only */ | ||||
| nativeMutex NO_COPY pthread_cond::condInitializationLock; | ||||
|  | ||||
| @@ -862,8 +840,7 @@ pthread_cond::pthread_cond (pthread_condattr *attr) : | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* threadsafe addition is easy */ | ||||
|   next = (pthread_cond *) InterlockedExchangePointer (&MT_INTERFACE->conds, this); | ||||
|   conds.Insert (this); | ||||
| } | ||||
|  | ||||
| pthread_cond::~pthread_cond () | ||||
| @@ -871,17 +848,7 @@ pthread_cond::~pthread_cond () | ||||
|   if (semWait) | ||||
|     CloseHandle (semWait); | ||||
|  | ||||
|   /* I'm not 100% sure the next bit is threadsafe. I think it is... */ | ||||
|   if (MT_INTERFACE->conds == this) | ||||
|     InterlockedExchangePointer (&MT_INTERFACE->conds, this->next); | ||||
|   else | ||||
|     { | ||||
|       pthread_cond *tempcond = MT_INTERFACE->conds; | ||||
|       while (tempcond->next && tempcond->next != this) | ||||
| 	tempcond = tempcond->next; | ||||
|       /* but there may be a race between the loop above and this statement */ | ||||
|       InterlockedExchangePointer (&tempcond->next, this->next); | ||||
|     } | ||||
|   conds.Remove (this); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -992,7 +959,7 @@ pthread_cond::Wait (pthread_mutex_t mutex, DWORD dwMilliseconds) | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_cond::fixup_after_fork () | ||||
| pthread_cond::FixupAfterFork () | ||||
| { | ||||
|   waiting = pending = 0; | ||||
|   mtxCond = NULL; | ||||
| @@ -1003,7 +970,7 @@ pthread_cond::fixup_after_fork () | ||||
|  | ||||
|   semWait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); | ||||
|   if (!semWait) | ||||
|     api_fatal ("pthread_cond::fixup_after_fork () failed to recreate win32 semaphore"); | ||||
|     api_fatal ("pthread_cond::FixupAfterFork () failed to recreate win32 semaphore"); | ||||
| } | ||||
|  | ||||
| bool | ||||
| @@ -1023,6 +990,8 @@ pthread_rwlockattr::~pthread_rwlockattr () | ||||
| { | ||||
| } | ||||
|  | ||||
| List<pthread_rwlock> pthread_rwlock::rwlocks; | ||||
|  | ||||
| /* This is used for rwlock creation protection within a single process only */ | ||||
| nativeMutex NO_COPY pthread_rwlock::rwlockInitializationLock; | ||||
|  | ||||
| @@ -1078,23 +1047,12 @@ pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) : | ||||
|     } | ||||
|  | ||||
|  | ||||
|   /* threadsafe addition is easy */ | ||||
|   next = (pthread_rwlock *) InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this); | ||||
|   rwlocks.Insert (this); | ||||
| } | ||||
|  | ||||
| pthread_rwlock::~pthread_rwlock () | ||||
| { | ||||
|   /* I'm not 100% sure the next bit is threadsafe. I think it is... */ | ||||
|   if (MT_INTERFACE->rwlocks == this) | ||||
|     InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this->next); | ||||
|   else | ||||
|     { | ||||
|       pthread_rwlock *temprwlock = MT_INTERFACE->rwlocks; | ||||
|       while (temprwlock->next && temprwlock->next != this) | ||||
| 	temprwlock = temprwlock->next; | ||||
|       /* but there may be a race between the loop above and this statement */ | ||||
|       InterlockedExchangePointer (&temprwlock->next, this->next); | ||||
|     } | ||||
|   rwlocks.Remove (this); | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -1315,7 +1273,7 @@ pthread_rwlock::WrLockCleanup (void *arg) | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_rwlock::fixup_after_fork () | ||||
| pthread_rwlock::FixupAfterFork () | ||||
| { | ||||
|   pthread_t self = pthread::self (); | ||||
|   struct RWLOCK_READER **temp = &readers; | ||||
| @@ -1346,42 +1304,6 @@ pthread_rwlock::fixup_after_fork () | ||||
| /* This stores pthread_key information across fork() boundaries */ | ||||
| List<pthread_key> pthread_key::keys; | ||||
|  | ||||
| void | ||||
| pthread_key::saveAKey (pthread_key *key) | ||||
| { | ||||
|   key->saveKeyToBuffer (); | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_key::fixup_before_fork () | ||||
| { | ||||
|   keys.forEach (saveAKey); | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_key::restoreAKey (pthread_key *key) | ||||
| { | ||||
|   key->recreateKeyFromBuffer (); | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_key::fixup_after_fork () | ||||
| { | ||||
|   keys.forEach (restoreAKey); | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_key::destroyAKey (pthread_key *key) | ||||
| { | ||||
|   key->run_destructor (); | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_key::runAllDestructors () | ||||
| { | ||||
|   keys.forEach (destroyAKey); | ||||
| } | ||||
|  | ||||
| bool | ||||
| pthread_key::isGoodObject (pthread_key_t const *key) | ||||
| { | ||||
| @@ -1445,7 +1367,7 @@ pthread_key::recreateKeyFromBuffer () | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_key::run_destructor () | ||||
| pthread_key::runDestructor () | ||||
| { | ||||
|   if (destructor) | ||||
|     { | ||||
| @@ -1528,6 +1450,8 @@ pthread_mutex::canBeUnlocked (pthread_mutex_t const *mutex) | ||||
|   return (pthread_equal ((*mutex)->owner, self)) && 1 == (*mutex)->recursion_counter; | ||||
| } | ||||
|  | ||||
| List<pthread_mutex> pthread_mutex::mutexes; | ||||
|  | ||||
| /* This is used for mutex creation protection within a single process only */ | ||||
| nativeMutex NO_COPY pthread_mutex::mutexInitializationLock; | ||||
|  | ||||
| @@ -1567,8 +1491,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) : | ||||
|       type = attr->mutextype; | ||||
|     } | ||||
|  | ||||
|   /* threadsafe addition is easy */ | ||||
|   next = (pthread_mutex *) InterlockedExchangePointer (&MT_INTERFACE->mutexs, this); | ||||
|   mutexes.Insert (this); | ||||
| } | ||||
|  | ||||
| pthread_mutex::~pthread_mutex () | ||||
| @@ -1576,19 +1499,7 @@ pthread_mutex::~pthread_mutex () | ||||
|   if (win32_obj_id) | ||||
|     CloseHandle (win32_obj_id); | ||||
|  | ||||
|   /* I'm not 100% sure the next bit is threadsafe. I think it is... */ | ||||
|   if (MT_INTERFACE->mutexs == this) | ||||
|     /* TODO: printf an error if the return value != this */ | ||||
|     InterlockedExchangePointer (&MT_INTERFACE->mutexs, next); | ||||
|   else | ||||
|     { | ||||
|       pthread_mutex *tempmutex = MT_INTERFACE->mutexs; | ||||
|       while (tempmutex->next && tempmutex->next != this) | ||||
| 	tempmutex = tempmutex->next; | ||||
|       /* but there may be a race between the loop above and this statement */ | ||||
|       /* TODO: printf an error if the return value != this */ | ||||
|       InterlockedExchangePointer (&tempmutex->next, this->next); | ||||
|     } | ||||
|   mutexes.Remove (this); | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -1665,11 +1576,11 @@ pthread_mutex::_Destroy (pthread_t self) | ||||
| } | ||||
|  | ||||
| void | ||||
| pthread_mutex::fixup_after_fork () | ||||
| pthread_mutex::FixupAfterFork () | ||||
| { | ||||
|   debug_printf ("mutex %x in fixup_after_fork", this); | ||||
|   debug_printf ("mutex %x in FixupAfterFork", this); | ||||
|   if (pshared != PTHREAD_PROCESS_PRIVATE) | ||||
|     api_fatal ("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's"); | ||||
|     api_fatal ("pthread_mutex::FixupAfterFork () doesn'tunderstand PROCESS_SHARED mutex's"); | ||||
|  | ||||
|   if (NULL == owner) | ||||
|     /* mutex has no owner, reset to initial */ | ||||
| @@ -1680,7 +1591,7 @@ pthread_mutex::fixup_after_fork () | ||||
|  | ||||
|   win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); | ||||
|   if (!win32_obj_id) | ||||
|     api_fatal ("pthread_mutex::fixup_after_fork () failed to recreate win32 semaphore for mutex"); | ||||
|     api_fatal ("pthread_mutex::FixupAfterFork () failed to recreate win32 semaphore for mutex"); | ||||
|  | ||||
|   condwaits = 0; | ||||
| } | ||||
| @@ -1702,6 +1613,8 @@ pthread_mutexattr::~pthread_mutexattr () | ||||
| { | ||||
| } | ||||
|  | ||||
| List<semaphore> semaphore::semaphores; | ||||
|  | ||||
| semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC) | ||||
| { | ||||
|   this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, value, LONG_MAX, | ||||
| @@ -1710,25 +1623,16 @@ semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MA | ||||
|     magic = 0; | ||||
|   this->shared = pshared; | ||||
|   currentvalue = value; | ||||
|   /* threadsafe addition is easy */ | ||||
|   next = (semaphore *) InterlockedExchangePointer (&MT_INTERFACE->semaphores, this); | ||||
|  | ||||
|   semaphores.Insert (this); | ||||
| } | ||||
|  | ||||
| semaphore::~semaphore () | ||||
| { | ||||
|   if (win32_obj_id) | ||||
|     CloseHandle (win32_obj_id); | ||||
|   /* I'm not 100% sure the next bit is threadsafe. I think it is... */ | ||||
|   if (MT_INTERFACE->semaphores == this) | ||||
|     InterlockedExchangePointer (&MT_INTERFACE->semaphores, this->next); | ||||
|   else | ||||
|     { | ||||
|       semaphore *tempsem = MT_INTERFACE->semaphores; | ||||
|       while (tempsem->next && tempsem->next != this) | ||||
| 	tempsem = tempsem->next; | ||||
|       /* but there may be a race between the loop above and this statement */ | ||||
|       InterlockedExchangePointer (&tempsem->next, this->next); | ||||
|     } | ||||
|  | ||||
|   semaphores.Remove (this); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1769,9 +1673,9 @@ semaphore::Wait () | ||||
| } | ||||
|  | ||||
| void | ||||
| semaphore::fixup_after_fork () | ||||
| semaphore::FixupAfterFork () | ||||
| { | ||||
|   debug_printf ("sem %x in fixup_after_fork", this); | ||||
|   debug_printf ("sem %x in FixupAfterFork", this); | ||||
|   if (shared != PTHREAD_PROCESS_PRIVATE) | ||||
|     api_fatal ("doesn't understand PROCESS_SHARED semaphores variables"); | ||||
|   /* FIXME: duplicate code here and in the constructor. */ | ||||
| @@ -2859,7 +2763,7 @@ pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set) | ||||
|  | ||||
| /* ID */ | ||||
|  | ||||
| int | ||||
| extern "C" int | ||||
| pthread_equal (pthread_t t1, pthread_t t2) | ||||
| { | ||||
|   return t1 == t2; | ||||
| @@ -2921,7 +2825,7 @@ pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, | ||||
|   return ENOSYS; | ||||
| } | ||||
|  | ||||
| int | ||||
| extern "C" int | ||||
| pthread_mutex_lock (pthread_mutex_t *mutex) | ||||
| { | ||||
|   pthread_mutex_t *themutex = mutex; | ||||
|   | ||||
| @@ -189,14 +189,50 @@ typedef enum | ||||
| verifyable_object_state verifyable_object_isvalid (void const *, long); | ||||
| verifyable_object_state verifyable_object_isvalid (void const *, long, void *); | ||||
|  | ||||
| /* interface */ | ||||
| template <class ListNode> class List { | ||||
| public: | ||||
|   List(); | ||||
|   void Insert (ListNode *aNode); | ||||
|   ListNode *Remove ( ListNode *aNode); | ||||
|   ListNode *Pop (); | ||||
|   void forEach (void (*)(ListNode *aNode)); | ||||
|   List() : head(NULL) | ||||
|   { | ||||
|   } | ||||
|  | ||||
|   void Insert (ListNode *aNode) | ||||
|   { | ||||
|     if (!aNode) | ||||
|       return; | ||||
|     aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode); | ||||
|   } | ||||
|  | ||||
|   ListNode *Remove ( ListNode *aNode) | ||||
|   { | ||||
|     if (!aNode || !head) | ||||
|       return NULL; | ||||
|     if (aNode == head) | ||||
|       return Pop (); | ||||
|  | ||||
|     ListNode *resultPrev = head; | ||||
|     while (resultPrev && resultPrev->next && !(aNode == resultPrev->next)) | ||||
|       resultPrev = resultPrev->next; | ||||
|     if (resultPrev) | ||||
|       return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next); | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   ListNode *Pop () | ||||
|   { | ||||
|     return (ListNode *) InterlockedExchangePointer (&head, head->next); | ||||
|   } | ||||
|  | ||||
|   /* poor mans generic programming. */ | ||||
|   void forEach (void (ListNode::*callback) ()) | ||||
|   { | ||||
|     ListNode *aNode = head; | ||||
|     while (aNode) | ||||
|       { | ||||
|         (aNode->*callback) (); | ||||
|         aNode = aNode->next; | ||||
|       } | ||||
|   } | ||||
|  | ||||
| protected: | ||||
|   ListNode *head; | ||||
| }; | ||||
| @@ -205,8 +241,6 @@ class pthread_key:public verifyable_object | ||||
| { | ||||
| public: | ||||
|   static bool isGoodObject (pthread_key_t const *); | ||||
|   static void runAllDestructors (); | ||||
|  | ||||
|   DWORD dwTlsIndex; | ||||
|  | ||||
|   int set (const void *); | ||||
| @@ -214,69 +248,32 @@ public: | ||||
|  | ||||
|   pthread_key (void (*)(void *)); | ||||
|   ~pthread_key (); | ||||
|   static void fixup_before_fork(); | ||||
|   static void fixup_after_fork(); | ||||
|   static void fixup_before_fork() | ||||
|   { | ||||
|     keys.forEach (&pthread_key::saveKeyToBuffer); | ||||
|   } | ||||
|  | ||||
|   static void fixup_after_fork() | ||||
|   { | ||||
|     keys.forEach (&pthread_key::recreateKeyFromBuffer); | ||||
|   } | ||||
|  | ||||
|   static void runAllDestructors () | ||||
|   { | ||||
|     keys.forEach (&pthread_key::runDestructor); | ||||
|   } | ||||
|  | ||||
|   /* List support calls */ | ||||
|   class pthread_key *next; | ||||
| private: | ||||
|   // lists of objects. USE THREADSAFE INSERTS AND DELETES. | ||||
|   static List<pthread_key> keys; | ||||
|   static void saveAKey (pthread_key *); | ||||
|   static void restoreAKey (pthread_key *); | ||||
|   static void destroyAKey (pthread_key *); | ||||
|   void saveKeyToBuffer (); | ||||
|   void recreateKeyFromBuffer (); | ||||
|   void (*destructor) (void *); | ||||
|   void run_destructor (); | ||||
|   void runDestructor (); | ||||
|   void *fork_buf; | ||||
| }; | ||||
|  | ||||
| /* implementation */ | ||||
| template <class ListNode> | ||||
| List<ListNode>::List<ListNode> () : head(NULL) | ||||
| { | ||||
| } | ||||
| template <class ListNode> void | ||||
| List<ListNode>::Insert (ListNode *aNode) | ||||
| { | ||||
|   if (!aNode) | ||||
|   return; | ||||
|   aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode); | ||||
| } | ||||
| template <class ListNode> ListNode * | ||||
| List<ListNode>::Remove ( ListNode *aNode) | ||||
| { | ||||
|   if (!aNode) | ||||
|   return NULL; | ||||
|   if (!head) | ||||
|   return NULL; | ||||
|   if (aNode == head) | ||||
|   return Pop (); | ||||
|   ListNode *resultPrev = head; | ||||
|   while (resultPrev && resultPrev->next && !(aNode == resultPrev->next)) | ||||
|   resultPrev = resultPrev->next; | ||||
|   if (resultPrev) | ||||
|   return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next); | ||||
|   return NULL; | ||||
| } | ||||
| template <class ListNode> ListNode * | ||||
| List<ListNode>::Pop () | ||||
| { | ||||
|   return (ListNode *) InterlockedExchangePointer (&head, head->next); | ||||
| } | ||||
| /* poor mans generic programming. */ | ||||
| template <class ListNode> void | ||||
| List<ListNode>::forEach (void (*callback)(ListNode *)) | ||||
| { | ||||
|   ListNode *aNode = head; | ||||
|   while (aNode) | ||||
|   { | ||||
|     callback (aNode); | ||||
|     aNode = aNode->next; | ||||
|   } | ||||
| } | ||||
|  | ||||
| class pthread_attr:public verifyable_object | ||||
| { | ||||
| public: | ||||
| @@ -319,7 +316,6 @@ public: | ||||
|   pthread_t owner; | ||||
|   int type; | ||||
|   int pshared; | ||||
|   class pthread_mutex * next; | ||||
|  | ||||
|   pthread_t GetPthreadSelf () const | ||||
|   { | ||||
| @@ -358,18 +354,25 @@ public: | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   void fixup_after_fork (); | ||||
|  | ||||
|   pthread_mutex (pthread_mutexattr * = NULL); | ||||
|   pthread_mutex (pthread_mutex_t *, pthread_mutexattr *); | ||||
|   ~pthread_mutex (); | ||||
|  | ||||
|   class pthread_mutex * next; | ||||
|   static void fixup_after_fork () | ||||
|   { | ||||
|     mutexes.forEach (&pthread_mutex::FixupAfterFork); | ||||
|   } | ||||
|  | ||||
|   void FixupAfterFork (); | ||||
|  | ||||
| private: | ||||
|   int _Lock (pthread_t self); | ||||
|   int _TryLock (pthread_t self); | ||||
|   int _UnLock (pthread_t self); | ||||
|   int _Destroy (pthread_t self); | ||||
|  | ||||
|   static List<pthread_mutex> mutexes; | ||||
|   static nativeMutex mutexInitializationLock; | ||||
| }; | ||||
|  | ||||
| @@ -506,16 +509,22 @@ public: | ||||
|  | ||||
|   pthread_mutex_t mtxCond; | ||||
|  | ||||
|   class pthread_cond * next; | ||||
|  | ||||
|   void UnBlock (const bool all); | ||||
|   int Wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE); | ||||
|   void fixup_after_fork (); | ||||
|  | ||||
|   pthread_cond (pthread_condattr *); | ||||
|   ~pthread_cond (); | ||||
|  | ||||
|   class pthread_cond * next; | ||||
|   static void fixup_after_fork () | ||||
|   { | ||||
|     conds.forEach (&pthread_cond::FixupAfterFork); | ||||
|   } | ||||
|  | ||||
|   void FixupAfterFork (); | ||||
|  | ||||
| private: | ||||
|   static List<pthread_cond> conds; | ||||
|   static nativeMutex condInitializationLock; | ||||
| }; | ||||
|  | ||||
| @@ -562,14 +571,20 @@ public: | ||||
|   pthread_cond condReaders; | ||||
|   pthread_cond condWriters; | ||||
|  | ||||
|   class pthread_rwlock * next; | ||||
|  | ||||
|   void fixup_after_fork (); | ||||
|  | ||||
|   pthread_rwlock (pthread_rwlockattr *); | ||||
|   ~pthread_rwlock (); | ||||
|  | ||||
|   class pthread_rwlock * next; | ||||
|   static void fixup_after_fork () | ||||
|   { | ||||
|     rwlocks.forEach (&pthread_rwlock::FixupAfterFork); | ||||
|   } | ||||
|  | ||||
|   void FixupAfterFork (); | ||||
|  | ||||
| private: | ||||
|   static List<pthread_rwlock> rwlocks; | ||||
|  | ||||
|   void addReader (struct RWLOCK_READER *rd); | ||||
|   void removeReader (struct RWLOCK_READER *rd); | ||||
|   struct RWLOCK_READER *lookupReader (pthread_t thread); | ||||
| @@ -600,16 +615,25 @@ public: | ||||
|   static int post (sem_t * sem); | ||||
|  | ||||
|   HANDLE win32_obj_id; | ||||
|   class semaphore * next; | ||||
|   int shared; | ||||
|   long currentvalue; | ||||
|   void Wait (); | ||||
|   void Post (); | ||||
|   int TryWait (); | ||||
|   void fixup_after_fork (); | ||||
|  | ||||
|   semaphore (int, unsigned int); | ||||
|   ~semaphore (); | ||||
|  | ||||
|   class semaphore * next; | ||||
|   static void fixup_after_fork () | ||||
|   { | ||||
|     semaphores.forEach (&semaphore::FixupAfterFork); | ||||
|   } | ||||
|  | ||||
|   void FixupAfterFork (); | ||||
|  | ||||
| private: | ||||
|   static List<semaphore> semaphores; | ||||
| }; | ||||
|  | ||||
| class callback | ||||
| @@ -634,12 +658,6 @@ public: | ||||
|   callback *pthread_child; | ||||
|   callback *pthread_parent; | ||||
|  | ||||
|   // lists of pthread objects. USE THREADSAFE INSERTS AND DELETES. | ||||
|   class pthread_mutex * mutexs; | ||||
|   class pthread_cond  * conds; | ||||
|   class pthread_rwlock * rwlocks; | ||||
|   class semaphore     * semaphores; | ||||
|  | ||||
|   pthread_key reent_key; | ||||
|   pthread_key thread_self_key; | ||||
|  | ||||
| @@ -650,7 +668,6 @@ public: | ||||
|   MTinterface () : | ||||
|     concurrency (0), threadcount (1), | ||||
|     pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL), | ||||
|     mutexs (NULL), conds (NULL), rwlocks (NULL), semaphores (NULL), | ||||
|     reent_key (NULL), thread_self_key (NULL) | ||||
|   { | ||||
|   } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user