/* * $Id: condition.h,v 1.1.1.1 2002/09/03 11:48:48 dreibh Exp $ * * SCTP implementation according to RFC 2960. * Copyright (C) 1999-2002 by Thomas Dreibholz * * Realized in co-operation between Siemens AG * and University of Essen, Institute of Computer Networking Technology. * * Acknowledgement * This work was partially funded by the Bundesministerium für Bildung und * Forschung (BMBF) of the Federal Republic of Germany (Förderkennzeichen 01AK045). * The authors alone are responsible for the contents. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * There are two mailinglists available at http://www.sctp.de which should be * used for any discussion related to this implementation. * * Contact: discussion AT sctp.de * dreibh AT exp-math.uni-essen.de * * Purpose: Condition * */ #ifndef CONDITION_H #define CONDITION_H #include "tdsystem.h" #include "synchronizable.h" /** * This class realizes a condition variable. * @short Condition * @author Thomas Dreibholz (dreibh AT exp-math.uni-essen.de) * @version 1.0 * @see Synchronizable * @see Thread */ class Condition : public Synchronizable { // ====== Constructor/Destructor ========================================= public: /** * Constructor. * * @param name Name. * @param parentCondition Parent condition. * @param recursive true to make condition's mutex recursive; false otherwise (default for Condition!). */ Condition(const char* name = "Condition", Condition* parentCondition = NULL, const bool recursive = false); /** * Destructor. */ ~Condition(); // ====== Condition variable functions =================================== /** * Fire condition: One thread waiting for this variable will be * resumed. */ void signal(); /** * Broadcast condition: All threads waiting for this variable will be * resumed. */ void broadcast(); /** * Check, if condition has been fired. This call will reset * the fired state. * * @return true, if condition has been fired; false otherwise. */ inline bool fired(); /** * Check, if condition has been fired. This call will *not* * reset the fired state. * * @return true, if condition has been fired; false otherwise. */ inline bool peekFired(); /** * Wait for condition without timeout. */ inline void wait(); /** * Wait for condition with timeout. * * @param microseconds Timeout in microseconds. * @return true, if condition has been received; false for timeout. */ bool timedWait(const card64 microseconds); // ====== Parent condition management ==================================== /** * Add parent condition. * * @param parentCondition Parent condition to be added. */ void addParent(Condition* parentCondition); /** * Remove parent condition. * * @param parentCondition Parent condition to be removed. */ void removeParent(Condition* parentCondition); // ====== Private data =================================================== private: struct ParentNode { struct ParentNode* Next; struct Condition* Parent; }; ParentNode* ParentSet; pthread_cond_t ConditionVariable; bool Fired; static void debug(ParentNode* parent); }; #include "condition.icc" #endif
/* * $Id: condition.cc,v 1.1.1.1 2002/09/03 11:48:48 dreibh Exp $ * * SCTP implementation according to RFC 2960. * Copyright (C) 1999-2002 by Thomas Dreibholz * * Realized in co-operation between Siemens AG * and University of Essen, Institute of Computer Networking Technology. * * Acknowledgement * This work was partially funded by the Bundesministerium für Bildung und * Forschung (BMBF) of the Federal Republic of Germany (Förderkennzeichen 01AK045). * The authors alone are responsible for the contents. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * There are two mailinglists available at http://www.sctp.de which should be * used for any discussion related to this implementation. * * Contact: discussion AT sctp.de * dreibh AT exp-math.uni-essen.de * * Purpose: Condition * */ #include "tdsystem.h" #include "condition.h" #include "thread.h" #include <sys/time.h> // ###### Constructor ####################################################### Condition::Condition(const char* name, Condition* parentCondition, const bool recursive) : Synchronizable(name,recursive) { printf("Constructor: %p (%s)\n",(void*)this,getName()); debug(ParentSet); ParentSet = NULL; addParent(parentCondition); pthread_cond_init(&ConditionVariable,NULL); Fired = false; } // ###### Destructor ######################################################## Condition::~Condition() { printf("Destructor: %p (%s)\n",(void*)this,getName()); if(pthread_cond_destroy(&ConditionVariable) != 0) { #ifndef DISABLE_WARNINGS cerr << "ERROR: Condition::~Condition() - " "Another thread is still waiting for this condition!" << endl; cerr << "Condition name is \"" << MutexName << "\"." << endl; exit(1); #endif } ParentSet = NULL; } void Condition::debug(ParentNode* parent) { printf("Begin dump of ParentSet %p:\n",(void*)parent); cardinal i = 0; while(parent != NULL) { printf(" %d: newParent=%p &newParent->Next=%p newParent->Next=%x &newParent->Parent=%p newParent->Parent=%x %s\n", ++i, (void*)parent, (void*)&parent->Next, (void*)parent->Next, (void*)&parent->Parent, (void*)parent->Parent, (parent->Parent != NULL) ? parent->Parent->getName() : ""); parent = parent->Next; } printf("End dump of ParentSet %p.\n",(void*)parent); } // ###### Add parent condition ############################################## void Condition::addParent(Condition* parentCondition) { if(parentCondition != NULL) { ParentNode* newParent = new ParentNode; if(newParent != NULL) { synchronized(); debug(ParentSet); newParent->Next = ParentSet; newParent->Parent = parentCondition; ParentSet = newParent; printf("addParent: %p (%s) to %p (%s)\n",(void*)parentCondition,parentCondition->getName(),(void*)this,getName()); debug(ParentSet); if(Fired) { parentCondition->broadcast(); } unsynchronized(); } else { cerr << "ERROR: Condition::addParent() - Out of memory!" << endl; exit(1); } } } // ###### Remove parent condition ########################################### void Condition::removeParent(Condition* parentCondition) { if(parentCondition != NULL) { synchronized(); debug(ParentSet); ParentNode* prev = NULL; ParentNode* node = ParentSet; printf("removeParent: %p (%s) from %p (%s)\n",(void*)parentCondition,parentCondition->getName(),(void*)this,getName()); while(node != NULL) { if(node->Parent == parentCondition) { if(prev != NULL) { prev->Next = node->Next; } else { ParentSet = node->Next; } delete node; puts("Success!"); break; } prev = node; node = node->Next; } debug(ParentSet); unsynchronized(); } } // ###### Broadcast condition ############################################### void Condition::broadcast() { synchronized(); Fired = true; pthread_cond_broadcast(&ConditionVariable); #ifdef PRINT_SIGNAL cout << "broadcast: " << getName() << endl; #endif debug(ParentSet); ParentNode* node = ParentSet; while(node != NULL) { printf(" broadcast parent %p (%s)\n",(void*)node->Parent,node->Parent->getName()); node->Parent->broadcast(); node = node->Next; } puts("broadcast completed!"); debug(ParentSet); unsynchronized(); } // ###### Fire condition #################################################### void Condition::signal() { synchronized(); debug(ParentSet); Fired = true; pthread_cond_broadcast(&ConditionVariable); #ifdef PRINT_SIGNAL cout << "signal: " << getName() << endl; #endif ParentNode* node = ParentSet; while(node != NULL) { printf(" signal parent %p (%s)\n",(void*)node->Parent,node->Parent->getName()); node->Parent->signal(); node = node->Next; } puts("signal completed!"); debug(ParentSet); unsynchronized(); } // ###### Wait for condition with timeout ################################### bool Condition::timedWait(const card64 microseconds) { cardinal oldstate = Thread::setCancelState(Thread::TCS_CancelDisabled); synchronized(); // ====== Initialize timeout settings ==================================== timeval now; timespec timeout; gettimeofday(&now,NULL); timeout.tv_sec = now.tv_sec + (long)(microseconds / 1000000); timeout.tv_nsec = (now.tv_usec + (long)(microseconds % 1000000)) * 1000; if(timeout.tv_nsec >= 1000000000) { timeout.tv_sec++; timeout.tv_nsec -= 1000000000; } // ====== Wait =========================================================== int result = EINTR; if(Fired) { result = 0; } else { printf("TimedWait1: %Ld %Ld\n",(card64)timeout.tv_sec,(card64)timeout.tv_nsec); result = pthread_cond_timedwait(&ConditionVariable,&Mutex,&timeout); printf("result=%d EINTR=%d\n",result,result); while(result == EINTR) { unsynchronized(); Thread::setCancelState(oldstate); if(oldstate == Thread::TCS_CancelEnabled) { pthread_testcancel(); } oldstate = Thread::setCancelState(Thread::TCS_CancelDisabled); synchronized(); if(Fired) { result = 0; } else { printf("TimedWait2: %Ld %Ld\n",(card64)timeout.tv_sec,(card64)timeout.tv_nsec); result = pthread_cond_timedwait(&ConditionVariable,&Mutex,&timeout); printf("result=%d EINTR=%d\n",result,result); } } } if(result == 0) { Fired = false; } unsynchronized(); Thread::setCancelState(oldstate); if(oldstate == Thread::TCS_CancelEnabled) { pthread_testcancel(); } return(result == 0); }
Archive powered by MHonArc 2.6.19+.