]> git.vomp.tv Git - vompclient.git/commitdiff
Allow a timercall to try to cancel its own timer - silent ignore
authorChris Tallon <chris@vomp.tv>
Sun, 25 Mar 2007 15:48:56 +0000 (15:48 +0000)
committerChris Tallon <chris@vomp.tv>
Sun, 25 Mar 2007 15:48:56 +0000 (15:48 +0000)
defines.h
thread.h
threadp.cc
threadp.h
timers.cc

index a1a7d7d0408c7ccf5eea17b4438a8f370faa396f..b3bde1076e2a98a72cee40d1fe96647532618006 100644 (file)
--- a/defines.h
+++ b/defines.h
@@ -38,6 +38,7 @@ void MILLISLEEP(ULONG a);
 
   #define Surface_TYPE SurfaceWin
   #define Thread_TYPE ThreadWin
+  #define ThreadID_TYPE             FIXME Marten
 
   #define SNPRINTF _snprintf
   #define VSNPRINTF _vsnprintf
@@ -51,6 +52,8 @@ void MILLISLEEP(ULONG a);
 
   #define Surface_TYPE SurfaceMVP
   #define Thread_TYPE ThreadP
+  #include <pthread.h>
+  #define ThreadID_TYPE pthread_t
 
   #define SNPRINTF snprintf
   #define VSNPRINTF vsnprintf
index 16178e0e6fa68a14b98c07ebedaf5a8c2ee728af..f6dcfcfb76595ba61bec10437d9770646ce1e703 100644 (file)
--- a/thread.h
+++ b/thread.h
@@ -21,6 +21,8 @@
 #ifndef THREAD_H
 #define THREAD_H
 
+#include "defines.h"
+
 class Thread
 {
   protected:
@@ -35,6 +37,7 @@ class Thread
     virtual void threadSignal()=0;  // releases a thread that has called threadWaitForSignal
     virtual void threadSignalNoLock()=0;  // same as above but without locking guarantees. probably not a good idea.
     char threadIsActive(); // returns 1 if thread has been started but not stop() or cancel() 'd
+    virtual ThreadID_TYPE getThreadID()=0; // returns the ID of this thread
 
     // Methods to use from inside the thread
     virtual void threadSetKillable()=0;    // allows threadCancel() to work
index f97fb8f28f782bd89c8a80cf8e80b4b863e2c90c..d95156fb44777c8b46a476e90df0235b5c134197 100644 (file)
@@ -102,6 +102,13 @@ void ThreadP::threadSetKillable()
   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 }
 
+pthread_t ThreadP::getThreadID() // returns the ID of this thread
+{
+  return pthread;
+}
+
+// Static functions
+
 void ThreadP::threadSuicide()
 {
   if(!pthread_detach(pthread_self()))
@@ -116,3 +123,8 @@ void ThreadP::threadSuicide()
 
   pthread_exit(NULL);
 }
+
+pthread_t ThreadP::thisThreadID() // returns the ID of the calling thread
+{
+  return pthread_self();
+}
index 419a93ee862dc4b13e9f49e61aabd54605776edf..46deb25eac10567ebdfa97e731e9c59e1d465a0b 100644 (file)
--- a/threadp.h
+++ b/threadp.h
@@ -51,12 +51,15 @@ class ThreadP : public Thread
 
     // Internal bits and pieces
 
-  private:
     pthread_t pthread;
     pthread_cond_t threadCond;
     pthread_mutex_t threadCondMutex;
 
   public:
+    pthread_t getThreadID();    // returns the ID of the thread represented by this object
+
+
+    static pthread_t thisThreadID();    // Self identification - returns ID of calling thread
     static void threadSuicide();        // Self termination
 };
 
index 9c491ccb87f21e3dc5312af104358619fd25a57f..0c1b460988ea527b6381201790f8b5e5a4bfb32a 100755 (executable)
--- a/timers.cc
+++ b/timers.cc
@@ -187,8 +187,13 @@ bool Timers::cancelTimer(TimerReceiver* client, int clientReference)
         Delete the timer normally, set resetFlag
      2. The TimerEvent is found, running = true. This means the timer is currently firing,
         timercall on the client is being called.
-        In this case, this thread calling cancelTimer needs to unlock and wait for the
-        timercall thread to get back. (sleeps or signalling)
+        a. Thread calling cancelTimer is an external thread: In this case, this thread
+           calling cancelTimer needs to unlock and wait for the timercall thread to get
+           back. (sleeps or signalling)
+        b. the timercall thread is calling cancelTimer. remove any restartAfterFinished
+           request, but otherwise ignore the request to cancelTimer because it has already
+           fired. The timercall thread will return to the calling code and eventually
+           terminate in threadEventFinished.
      3. The TimerEvent is not found. Client error or the thread returned to
         the Timers module in between client calling cancelTimer and cancelTimer actually
         running. Do nothing, return normally.
@@ -240,7 +245,17 @@ bool Timers::cancelTimer(TimerReceiver* client, int clientReference)
       }
       else
       {
-        // Case 2. For now, use polling with a 50ms delay.
+        if (Thread_TYPE::thisThreadID() == currentTimerEvent->getThreadID())
+        {
+          // Case 2 b.
+          // The thread requesting cancelTimer is the timer thread itself, the timer has already fired.
+          logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer itself calling - ignore", client, clientReference);
+          currentTimerEvent->restartAfterFinish = false; // in case a restart had already been set.
+          threadUnlock();
+          return true;
+        }
+
+        // Case 2 a. For now, use polling with a 50ms delay.
         // Don't delete a running timer.
         // FIXME upgrade me to signalling