Sleep is interrupted by signals other then message reception
[Tachyon.git] / src / Tachyon.cpp
index b9adaa4..bd50f66 100644 (file)
@@ -90,6 +90,7 @@ bool operator < (timespec a, timespec b)
 static void message_notification(int signum, siginfo_t *si, void *notused)
 {
    Tachyon *tp = (Tachyon *) si->si_value.sival_ptr;
+   //printf("Tachyon: Caught signal %d\n", signum);
    tp->receive_message();
    tp->expect_message();
 }
@@ -102,6 +103,8 @@ Tachyon::Tachyon()
 
    accelleration = 1.0;
 
+   msg_sequence  = 0;
+
    struct mq_attr  queue_attributes;
    struct sigevent sev;
    struct sigaction act;
@@ -124,6 +127,8 @@ Tachyon::Tachyon(const char *name)
 
    accelleration = 1.0;
 
+   msg_sequence  = 0;
+
    queue_name[0] = '\0';
    msg_queue = mq_open(name, O_WRONLY);
 }
@@ -168,7 +173,11 @@ void Tachyon::receive_message(void)
    int  message_size;
 
    //printf("Receiving message.\n");
+
    message_size = mq_receive(msg_queue, message, MAX_MESSAGE_SIZE, NULL);
+   msg_sequence++;
+
+   //printf("Message size = %d\n", message_size);
    message[message_size] = '\0';
 
    //printf("The message is %s.\n", message);
@@ -205,7 +214,7 @@ timespec Tachyon::gettime(void)
 
    //  Tvirtual = T0 + acc * (Tactual - T0) + offset
 
-   difference = timespec_subtract(actual_time, T0);
+   difference = actual_time - T0;
    //printf("  Ta - T0 = %d,%d\n", difference.tv_sec, difference.tv_nsec);
 
    seconds     = difference.tv_sec  * accelleration;
@@ -218,8 +227,7 @@ timespec Tachyon::gettime(void)
    difference.tv_nsec = trunc(nanoseconds);
    //printf("  a * (Ta - T0) = %d,%d\n", difference.tv_sec, difference.tv_nsec);
 
-   virtual_time   = timespec_add(T0, difference);
-   virtual_time   = timespec_add(virtual_time, offset);
+   virtual_time   = T0 + difference + offset;
  
    return virtual_time;
 }
@@ -234,7 +242,7 @@ int Tachyon::nanosleep(struct timespec req)
 
    virt_time = gettime();
 
-   return sleep_until(timespec_add(virt_time, req));
+   return sleep_until(virt_time + req);
 }
 
 int Tachyon::nanosleep(float req)
@@ -262,13 +270,16 @@ int Tachyon::sleep_until(timespec ends_at)
    double seconds;
    double nanoseconds;
    int    sleep_return;
-   bool   error;
+   int    last_msg_sequence;
 
    timespec  virt_time;
    timespec  remaining;
 
+   last_msg_sequence = msg_sequence;
+   sleep_return      = 0;
+
    virt_time = gettime();
-   while (!error && virt_time < ends_at)
+   while (sleep_return == 0 && virt_time < ends_at)
    {
       timespec period;
 
@@ -287,7 +298,20 @@ int Tachyon::sleep_until(timespec ends_at)
       sleep_return = ::nanosleep(&period, &remaining);
       //printf("nanosleep returns %d, error = %s\n", sleep_return, strerror(errno));
 
-      error = sleep_return == -1 && errno != EINTR;
+      // If a sleep interruption is caused by receiving a message, the sleep is resumed.
+      if (sleep_return == -1 && errno == EINTR)
+      {
+         if (msg_sequence != last_msg_sequence)
+         {
+            sleep_return = 0;
+            last_msg_sequence = msg_sequence;
+         }
+         else
+         {
+            sleep_return = -2;   //  Interrupted by a different signal
+         }
+      }
+
       virt_time = gettime();
    }