public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: timer: convert timer_tracker to a real C++ class
@ 2019-01-11 14:15 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2019-01-11 14:15 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=8d1d8fc914725a88c3463895b36daa353ebd0d26

commit 8d1d8fc914725a88c3463895b36daa353ebd0d26
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Fri Jan 11 15:13:11 2019 +0100

    Cygwin: timer: convert timer_tracker to a real C++ class
    
    ...with private members and all the jazz
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/timer.cc | 139 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 84 insertions(+), 55 deletions(-)

diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc
index e1d78eb..39a0f9d 100644
--- a/winsup/cygwin/timer.cc
+++ b/winsup/cygwin/timer.cc
@@ -17,9 +17,11 @@ details. */
 #include <sys/param.h>
 
 #define TT_MAGIC 0x513e4a1c
-struct timer_tracker
+class timer_tracker
 {
   unsigned magic;
+  timer_tracker *next;
+
   clockid_t clock_id;
   sigevent evp;
   timespec it_interval;
@@ -27,13 +29,20 @@ struct timer_tracker
   HANDLE syncthread;
   long long interval_us;
   long long sleepto_us;
+
   bool cancel ();
-  struct timer_tracker *next;
-  int settime (int, const itimerspec *, itimerspec *);
-  void gettime (itimerspec *);
+
+ public:
   timer_tracker (clockid_t, const sigevent *);
   ~timer_tracker ();
-  friend void fixup_timers_after_fork ();
+  inline bool is_timer_tracker () { return magic == TT_MAGIC; }
+
+  void gettime (itimerspec *);
+  int settime (int, const itimerspec *, itimerspec *);
+  int clean_and_unhook ();
+
+  DWORD thread_func ();
+  void fixup_after_fork ();
 };
 
 timer_tracker NO_COPY ttstart (CLOCK_REALTIME, NULL);
@@ -115,66 +124,65 @@ timespec_to_us (const timespec& ts)
   return res;
 }
 
-static DWORD WINAPI
-timer_thread (VOID *x)
+DWORD
+timer_tracker::thread_func ()
 {
-  timer_tracker *tt = ((timer_tracker *) x);
   long long now;
-  long long sleepto_us =  tt->sleepto_us;
+  long long cur_sleepto_us = sleepto_us;
   while (1)
     {
       long long sleep_us;
       LONG sleep_ms;
       /* Account for delays in starting thread
 	and sending the signal */
-      now = get_clock (tt->clock_id)->usecs ();
-      sleep_us = sleepto_us - now;
+      now = get_clock (clock_id)->usecs ();
+      sleep_us = cur_sleepto_us - now;
       if (sleep_us > 0)
 	{
-	  tt->sleepto_us = sleepto_us;
+	  sleepto_us = cur_sleepto_us;
 	  sleep_ms = (sleep_us + (USPERSEC / MSPERSEC) - 1)
 		     / (USPERSEC / MSPERSEC);
 	}
       else
 	{
-	  tt->sleepto_us = now;
+	  sleepto_us = now;
 	  sleep_ms = 0;
 	}
 
-      debug_printf ("%p waiting for %u ms", x, sleep_ms);
-      switch (WaitForSingleObject (tt->hcancel, sleep_ms))
+      debug_printf ("%p waiting for %u ms", this, sleep_ms);
+      switch (WaitForSingleObject (hcancel, sleep_ms))
 	{
 	case WAIT_TIMEOUT:
 	  debug_printf ("timed out");
 	  break;
 	case WAIT_OBJECT_0:
-	  debug_printf ("%p cancelled", x);
+	  debug_printf ("%p cancelled", this);
 	  goto out;
 	default:
-	  debug_printf ("%p wait failed, %E", x);
+	  debug_printf ("%p wait failed, %E", this);
 	  goto out;
 	}
 
-      switch (tt->evp.sigev_notify)
+      switch (evp.sigev_notify)
 	{
 	case SIGEV_SIGNAL:
 	  {
 	    siginfo_t si = {0};
-	    si.si_signo = tt->evp.sigev_signo;
-	    si.si_sigval.sival_ptr = tt->evp.sigev_value.sival_ptr;
+	    si.si_signo = evp.sigev_signo;
+	    si.si_sigval.sival_ptr = evp.sigev_value.sival_ptr;
 	    si.si_code = SI_TIMER;
-	    debug_printf ("%p sending signal %d", x, tt->evp.sigev_signo);
+	    debug_printf ("%p sending signal %d", this, evp.sigev_signo);
 	    sig_send (myself_nowait, si);
 	    break;
 	  }
 	case SIGEV_THREAD:
 	  {
 	    pthread_t notify_thread;
-	    debug_printf ("%p starting thread", x);
+	    debug_printf ("%p starting thread", this);
 	    pthread_attr_t *attr;
 	    pthread_attr_t default_attr;
-	    if (tt->evp.sigev_notify_attributes)
-	      attr = tt->evp.sigev_notify_attributes;
+	    if (evp.sigev_notify_attributes)
+	      attr = evp.sigev_notify_attributes;
 	    else
 	      {
 		pthread_attr_init(attr = &default_attr);
@@ -182,8 +190,8 @@ timer_thread (VOID *x)
 	      }
 
 	    int rc = pthread_create (&notify_thread, attr,
-				     (void * (*) (void *)) tt->evp.sigev_notify_function,
-				     tt->evp.sigev_value.sival_ptr);
+			     (void * (*) (void *)) evp.sigev_notify_function,
+			     evp.sigev_value.sival_ptr);
 	    if (rc)
 	      {
 		debug_printf ("thread creation failed, %E");
@@ -193,10 +201,10 @@ timer_thread (VOID *x)
 	    break;
 	  }
 	}
-      if (!tt->interval_us)
+      if (!interval_us)
 	break;
 
-      sleepto_us = tt->sleepto_us + tt->interval_us;
+      cur_sleepto_us = sleepto_us + interval_us;
       debug_printf ("looping");
     }
 
@@ -205,6 +213,13 @@ out:
   return 0;
 }
 
+static DWORD WINAPI
+timer_thread (VOID *x)
+{
+  timer_tracker *tt = ((timer_tracker *) x);
+  return tt->thread_func ();
+}
+
 static inline bool
 timespec_bad (const timespec& t)
 {
@@ -282,6 +297,37 @@ timer_tracker::gettime (itimerspec *ovalue)
     }
 }
 
+int
+timer_tracker::clean_and_unhook ()
+{
+  for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next)
+    if (tt->next == this)
+      {
+	tt->next = this->next;
+	return 0;
+      }
+  return -1;
+}
+
+void
+timer_tracker::fixup_after_fork ()
+{
+  hcancel = syncthread = NULL;
+  for (timer_tracker *tt = this; tt->next != NULL; /* nothing */)
+    {
+      timer_tracker *deleteme = tt->next;
+      tt->next = deleteme->next;
+      deleteme->hcancel = deleteme->syncthread = NULL;
+      delete deleteme;
+    }
+}
+
+void
+fixup_timers_after_fork ()
+{
+  ttstart.fixup_after_fork ();
+}
+
 extern "C" int
 timer_gettime (timer_t timerid, struct itimerspec *ovalue)
 {
@@ -290,7 +336,7 @@ timer_gettime (timer_t timerid, struct itimerspec *ovalue)
   __try
     {
       timer_tracker *tt = (timer_tracker *) timerid;
-      if (tt->magic != TT_MAGIC)
+      if (!tt->is_timer_tracker ())
 	{
 	  set_errno (EINVAL);
 	  return -1;
@@ -342,7 +388,7 @@ timer_settime (timer_t timerid, int flags,
   __try
     {
       timer_tracker *tt = (timer_tracker *) timerid;
-      if (tt->magic != TT_MAGIC)
+      if (!tt->is_timer_tracker ())
 	{
 	  set_errno (EINVAL);
 	  __leave;
@@ -362,43 +408,26 @@ timer_delete (timer_t timerid)
   __try
     {
       timer_tracker *in_tt = (timer_tracker *) timerid;
-      if (in_tt->magic != TT_MAGIC)
+      if (!in_tt->is_timer_tracker ())
 	{
 	  set_errno (EINVAL);
 	  __leave;
 	}
 
       lock_timer_tracker here;
-      for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next)
-	if (tt->next == in_tt)
-	  {
-	    tt->next = in_tt->next;
-	    delete in_tt;
-	    ret = 0;
-	    __leave;
-	  }
-      set_errno (EINVAL);
-      ret = 0;
+      if (in_tt->clean_and_unhook () == 0)
+	{
+	  delete in_tt;
+	  ret = 0;
+	}
+      else
+	set_errno (EINVAL);
     }
   __except (EFAULT) {}
   __endtry
   return ret;
 }
 
-void
-fixup_timers_after_fork ()
-{
-  ttstart.hcancel = ttstart.syncthread = NULL;
-  for (timer_tracker *tt = &ttstart; tt->next != NULL; /* nothing */)
-    {
-      timer_tracker *deleteme = tt->next;
-      tt->next = deleteme->next;
-      deleteme->hcancel = deleteme->syncthread = NULL;
-      delete deleteme;
-    }
-}
-
-
 extern "C" int
 setitimer (int which, const struct itimerval *__restrict value,
 	   struct itimerval *__restrict ovalue)


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-01-11 14:15 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-11 14:15 [newlib-cygwin] Cygwin: timer: convert timer_tracker to a real C++ class Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).