Author: rfm
Date: Sun Jan 31 18:54:32 2016
New Revision: 39324

URL: http://svn.gna.org/viewcvs/gnustep?rev=39324&view=rev
Log:
Add delay period for alarm, to allow coalesching within the queue and add
hysteresis so we won't forward alarms which are cleared shortly after being
raised.

Modified:
    libs/ec/trunk/ChangeLog
    libs/ec/trunk/EcAlarm.h
    libs/ec/trunk/EcAlarm.m
    libs/ec/trunk/EcAlarmDestination.m

Modified: libs/ec/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/ChangeLog?rev=39324&r1=39323&r2=39324&view=diff
==============================================================================
--- libs/ec/trunk/ChangeLog     (original)
+++ libs/ec/trunk/ChangeLog     Sun Jan 31 18:54:32 2016
@@ -1,3 +1,14 @@
+2016-01-21  Richard Frith-Macdonald <[email protected]>
+
+       * EcAlarm.h:
+       * EcAlarm.m:
+        * EcAlarmDestination.m: When coalescing alarms, allow a clear and
+       alarm to cancel each other out, but only if the alarm is not yet
+       active (only queued). Allow alarms to be set to persist in the queue
+       for up to 255 seconds to allow more coalescing.
+       This lets us raise an alarm which, if cleared within the delay
+       period, will never be forwarded anywhere.
+
 2015-11-18  Richard Frith-Macdonald <[email protected]>
 
        * EcProcess.m: Improve output when changing/reading defaults, and

Modified: libs/ec/trunk/EcAlarm.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcAlarm.h?rev=39324&r1=39323&r2=39324&view=diff
==============================================================================
--- libs/ec/trunk/EcAlarm.h     (original)
+++ libs/ec/trunk/EcAlarm.h     Sun Jan 31 18:54:32 2016
@@ -350,6 +350,7 @@
   NSDictionary          *_userInfo;
   void                 *_extra;
   BOOL                 _frozen;
+  uint8_t               _delay;
 }
 
 /** Creates and returns an autoreleased instance by calling the
@@ -427,6 +428,15 @@
 /** Deallocates the receiver.
  */
 - (void) dealloc;
+
+/** Returns the queue delay set for this alarm (or zero if none was set).
+ */
+- (uint8_t) delay;
+
+/** Returns YES if the receiver should be delayed in the queue past the
+ * supplied timestamp, NO otherwise.
+ */
+- (BOOL) delayed: (NSTimeInterval)at;
 
 /** EcAlarm objects may be passed over the distributed objects system or
  * archived.  This method is provided to implement the NSCoding protocol.<br />
@@ -541,6 +551,13 @@
 /** Returns the probableCause set when the receiver was initialised.
  */
 - (EcAlarmProbableCause) probableCause;
+
+/** Sets the number of seconds for which this alarm should be delayed in the
+ * queue to allow coalescing with other matching alarms.  This defaults to
+ * zero so that there is no special delay in processing beyond that imposed
+ * by periodic queue flushing.
+ */
+- (void) setDelay: (uint8_t)delay;
 
 /** Sets extra data for the current instance.<br />
  * Extra data is not copied, archived, or transferred over DO, it is available

Modified: libs/ec/trunk/EcAlarm.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcAlarm.m?rev=39324&r1=39323&r2=39324&view=diff
==============================================================================
--- libs/ec/trunk/EcAlarm.m     (original)
+++ libs/ec/trunk/EcAlarm.m     Sun Jan 31 18:54:32 2016
@@ -456,6 +456,7 @@
       c->_firstEventDate = [_firstEventDate copyWithZone: aZone];
       c->_notificationID = _notificationID;
       c->_trendIndicator = _trendIndicator;
+      c->_delay = _delay;
       ASSIGNCOPY(c->_userInfo, _userInfo);
     }
   return c;
@@ -471,6 +472,23 @@
   DESTROY(_proposedRepairAction);
   DESTROY(_additionalText);
   [super dealloc];
+}
+
+- (uint8_t) delay
+{
+  return _delay;
+}
+
+- (BOOL) delayed: (NSTimeInterval)at
+{
+  if (_delay > 0)
+    {
+      if (at < [_eventDate timeIntervalSinceReferenceDate] + _delay)
+        {
+          return YES;
+        }
+    }
+  return NO;
 }
 
 - (NSString*) description
@@ -849,6 +867,17 @@
   return self;
 }
 
+- (void) setDelay: (uint8_t)delay
+{
+  if (YES == _frozen)
+    {
+      [NSException raise: NSInternalInconsistencyException
+                 format: @"[%@-%@] called for frozen instance",
+       NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
+    }
+  _delay = delay;
+}
+
 - (void) setExtra: (void*)extra
 {
   if (YES == _frozen)

Modified: libs/ec/trunk/EcAlarmDestination.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcAlarmDestination.m?rev=39324&r1=39323&r2=39324&view=diff
==============================================================================
--- libs/ec/trunk/EcAlarmDestination.m  (original)
+++ libs/ec/trunk/EcAlarmDestination.m  Sun Jan 31 18:54:32 2016
@@ -75,25 +75,40 @@
         {
           NSUInteger    index;
 
-          /* Event clears may only be coalesced with other clears,
-           * otherwise we might have a case where a clear is sent
-           * to the alarm sink without a corresponding alarm having
-           * been raised.
-           */
           index = [_alarmQueue indexOfObject: event];
-         [_alarmQueue addObject: event];
-          if (NSNotFound != index)
+          if (NSNotFound == index)
+            {
+              [_alarmQueue addObject: event];
+            }
+          else
             {
              EcAlarm   *old = [_alarmQueue objectAtIndex: index];
 
              if ([old perceivedSeverity] == EcAlarmSeverityCleared)
                {
+                  /* Repeated clears may be coalesced with later clears
+                   * being ignored.
+                   */
                   if (YES == _debug)
                     {
-                      NSLog(@"Coalesce %@ by removing %@", event, old);
+                      NSLog(@"Coalesce %@ by dropping it (%@ exists)",
+                        event, old);
+                    }
+                  [_alarmQueue addObject: event];
+                 [_alarmQueue removeObjectAtIndex: index];
+               }
+              else if (nil == [_alarmsActive member: old])
+                {
+                  /* An alarm which is not yet active may be cancelled-out
+                   * by a following clear.
+                   */
+                  if (YES == _debug)
+                    {
+                      NSLog(@"Coalesce %@ by removing %@ (old)",
+                        event, old);
                     }
                  [_alarmQueue removeObjectAtIndex: index];
-               }
+                }
             }
         }
       else
@@ -101,16 +116,32 @@
           NSUInteger    index;
 
           index = [_alarmQueue indexOfObject: event];
-         [_alarmQueue addObject: event];
-          if (NSNotFound != index)
+          if (NSNotFound == index)
+            {
+              [_alarmQueue addObject: event];
+            }
+          else
             {
              EcAlarm   *old = [_alarmQueue objectAtIndex: index];
 
-              if (YES == _debug)
+             if ([old perceivedSeverity] == EcAlarmSeverityCleared)
                 {
-                  NSLog(@"Coalesce %@ by removing %@", event, old);
+                  [_alarmQueue addObject: event];
+                  if (YES == _debug)
+                    {
+                      NSLog(@"Coalesce %@ by removing %@ (old)",
+                        event, old);
+                    }
+                 [_alarmQueue removeObjectAtIndex: index];
                 }
-              [_alarmQueue removeObjectAtIndex: index];
+              else
+                {
+                  if (YES == _debug)
+                    {
+                      NSLog(@"Coalesce %@ by dropping it (%@ exists)",
+                        event, old);
+                    }
+                }
             }
        }
       [_alarmLock unlock];
@@ -499,21 +530,81 @@
        {
          if ([_alarmQueue count] > 0)
            {
+              NSTimeInterval    now = [NSDate timeIntervalSinceReferenceDate];
+              NSUInteger        index = 0;
+
              // Do stuff here
 
-             while ([_alarmQueue count] > 0)
+              while (index < [_alarmQueue count])
                {
-                 id    o;
-
-                 o = [[[_alarmQueue objectAtIndex: 0] retain] autorelease];
-                 [_alarmQueue removeObjectAtIndex: 0];
-
-                 if (YES == [o isKindOfClass: [EcAlarm class]])
+                 id    o = [_alarmQueue objectAtIndex: index];
+
+                 if (NO == [o isKindOfClass: [EcAlarm class]])
                    {
-                     EcAlarm   *next = (EcAlarm*)o;
+                     NSString  *s = RETAIN([o description]);
+
+                      [_alarmQueue removeObjectAtIndex: index];
+
+                     if (YES == [s hasPrefix: @"domanage "])
+                       {
+                         NSString      *m = [s substringFromIndex: 9];
+
+                         if (nil == [_managedObjects member: m])
+                           {
+                             [_managedObjects addObject: m];
+                              [_alarmLock unlock];
+                             [self domanageFwd: m];
+                              [_alarmLock lock];
+                           }
+                       }
+                     else if (YES == [s hasPrefix: @"unmanage "])
+                       {
+                         NSString      *m = [s substringFromIndex: 9];
+
+                         if (nil != [_managedObjects member: m])
+                           {
+                              [_alarmLock unlock];
+                              [self _unmanage: m];
+                             [self unmanageFwd: m];
+                              [_alarmLock lock];
+                           }
+
+                         /* When we unmanage an object, we also
+                          * implicitly unmanage objects which
+                          * are components of that object.
+                          */
+                         if (YES == [m hasSuffix: @"_"])
+                           {
+                             NSEnumerator      *e;
+                             NSString          *c;
+
+                             e = [[_managedObjects allObjects]
+                               objectEnumerator];
+                             while (nil != (c = [e nextObject]))
+                               {
+                                 if (YES == [c hasPrefix: m])
+                                   {
+                                      [_alarmLock unlock];
+                                      [self unmanageFwd: c];
+                                      [_alarmLock lock];
+                                   }
+                               }
+                           }
+                       }
+                     else
+                       {
+                         NSLog(@"ERROR ... unexpected command '%@'", s);
+                       }
+                      RELEASE(s);
+                   }
+                  else if (NO == [(EcAlarm*)o delayed: now])
+                   {
+                     EcAlarm   *next = (EcAlarm*)AUTORELEASE(RETAIN(o));
                      EcAlarm   *prev = [_alarmsActive member: next];
                      NSString  *m = [next managedObject];
                       BOOL      shouldForward = NO;
+
+                      [_alarmQueue removeObjectAtIndex: index];
 
                      if (nil == prev)
                        {
@@ -584,61 +675,13 @@
                           [_alarmLock lock];
                         }
                    }
-                 else
-                   {
-                     NSString  *s = [o description];
-
-                     if (YES == [s hasPrefix: @"domanage "])
-                       {
-                         NSString      *m = [s substringFromIndex: 9];
-
-                         if (nil == [_managedObjects member: m])
-                           {
-                             [_managedObjects addObject: m];
-                              [_alarmLock unlock];
-                             [self domanageFwd: m];
-                              [_alarmLock lock];
-                           }
-                       }
-                     else if (YES == [s hasPrefix: @"unmanage "])
-                       {
-                         NSString      *m = [s substringFromIndex: 9];
-
-                         if (nil != [_managedObjects member: m])
-                           {
-                              [_alarmLock unlock];
-                              [self _unmanage: m];
-                             [self unmanageFwd: m];
-                              [_alarmLock lock];
-                           }
-
-                         /* When we unmanage an object, we also
-                          * implicitly unmanage objects which
-                          * are components of that object.
-                          */
-                         if (YES == [m hasSuffix: @"_"])
-                           {
-                             NSEnumerator      *e;
-                             NSString          *s;
-
-                             e = [[_managedObjects allObjects]
-                               objectEnumerator];
-                             while (nil != (s = [e nextObject]))
-                               {
-                                 if (YES == [s hasPrefix: m])
-                                   {
-                                      [_alarmLock unlock];
-                                      [self unmanageFwd: s];
-                                      [_alarmLock lock];
-                                   }
-                               }
-                           }
-                       }
-                     else
-                       {
-                         NSLog(@"ERROR ... unexpected command '%@'", s);
-                       }
-                   }
+                  else
+                    {
+                      /* This alarm is delayed, skip past to process the
+                       * next one.
+                       */
+                      index++;
+                    }
                }
            }
          _inTimeout = NO;


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to