2005-10-28 16:38:24 +00:00
|
|
|
|
/* -*-objc-*- */
|
|
|
|
|
|
|
|
|
|
/** Implementation of GSThroughput for GNUStep
|
|
|
|
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
|
|
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
|
|
|
|
Date: October 2005
|
|
|
|
|
|
|
|
|
|
This file is part of the Performance Library.
|
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 13:00:42 +00:00
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2005-10-28 16:38:24 +00:00
|
|
|
|
License as published by the Free Software Foundation; either
|
2007-09-14 13:00:42 +00:00
|
|
|
|
version 3 of the License, or (at your option) any later version.
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2007-09-14 13:00:42 +00:00
|
|
|
|
Lesser General Public License for more details.
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
2007-09-14 13:00:42 +00:00
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2005-10-28 16:38:24 +00:00
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
|
|
|
|
|
|
|
|
|
$Date$ $Revision$
|
|
|
|
|
*/
|
|
|
|
|
|
2007-02-24 11:04:53 +00:00
|
|
|
|
#import <Foundation/NSArray.h>
|
|
|
|
|
#import <Foundation/NSString.h>
|
|
|
|
|
#import <Foundation/NSData.h>
|
|
|
|
|
#import <Foundation/NSDate.h>
|
|
|
|
|
#import <Foundation/NSCalendarDate.h>
|
2007-04-01 05:20:38 +00:00
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
|
#import <Foundation/NSEnumerator.h>
|
2007-02-24 11:04:53 +00:00
|
|
|
|
#import <Foundation/NSException.h>
|
|
|
|
|
#import <Foundation/NSNotification.h>
|
|
|
|
|
#import <Foundation/NSHashTable.h>
|
|
|
|
|
#import <Foundation/NSAutoreleasePool.h>
|
|
|
|
|
#import <Foundation/NSDebug.h>
|
|
|
|
|
#import <Foundation/NSThread.h>
|
2008-05-30 10:58:42 +00:00
|
|
|
|
#import <Foundation/NSValue.h>
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
2007-02-24 11:04:53 +00:00
|
|
|
|
#import "GSThroughput.h"
|
|
|
|
|
#import "GSTicker.h"
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
2024-07-14 17:37:31 +00:00
|
|
|
|
#if !defined (GNUSTEP)
|
|
|
|
|
#import "GNUstep.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2008-05-30 10:58:42 +00:00
|
|
|
|
NSString * const GSThroughputNotification = @"GSThroughputNotification";
|
|
|
|
|
NSString * const GSThroughputCountKey = @"Count";
|
|
|
|
|
NSString * const GSThroughputMaximumKey = @"Maximum";
|
|
|
|
|
NSString * const GSThroughputMinimumKey = @"Maximum";
|
|
|
|
|
NSString * const GSThroughputTimeKey = @"Time";
|
|
|
|
|
NSString * const GSThroughputTotalKey = @"Total";
|
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
#define MAXDURATION 24.0*60.0*60.0
|
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
@class GSThroughputThread;
|
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
static Class NSDateClass = 0;
|
|
|
|
|
static SEL tiSel = 0;
|
|
|
|
|
static NSTimeInterval (*tiImp)(Class,SEL) = 0;
|
|
|
|
|
|
2005-10-29 09:23:09 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
unsigned cnt; // Number of events.
|
|
|
|
|
unsigned tick; // Start time
|
2009-11-17 20:04:11 +00:00
|
|
|
|
} CountInfo;
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
unsigned cnt; // Number of events.
|
|
|
|
|
NSTimeInterval max; // Longest duration
|
|
|
|
|
NSTimeInterval min; // Shortest duration
|
|
|
|
|
NSTimeInterval sum; // Total (sum of durations for event)
|
2005-10-29 09:23:09 +00:00
|
|
|
|
unsigned tick; // Start time
|
2009-11-17 20:04:11 +00:00
|
|
|
|
} DurationInfo;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
2005-10-29 09:23:09 +00:00
|
|
|
|
void *seconds;
|
|
|
|
|
void *minutes;
|
|
|
|
|
void *periods;
|
2006-11-09 09:22:11 +00:00
|
|
|
|
void *total;
|
2005-10-29 09:23:09 +00:00
|
|
|
|
BOOL supportDurations;
|
2008-05-30 10:58:42 +00:00
|
|
|
|
BOOL notify;
|
2005-10-29 09:23:09 +00:00
|
|
|
|
unsigned numberOfPeriods;
|
|
|
|
|
unsigned minutesPerPeriod;
|
|
|
|
|
unsigned second;
|
|
|
|
|
unsigned minute;
|
|
|
|
|
unsigned period;
|
|
|
|
|
unsigned last; // last tick used
|
|
|
|
|
NSTimeInterval started; // When duration logging started.
|
2005-10-29 16:07:38 +00:00
|
|
|
|
NSString *event; // Name of current event
|
|
|
|
|
NSString *name; // Name of this instance
|
|
|
|
|
GSThroughputThread *thread; // Thread info
|
2005-10-28 16:38:24 +00:00
|
|
|
|
} Item;
|
2005-11-04 06:00:41 +00:00
|
|
|
|
#define my ((Item*)_data)
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
2009-11-17 20:04:11 +00:00
|
|
|
|
#define cseconds ((CountInfo*)my->seconds)
|
|
|
|
|
#define cminutes ((CountInfo*)my->minutes)
|
|
|
|
|
#define cperiods ((CountInfo*)my->periods)
|
|
|
|
|
#define dseconds ((DurationInfo*)my->seconds)
|
|
|
|
|
#define dminutes ((DurationInfo*)my->minutes)
|
|
|
|
|
#define dperiods ((DurationInfo*)my->periods)
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@interface GSThroughputThread : NSObject
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2005-10-29 16:07:38 +00:00
|
|
|
|
@public
|
|
|
|
|
NSHashTable *instances;
|
|
|
|
|
}
|
|
|
|
|
@end
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
@interface GSThroughput (Private)
|
|
|
|
|
+ (GSThroughputThread*) _threadInfo;
|
2005-11-14 18:14:21 +00:00
|
|
|
|
+ (void) newSecond: (GSThroughputThread*)t;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
- (void) _detach;
|
|
|
|
|
- (void) _update;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation GSThroughputThread
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
if (instances != 0)
|
|
|
|
|
{
|
|
|
|
|
NSHashEnumerator e;
|
|
|
|
|
GSThroughput *i;
|
|
|
|
|
|
|
|
|
|
e = NSEnumerateHashTable(instances);
|
|
|
|
|
while ((i = (GSThroughput*)NSNextHashEnumeratorItem(&e)) != nil)
|
|
|
|
|
{
|
|
|
|
|
[i _detach];
|
|
|
|
|
}
|
|
|
|
|
NSEndHashTableEnumeration(&e);
|
|
|
|
|
NSFreeHashTable(instances);
|
|
|
|
|
instances = 0;
|
|
|
|
|
}
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
|
{
|
2011-02-26 15:53:44 +00:00
|
|
|
|
if (nil != (self = [super init]))
|
|
|
|
|
{
|
|
|
|
|
instances = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
|
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation GSThroughput (Private)
|
|
|
|
|
|
|
|
|
|
+ (GSThroughputThread*) _threadInfo
|
|
|
|
|
{
|
|
|
|
|
GSThroughputThread *t;
|
|
|
|
|
|
|
|
|
|
t = [[[NSThread currentThread] threadDictionary]
|
|
|
|
|
objectForKey: @"GSThroughput"];
|
|
|
|
|
if (t == nil)
|
|
|
|
|
{
|
|
|
|
|
t = [GSThroughputThread new];
|
|
|
|
|
[[[NSThread currentThread] threadDictionary] setObject: t
|
|
|
|
|
forKey: @"GSThroughput"];
|
2009-11-17 20:04:11 +00:00
|
|
|
|
[t release];
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-14 18:14:21 +00:00
|
|
|
|
+ (void) newSecond: (GSThroughputThread*)t
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
NSHashEnumerator e;
|
|
|
|
|
GSThroughput *i;
|
|
|
|
|
|
|
|
|
|
e = NSEnumerateHashTable(t->instances);
|
|
|
|
|
while ((i = (GSThroughput*)NSNextHashEnumeratorItem(&e)) != nil)
|
|
|
|
|
{
|
|
|
|
|
[i _update];
|
|
|
|
|
}
|
|
|
|
|
NSEndHashTableEnumeration(&e);
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
- (void) _detach
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->thread = nil;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
- (void) _update
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2008-05-30 10:58:42 +00:00
|
|
|
|
NSTimeInterval base;
|
|
|
|
|
unsigned tick;
|
|
|
|
|
|
|
|
|
|
if (my->thread == nil)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base = GSTickerTimeStart();
|
|
|
|
|
tick = GSTickerTimeTick();
|
|
|
|
|
if (my->numberOfPeriods > 0)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
if (my->supportDurations == YES)
|
|
|
|
|
{
|
|
|
|
|
while (my->last < tick)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *info;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
if (my->second++ == 59)
|
|
|
|
|
{
|
|
|
|
|
info = &dminutes[my->minute];
|
|
|
|
|
for (i = 0; i < 60; i++)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *from = &dseconds[i];
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
|
|
|
|
info->cnt += from->cnt;
|
|
|
|
|
if (from->min < info->min)
|
|
|
|
|
{
|
|
|
|
|
info->min = from->min;
|
|
|
|
|
}
|
|
|
|
|
if (from->max > info->max)
|
|
|
|
|
{
|
|
|
|
|
info->max = from->max;
|
|
|
|
|
}
|
|
|
|
|
info->sum += from->sum;
|
|
|
|
|
}
|
2008-05-30 10:58:42 +00:00
|
|
|
|
if (my->notify == YES && my->last > 59)
|
|
|
|
|
{
|
2008-05-30 11:05:28 +00:00
|
|
|
|
if (info->min >= MAXDURATION)
|
2008-05-30 10:58:42 +00:00
|
|
|
|
{
|
|
|
|
|
info->min = -1.0;
|
|
|
|
|
}
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
postNotificationName: GSThroughputNotification
|
|
|
|
|
object: self
|
|
|
|
|
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
[NSNumber numberWithUnsignedInt: info->cnt],
|
|
|
|
|
GSThroughputCountKey,
|
|
|
|
|
[NSNumber numberWithDouble: info->max],
|
|
|
|
|
GSThroughputMaximumKey,
|
|
|
|
|
[NSNumber numberWithDouble: info->min],
|
|
|
|
|
GSThroughputMinimumKey,
|
|
|
|
|
[NSNumber numberWithDouble: info->sum],
|
|
|
|
|
GSThroughputTotalKey,
|
|
|
|
|
[NSDate dateWithTimeIntervalSinceReferenceDate:
|
2008-05-30 11:05:28 +00:00
|
|
|
|
base + my->last - 60],
|
2008-05-30 10:58:42 +00:00
|
|
|
|
GSThroughputTimeKey,
|
|
|
|
|
nil]];
|
2008-05-30 11:05:28 +00:00
|
|
|
|
if (info->min < 0.0)
|
|
|
|
|
{
|
|
|
|
|
info->min = MAXDURATION;
|
|
|
|
|
}
|
2008-05-30 10:58:42 +00:00
|
|
|
|
}
|
2005-11-04 12:48:59 +00:00
|
|
|
|
if (my->minute++ == my->minutesPerPeriod - 1)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
info = &dperiods[my->period];
|
|
|
|
|
for (i = 0; i < my->minutesPerPeriod; i++)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *from = &dminutes[i];
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
|
|
|
|
info->cnt += from->cnt;
|
|
|
|
|
if (from->min > 0.0 && from->min < info->min)
|
|
|
|
|
{
|
|
|
|
|
info->min = from->min;
|
|
|
|
|
}
|
|
|
|
|
if (from->max > info->max)
|
|
|
|
|
{
|
|
|
|
|
info->max = from->max;
|
|
|
|
|
}
|
|
|
|
|
info->sum += from->sum;
|
|
|
|
|
}
|
2005-11-04 12:48:59 +00:00
|
|
|
|
if (my->period++ == my->numberOfPeriods - 1)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
my->period = 0;
|
|
|
|
|
}
|
|
|
|
|
info = &dperiods[my->period];
|
|
|
|
|
info->cnt = 0;
|
|
|
|
|
info->max = 0.0;
|
|
|
|
|
info->min = MAXDURATION;
|
|
|
|
|
info->sum = 0.0;
|
2005-11-04 12:08:50 +00:00
|
|
|
|
info->tick = my->last;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->minute = 0;
|
|
|
|
|
}
|
|
|
|
|
info = &dminutes[my->minute];
|
|
|
|
|
info->cnt = 0;
|
|
|
|
|
info->max = 0.0;
|
|
|
|
|
info->min = MAXDURATION;
|
|
|
|
|
info->sum = 0.0;
|
2005-11-04 12:08:50 +00:00
|
|
|
|
info->tick = my->last;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->second = 0;
|
|
|
|
|
}
|
|
|
|
|
info = &dseconds[my->second];
|
|
|
|
|
info->cnt = 0;
|
|
|
|
|
info->max = 0.0;
|
|
|
|
|
info->min = MAXDURATION;
|
|
|
|
|
info->sum = 0.0;
|
2005-11-04 12:08:50 +00:00
|
|
|
|
info->tick = my->last;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
|
|
|
|
my->last++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (my->last < tick)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
|
|
|
|
if (my->second++ == 59)
|
|
|
|
|
{
|
|
|
|
|
info = &cminutes[my->minute];
|
|
|
|
|
for (i = 0; i < 60; i++)
|
|
|
|
|
{
|
|
|
|
|
info->cnt += cseconds[i].cnt;
|
|
|
|
|
}
|
2008-05-30 10:58:42 +00:00
|
|
|
|
if (my->notify == YES && my->last > 59)
|
|
|
|
|
{
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
postNotificationName: GSThroughputNotification
|
|
|
|
|
object: self
|
|
|
|
|
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
[NSNumber numberWithUnsignedInt: info->cnt],
|
|
|
|
|
GSThroughputCountKey,
|
|
|
|
|
[NSDate dateWithTimeIntervalSinceReferenceDate:
|
2008-05-30 11:05:28 +00:00
|
|
|
|
base + my->last - 60],
|
2008-05-30 10:58:42 +00:00
|
|
|
|
GSThroughputTimeKey,
|
|
|
|
|
nil]];
|
|
|
|
|
}
|
2005-11-04 12:48:59 +00:00
|
|
|
|
if (my->minute++ == my->minutesPerPeriod - 1)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
info = &cperiods[my->period];
|
|
|
|
|
for (i = 0; i < my->minutesPerPeriod; i++)
|
|
|
|
|
{
|
|
|
|
|
info->cnt += cminutes[i].cnt;
|
|
|
|
|
}
|
2005-11-04 12:48:59 +00:00
|
|
|
|
if (my->period++ == my->numberOfPeriods - 1)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
my->period = 0;
|
|
|
|
|
}
|
|
|
|
|
info = &cperiods[my->period];
|
|
|
|
|
info->cnt = 0;
|
2005-11-04 12:08:50 +00:00
|
|
|
|
info->tick = my->last;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->minute = 0;
|
|
|
|
|
}
|
|
|
|
|
info = &cminutes[my->minute];
|
|
|
|
|
info->cnt = 0;
|
2005-11-04 12:08:50 +00:00
|
|
|
|
info->tick = my->last;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->second = 0;
|
|
|
|
|
}
|
|
|
|
|
info = &cseconds[my->second];
|
|
|
|
|
info->cnt = 0;
|
2005-11-04 12:08:50 +00:00
|
|
|
|
info->tick = my->last;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
|
|
|
|
my->last++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-05-30 10:58:42 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (my->last < tick)
|
|
|
|
|
{
|
|
|
|
|
if (my->second++ == 59)
|
|
|
|
|
{
|
|
|
|
|
my->second = 0;
|
|
|
|
|
if (my->supportDurations == YES)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *info = &dseconds[1];
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
|
|
|
|
if (my->notify == YES && my->last > 59)
|
|
|
|
|
{
|
|
|
|
|
if (info->min == MAXDURATION)
|
|
|
|
|
{
|
|
|
|
|
info->min = -1.0;
|
|
|
|
|
}
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
postNotificationName: GSThroughputNotification
|
|
|
|
|
object: self
|
|
|
|
|
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
[NSNumber numberWithUnsignedInt: info->cnt],
|
|
|
|
|
GSThroughputCountKey,
|
|
|
|
|
[NSNumber numberWithDouble: info->max],
|
|
|
|
|
GSThroughputMaximumKey,
|
|
|
|
|
[NSNumber numberWithDouble: info->min],
|
|
|
|
|
GSThroughputMinimumKey,
|
|
|
|
|
[NSNumber numberWithDouble: info->sum],
|
|
|
|
|
GSThroughputTotalKey,
|
|
|
|
|
[NSDate dateWithTimeIntervalSinceReferenceDate:
|
2008-05-30 11:05:28 +00:00
|
|
|
|
base + my->last - 60],
|
2008-05-30 10:58:42 +00:00
|
|
|
|
GSThroughputTimeKey,
|
|
|
|
|
nil]];
|
|
|
|
|
}
|
|
|
|
|
info->cnt = 0;
|
|
|
|
|
info->max = 0.0;
|
|
|
|
|
info->min = MAXDURATION;
|
|
|
|
|
info->sum = 0.0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info = &cseconds[1];
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
|
|
|
|
if (my->notify == YES && my->last > 59)
|
|
|
|
|
{
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
postNotificationName: GSThroughputNotification
|
|
|
|
|
object: self
|
|
|
|
|
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
[NSNumber numberWithUnsignedInt: info->cnt],
|
|
|
|
|
GSThroughputCountKey,
|
|
|
|
|
[NSDate dateWithTimeIntervalSinceReferenceDate:
|
2008-05-30 11:05:28 +00:00
|
|
|
|
base + my->last - 60],
|
2008-05-30 10:58:42 +00:00
|
|
|
|
GSThroughputTimeKey,
|
|
|
|
|
nil]];
|
|
|
|
|
}
|
|
|
|
|
info->cnt = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
my->last++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation GSThroughput
|
|
|
|
|
|
|
|
|
|
+ (NSArray*) allInstances
|
|
|
|
|
{
|
|
|
|
|
GSThroughputThread *t;
|
|
|
|
|
NSArray *a;
|
|
|
|
|
|
|
|
|
|
t = [[[NSThread currentThread] threadDictionary]
|
|
|
|
|
objectForKey: @"GSThroughput"];
|
|
|
|
|
if (t == nil)
|
|
|
|
|
{
|
|
|
|
|
a = nil;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
a = NSAllHashTableObjects(t->instances);
|
|
|
|
|
}
|
|
|
|
|
return a;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (NSString*) description
|
|
|
|
|
{
|
2005-10-29 16:07:38 +00:00
|
|
|
|
GSThroughputThread *t;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
NSMutableString *ms;
|
|
|
|
|
|
|
|
|
|
ms = [NSMutableString stringWithString: [super description]];
|
2005-10-29 16:07:38 +00:00
|
|
|
|
t = [[[NSThread currentThread] threadDictionary]
|
|
|
|
|
objectForKey: @"GSThroughput"];
|
|
|
|
|
if (t != nil)
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2006-11-09 13:18:12 +00:00
|
|
|
|
NSArray *a;
|
|
|
|
|
NSEnumerator *e;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
GSThroughput *c;
|
|
|
|
|
|
2006-11-09 13:18:12 +00:00
|
|
|
|
a = [NSAllHashTableObjects(t->instances) sortedArrayUsingSelector:
|
|
|
|
|
@selector(compare:)];
|
|
|
|
|
e = [a objectEnumerator];
|
|
|
|
|
while ((c = (GSThroughput*)[e nextObject]) != nil)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
|
|
|
|
[ms appendFormat: @"\n%@", [c description]];
|
|
|
|
|
}
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
return ms;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
2005-10-29 16:07:38 +00:00
|
|
|
|
if (NSDateClass == 0)
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
|
|
|
|
NSDateClass = [NSDate class];
|
|
|
|
|
tiSel = @selector(timeIntervalSinceReferenceDate);
|
|
|
|
|
tiImp
|
|
|
|
|
= (NSTimeInterval (*)(Class,SEL))[NSDateClass methodForSelector: tiSel];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-14 18:14:21 +00:00
|
|
|
|
+ (void) setTick: (BOOL)aFlag
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2005-11-14 18:14:21 +00:00
|
|
|
|
if (aFlag == YES)
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2005-11-14 18:14:21 +00:00
|
|
|
|
GSThroughputThread *t = [self _threadInfo];
|
|
|
|
|
|
|
|
|
|
[GSTicker registerObserver: (id<GSTicker>)self userInfo: t];
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
2005-11-14 18:14:21 +00:00
|
|
|
|
else
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2005-11-14 18:14:21 +00:00
|
|
|
|
[GSTicker unregisterObserver: (id<GSTicker>)self];
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (void) tick
|
|
|
|
|
{
|
2005-11-14 18:14:21 +00:00
|
|
|
|
[self newSecond: [self _threadInfo]];
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) add: (unsigned)count
|
|
|
|
|
{
|
2014-11-12 15:11:22 +00:00
|
|
|
|
if (NO != my->supportDurations)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"-add: called when set for durations"];
|
|
|
|
|
}
|
2008-05-30 10:58:42 +00:00
|
|
|
|
if (my->numberOfPeriods == 0)
|
|
|
|
|
{
|
|
|
|
|
cseconds[0].cnt += count; // Total
|
|
|
|
|
cseconds[1].cnt += count; // Current minute
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cseconds[my->second].cnt += count;
|
|
|
|
|
}
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-11-11 07:14:30 +00:00
|
|
|
|
- (void) add: (unsigned)count duration: (NSTimeInterval)length
|
|
|
|
|
{
|
2014-11-12 15:11:22 +00:00
|
|
|
|
if (YES != my->supportDurations)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"-add:duration: called when not set for durations"];
|
|
|
|
|
}
|
2006-11-11 07:14:30 +00:00
|
|
|
|
|
|
|
|
|
if (count > 0)
|
|
|
|
|
{
|
|
|
|
|
NSTimeInterval total = length;
|
2008-05-30 10:58:42 +00:00
|
|
|
|
unsigned from;
|
|
|
|
|
unsigned to;
|
2006-11-11 07:14:30 +00:00
|
|
|
|
|
|
|
|
|
length /= count;
|
2008-05-30 10:58:42 +00:00
|
|
|
|
if (my->numberOfPeriods == 0)
|
|
|
|
|
{
|
|
|
|
|
from = 0; // total
|
|
|
|
|
to = 1; // current minute
|
|
|
|
|
}
|
2006-11-11 07:14:30 +00:00
|
|
|
|
else
|
2008-05-30 10:58:42 +00:00
|
|
|
|
{
|
|
|
|
|
from = my->second;
|
|
|
|
|
to = from;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (from <= to)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *info = &dseconds[from++];
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
|
|
|
|
if (info->cnt == 0)
|
|
|
|
|
{
|
|
|
|
|
info->cnt = count;
|
|
|
|
|
info->min = length;
|
|
|
|
|
info->max = length;
|
|
|
|
|
info->sum = total;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info->cnt += count;
|
|
|
|
|
info->sum += total;
|
|
|
|
|
if (length > info->max)
|
|
|
|
|
{
|
|
|
|
|
info->max = length;
|
|
|
|
|
}
|
|
|
|
|
if (length < info->min)
|
|
|
|
|
{
|
|
|
|
|
info->min = length;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-11-11 07:14:30 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
- (void) addDuration: (NSTimeInterval)length
|
|
|
|
|
{
|
2008-05-30 10:58:42 +00:00
|
|
|
|
unsigned from;
|
|
|
|
|
unsigned to;
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2014-11-12 15:11:22 +00:00
|
|
|
|
if (YES != my->supportDurations)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"-addDuration: called when not set for durations"];
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-30 10:58:42 +00:00
|
|
|
|
if (my->numberOfPeriods == 0)
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2008-05-30 10:58:42 +00:00
|
|
|
|
from = 0; // Total
|
|
|
|
|
to = 1; // Current minute
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2008-05-30 10:58:42 +00:00
|
|
|
|
from = my->second;
|
|
|
|
|
to = from;
|
|
|
|
|
}
|
|
|
|
|
while (from <= to)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *info = &dseconds[from++];
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
|
|
|
|
if (info->cnt++ == 0)
|
|
|
|
|
{
|
|
|
|
|
info->min = length;
|
|
|
|
|
info->max = length;
|
|
|
|
|
info->sum = length;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info->sum += length;
|
|
|
|
|
if (length > info->max)
|
|
|
|
|
{
|
|
|
|
|
info->max = length;
|
|
|
|
|
}
|
|
|
|
|
if (length < info->min)
|
|
|
|
|
{
|
|
|
|
|
info->min = length;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-09 13:18:12 +00:00
|
|
|
|
- (NSComparisonResult) compare: (id)other
|
|
|
|
|
{
|
|
|
|
|
if ([other isKindOfClass: [GSThroughput class]] == YES)
|
|
|
|
|
{
|
|
|
|
|
NSString *myName = [self name];
|
|
|
|
|
NSString *otherName = [other name];
|
|
|
|
|
|
|
|
|
|
if (myName == nil)
|
|
|
|
|
{
|
|
|
|
|
myName = @"";
|
|
|
|
|
}
|
|
|
|
|
if (otherName == nil)
|
|
|
|
|
{
|
|
|
|
|
otherName = @"";
|
|
|
|
|
}
|
|
|
|
|
return [myName compare: otherName];
|
|
|
|
|
}
|
|
|
|
|
return NSOrderedAscending;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2005-11-04 06:00:41 +00:00
|
|
|
|
if (_data)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
2005-11-04 06:00:41 +00:00
|
|
|
|
if (my->seconds != 0)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), my->seconds);
|
|
|
|
|
}
|
2009-11-17 20:04:11 +00:00
|
|
|
|
[my->name release];
|
2005-11-04 06:00:41 +00:00
|
|
|
|
if (my->thread != nil)
|
|
|
|
|
{
|
|
|
|
|
NSHashRemove(my->thread->instances, (void*)self);
|
|
|
|
|
my->thread = nil;
|
|
|
|
|
}
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), _data);
|
|
|
|
|
_data = 0;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
2005-11-04 06:00:41 +00:00
|
|
|
|
[super dealloc];
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-23 15:53:58 +00:00
|
|
|
|
static void
|
|
|
|
|
appendCountInfo(CountInfo *info, NSMutableString *m, NSTimeInterval base)
|
|
|
|
|
{
|
|
|
|
|
NSDate *d = [NSDate alloc];
|
|
|
|
|
|
|
|
|
|
d = [d initWithTimeIntervalSinceReferenceDate: info->tick + base];
|
|
|
|
|
[m appendFormat: @"%u, %@\n", info->cnt, d];
|
|
|
|
|
RELEASE(d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
appendDurationInfo(DurationInfo *info, NSMutableString *m, NSTimeInterval base)
|
|
|
|
|
{
|
|
|
|
|
NSDate *d = [NSDate alloc];
|
|
|
|
|
|
|
|
|
|
d = [d initWithTimeIntervalSinceReferenceDate: info->tick + base];
|
|
|
|
|
if (info->cnt)
|
|
|
|
|
{
|
|
|
|
|
[m appendFormat: @"%u, %g, %g, %g, %@\n",
|
|
|
|
|
info->cnt, info->max, info->min, info->sum, d];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[m appendFormat: @"0, -, -, -, %@\n", d];
|
|
|
|
|
}
|
|
|
|
|
RELEASE(d);
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
- (NSString*) description
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
2005-10-29 03:01:50 +00:00
|
|
|
|
NSString *n = my->name;
|
|
|
|
|
NSMutableString *m;
|
|
|
|
|
unsigned i;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
n = [super description];
|
|
|
|
|
}
|
2005-10-29 03:01:50 +00:00
|
|
|
|
m = [n mutableCopy];
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
if (my->thread != nil)
|
2005-10-29 03:01:50 +00:00
|
|
|
|
{
|
2005-11-14 18:14:21 +00:00
|
|
|
|
NSTimeInterval baseTime = GSTickerTimeStart();
|
2005-11-04 11:42:10 +00:00
|
|
|
|
unsigned tick;
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
if (my->numberOfPeriods == 0)
|
2005-10-29 03:01:50 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
if (my->supportDurations == YES)
|
2005-10-29 09:23:09 +00:00
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
DurationInfo *info = &dseconds[0];
|
2005-10-29 03:01:50 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendFormat: @": cnt %u, max %g, min %g, avg %g",
|
|
|
|
|
info->cnt, info->max,
|
|
|
|
|
info->min == MAXDURATION ? 0.0 : info->min,
|
2006-11-09 13:24:49 +00:00
|
|
|
|
info->cnt == 0 ? 0 : info->sum / info->cnt];
|
2005-10-29 09:23:09 +00:00
|
|
|
|
}
|
2006-11-09 09:22:11 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info = &cseconds[0];
|
2005-10-29 03:01:50 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendFormat: @": cnt %u", info->cnt];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (my->supportDurations == YES)
|
2005-10-29 09:23:09 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendString: @"\nSeconds in current minute:\n"];
|
|
|
|
|
if (my->second > 0)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
tick = 0;
|
|
|
|
|
for (i = 0; i < my->second; i++)
|
2005-11-04 11:42:10 +00:00
|
|
|
|
{
|
2021-02-23 15:53:58 +00:00
|
|
|
|
DurationInfo *info = &dseconds[i];
|
2006-11-09 09:22:11 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendDurationInfo(info, m, baseTime);
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2005-11-04 11:42:10 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
2005-10-29 03:01:50 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendString: @"\nPrevious minutes in current period:\n"];
|
|
|
|
|
if (my->minute > 0)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
tick = 0;
|
|
|
|
|
for (i = 0; i < my->minute; i++)
|
|
|
|
|
{
|
2021-02-23 15:53:58 +00:00
|
|
|
|
DurationInfo *info = &dminutes[i];
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendDurationInfo(info, m, baseTime);
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[m appendString: @"\nPrevious periods:\n"];
|
|
|
|
|
if (my->period > 0)
|
|
|
|
|
{
|
|
|
|
|
tick = 0;
|
2007-12-08 06:26:21 +00:00
|
|
|
|
/* Periods from last cycle
|
|
|
|
|
*/
|
|
|
|
|
for (i = my->period; i < my->numberOfPeriods; i++)
|
|
|
|
|
{
|
2021-02-23 15:53:58 +00:00
|
|
|
|
DurationInfo *info = &dperiods[i];
|
2007-12-08 06:26:21 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendDurationInfo(info, m, baseTime);
|
2007-12-08 06:26:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Periods from current cycle
|
|
|
|
|
*/
|
2006-11-09 09:22:11 +00:00
|
|
|
|
for (i = 0; i < my->period; i++)
|
2005-11-04 11:42:10 +00:00
|
|
|
|
{
|
2021-02-23 15:53:58 +00:00
|
|
|
|
DurationInfo *info = &dperiods[i];
|
2006-11-09 09:22:11 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendDurationInfo(info, m, baseTime);
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2005-11-04 11:42:10 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
2005-10-29 09:23:09 +00:00
|
|
|
|
}
|
2006-11-09 09:22:11 +00:00
|
|
|
|
else
|
2005-10-29 09:23:09 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendString: @"\nSeconds in current minute:\n"];
|
|
|
|
|
if (my->second > 0)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
tick = 0;
|
|
|
|
|
for (i = 0; i < my->second; i++)
|
2005-11-04 11:42:10 +00:00
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info = &cseconds[i];
|
2006-11-09 09:22:11 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendCountInfo(info, m, baseTime);
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2005-11-04 11:42:10 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendString: @"\nPrevious minutes in current period:\n"];
|
|
|
|
|
if (my->minute > 0)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
tick = 0;
|
|
|
|
|
for (i = 0; i < my->minute; i++)
|
2005-11-04 11:42:10 +00:00
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info = &cminutes[i];
|
2006-11-09 09:22:11 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendCountInfo(info, m, baseTime);
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2005-11-04 11:42:10 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
2005-10-29 09:23:09 +00:00
|
|
|
|
|
2006-11-09 09:22:11 +00:00
|
|
|
|
[m appendString: @"\nPrevious periods:\n"];
|
|
|
|
|
if (my->period > 0)
|
2005-10-29 16:07:38 +00:00
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
tick = 0;
|
2007-12-08 06:26:21 +00:00
|
|
|
|
/* Periods from last cycle
|
|
|
|
|
*/
|
|
|
|
|
for (i = my->period; i < my->numberOfPeriods; i++)
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info = &cperiods[i];
|
2007-12-08 06:26:21 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendCountInfo(info, m, baseTime);
|
2007-12-08 06:26:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Periods from current cycle
|
|
|
|
|
*/
|
2006-11-09 09:22:11 +00:00
|
|
|
|
for (i = 0; i < my->period; i++)
|
2005-11-04 11:42:10 +00:00
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
CountInfo *info = &cperiods[i];
|
2006-11-09 09:22:11 +00:00
|
|
|
|
|
|
|
|
|
if (info->tick != tick)
|
|
|
|
|
{
|
|
|
|
|
tick = info->tick;
|
2021-02-23 15:53:58 +00:00
|
|
|
|
appendCountInfo(info, m, baseTime);
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2005-11-04 11:42:10 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
}
|
2005-10-29 09:23:09 +00:00
|
|
|
|
}
|
2005-10-29 03:01:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-17 20:04:11 +00:00
|
|
|
|
[pool release];
|
|
|
|
|
return [m autorelease];
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-29 09:23:09 +00:00
|
|
|
|
- (void) endDuration
|
|
|
|
|
{
|
2006-11-09 09:22:11 +00:00
|
|
|
|
if (my->started > 0.0)
|
|
|
|
|
{
|
2014-11-12 15:11:22 +00:00
|
|
|
|
NSTimeInterval ti;
|
|
|
|
|
|
|
|
|
|
ti = (*tiImp)(NSDateClass, tiSel) - my->started;
|
2006-11-09 09:22:11 +00:00
|
|
|
|
my->event = nil;
|
|
|
|
|
my->started = 0.0;
|
2014-11-12 15:11:22 +00:00
|
|
|
|
[self addDuration: ti];
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2005-10-29 09:23:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-05-30 10:58:42 +00:00
|
|
|
|
- (BOOL) enableNotifications: (BOOL)flag
|
|
|
|
|
{
|
|
|
|
|
BOOL old = my->notify;
|
|
|
|
|
|
|
|
|
|
my->notify = flag;
|
|
|
|
|
return old;
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-11 07:24:18 +00:00
|
|
|
|
- (void) endDuration: (unsigned)count
|
|
|
|
|
{
|
|
|
|
|
if (my->started > 0.0)
|
|
|
|
|
{
|
|
|
|
|
[self add: count duration: (*tiImp)(NSDateClass, tiSel) - my->started];
|
|
|
|
|
my->event = nil;
|
|
|
|
|
my->started = 0.0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
- (id) init
|
2005-10-29 09:23:09 +00:00
|
|
|
|
{
|
|
|
|
|
return [self initWithDurations: YES
|
|
|
|
|
forPeriods: 96
|
|
|
|
|
ofLength: 15];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithDurations: (BOOL)aFlag
|
|
|
|
|
forPeriods: (unsigned)numberOfPeriods
|
|
|
|
|
ofLength: (unsigned)minutesPerPeriod
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2011-02-26 15:53:44 +00:00
|
|
|
|
if (nil != (self = [super init]))
|
|
|
|
|
{
|
|
|
|
|
NSCalendarDate *c;
|
|
|
|
|
unsigned i;
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
2011-02-26 15:53:44 +00:00
|
|
|
|
_data = (Item*)NSZoneCalloc(NSDefaultMallocZone(), 1, sizeof(Item));
|
2005-11-04 06:00:41 +00:00
|
|
|
|
|
2011-02-26 15:53:44 +00:00
|
|
|
|
/*
|
|
|
|
|
* Add this instance to the current thread.
|
|
|
|
|
*/
|
|
|
|
|
my->thread = [[self class] _threadInfo];
|
|
|
|
|
NSHashInsert(my->thread->instances, (void*)self);
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
2011-02-26 15:53:44 +00:00
|
|
|
|
my->supportDurations = aFlag;
|
|
|
|
|
my->notify = NO;
|
|
|
|
|
my->last = GSTickerTimeTick();
|
2006-11-09 09:22:11 +00:00
|
|
|
|
|
2011-02-26 15:53:44 +00:00
|
|
|
|
c = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate:
|
|
|
|
|
GSTickerTimeLast()];
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
2011-02-26 15:53:44 +00:00
|
|
|
|
my->second = [c secondOfMinute];
|
|
|
|
|
i = [c hourOfDay] * 60 + [c minuteOfHour];
|
2008-05-30 10:58:42 +00:00
|
|
|
|
|
2011-02-26 15:53:44 +00:00
|
|
|
|
if (numberOfPeriods < 1 || minutesPerPeriod < 1)
|
2006-11-09 09:22:11 +00:00
|
|
|
|
{
|
2011-02-26 15:53:44 +00:00
|
|
|
|
/* If we are not using periods of N minutes, we must just be keeping
|
|
|
|
|
* a running total recorded second by second.
|
|
|
|
|
*/
|
|
|
|
|
my->numberOfPeriods = 0;
|
|
|
|
|
my->minutesPerPeriod = 0;
|
|
|
|
|
my->minute = i;
|
|
|
|
|
my->period = 0;
|
|
|
|
|
if (my->supportDurations == YES)
|
2006-11-09 09:22:11 +00:00
|
|
|
|
{
|
2011-02-26 15:53:44 +00:00
|
|
|
|
DurationInfo *ptr;
|
|
|
|
|
|
|
|
|
|
ptr = (DurationInfo*)NSZoneCalloc
|
|
|
|
|
(NSDefaultMallocZone(), 2, sizeof(DurationInfo));
|
|
|
|
|
my->seconds = ptr;
|
|
|
|
|
my->minutes = 0;
|
|
|
|
|
my->periods = 0;
|
|
|
|
|
dseconds[0].tick = my->last;
|
|
|
|
|
dseconds[0].max = 0;
|
|
|
|
|
dseconds[0].min = MAXDURATION;
|
|
|
|
|
dseconds[0].sum = 0;
|
|
|
|
|
dseconds[0].cnt = 0;
|
|
|
|
|
|
|
|
|
|
dseconds[1].tick = my->last;
|
|
|
|
|
dseconds[1].max = 0;
|
|
|
|
|
dseconds[1].min = 0;
|
|
|
|
|
dseconds[1].sum = 0;
|
|
|
|
|
dseconds[1].cnt = 0;
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2011-02-26 15:53:44 +00:00
|
|
|
|
else
|
2006-11-09 09:22:11 +00:00
|
|
|
|
{
|
2011-02-26 15:53:44 +00:00
|
|
|
|
CountInfo *ptr;
|
|
|
|
|
|
|
|
|
|
ptr = (CountInfo*)NSZoneCalloc
|
|
|
|
|
(NSDefaultMallocZone(), 2, sizeof(CountInfo));
|
|
|
|
|
my->seconds = ptr;
|
|
|
|
|
my->minutes = 0;
|
|
|
|
|
my->periods = 0;
|
|
|
|
|
cseconds[0].tick = my->last;
|
|
|
|
|
cseconds[0].cnt = 0;
|
|
|
|
|
cseconds[1].tick = my->last;
|
|
|
|
|
cseconds[1].cnt = 0;
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-02-26 15:53:44 +00:00
|
|
|
|
my->numberOfPeriods = numberOfPeriods;
|
|
|
|
|
my->minutesPerPeriod = minutesPerPeriod;
|
|
|
|
|
|
|
|
|
|
my->minute = i % minutesPerPeriod;
|
|
|
|
|
my->period = (i / minutesPerPeriod) % numberOfPeriods;
|
|
|
|
|
|
|
|
|
|
i = 60 + minutesPerPeriod + numberOfPeriods;
|
|
|
|
|
if (my->supportDurations == YES)
|
|
|
|
|
{
|
|
|
|
|
DurationInfo *ptr;
|
|
|
|
|
|
|
|
|
|
ptr = (DurationInfo*)NSZoneCalloc
|
|
|
|
|
(NSDefaultMallocZone(), i, sizeof(DurationInfo));
|
|
|
|
|
my->seconds = ptr;
|
|
|
|
|
my->minutes = ptr + 60;
|
|
|
|
|
my->periods = ptr + 60 + minutesPerPeriod;
|
|
|
|
|
dseconds[my->second].tick = my->last;
|
|
|
|
|
dminutes[my->minute].tick = my->last;
|
|
|
|
|
dperiods[my->period].tick = my->last;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < my->numberOfPeriods; i++)
|
|
|
|
|
{
|
|
|
|
|
dperiods[i].min = MAXDURATION;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < my->minutesPerPeriod; i++)
|
|
|
|
|
{
|
|
|
|
|
dminutes[i].min = MAXDURATION;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < 60; i++)
|
|
|
|
|
{
|
|
|
|
|
dseconds[i].min = MAXDURATION;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CountInfo *ptr;
|
|
|
|
|
|
|
|
|
|
ptr = (CountInfo*)NSZoneCalloc
|
|
|
|
|
(NSDefaultMallocZone(), i, sizeof(CountInfo));
|
|
|
|
|
my->seconds = ptr;
|
|
|
|
|
my->minutes = ptr + 60;
|
|
|
|
|
my->periods = ptr + 60 + minutesPerPeriod;
|
|
|
|
|
cseconds[my->second].tick = my->last;
|
|
|
|
|
cminutes[my->minute].tick = my->last;
|
|
|
|
|
cperiods[my->period].tick = my->last;
|
|
|
|
|
}
|
2006-11-09 09:22:11 +00:00
|
|
|
|
}
|
2011-02-26 15:53:44 +00:00
|
|
|
|
[c release];
|
2005-10-29 09:23:09 +00:00
|
|
|
|
}
|
2005-10-28 16:38:24 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSString*) name
|
|
|
|
|
{
|
|
|
|
|
return my->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) setName: (NSString*)name
|
|
|
|
|
{
|
2009-11-17 20:04:11 +00:00
|
|
|
|
[name retain];
|
|
|
|
|
[my->name release];
|
|
|
|
|
my->name = name;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-29 16:07:38 +00:00
|
|
|
|
- (void) startDuration: (NSString*)name
|
2005-10-29 09:23:09 +00:00
|
|
|
|
{
|
2014-11-12 15:11:22 +00:00
|
|
|
|
if (NO == my->supportDurations)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"-startDuration: for '%@' when not set for durations", name];
|
|
|
|
|
}
|
2014-12-02 11:24:51 +00:00
|
|
|
|
if (0.0 != my->started)
|
2014-11-12 15:11:22 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"-startDuration: for '%@' when already started", name];
|
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
if (my->event != nil)
|
2005-10-28 16:38:24 +00:00
|
|
|
|
{
|
2005-10-29 16:07:38 +00:00
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
2014-11-12 15:11:22 +00:00
|
|
|
|
format: @"-startDuration: for '%@' nested inside '%@'",
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->event, name];
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
my->started = (*tiImp)(NSDateClass, tiSel);
|
|
|
|
|
my->event = name;
|
2005-10-28 16:38:24 +00:00
|
|
|
|
}
|
2005-10-29 16:07:38 +00:00
|
|
|
|
|
2005-10-28 16:38:24 +00:00
|
|
|
|
@end
|
|
|
|
|
|