@class NSArray;
@class NSString;
extern NSString * const GSThroughputNotification;
extern NSString * const GSThroughputCountKey;
extern NSString * const GSThroughputMaximumKey;
extern NSString * const GSThroughputMinimumKey;
extern NSString * const GSThroughputTimeKey;
extern NSString * const GSThroughputTotalKey;
/**
* The GSThroughput class is used maintain statistics about the number
* of events or the duration of operations in your software.
*
* For performance reasons, the class avoids locking and you must ensure
* that an instance of the class is only ever used by a single thread
* (the one in which it was created). You are responsible for ensuring
* that a run loop runs in each thread in which you use an instance, so that
* stats can be updated for that thread every second.
*
* You create an instance of the class for each event/operation that you
* are interested in monitoring, and you call the -add: or -addDuration:
* method to record events.
* For duration logging, you may also use the -startDuration: and
* -endDuration methods to handle adding of the amount of time taken between
* the two calls.
*
* To dump a record of the gathered statistics, you may call the
* -description method of an instance or the class +description method
* to dump statistics for all instances in the current thread.
* If you need to gather a record for all the threads you use, you must
* generate a dump in each thread and combine the results.
*
* To be notified of statistics at the end of each minute, you may call
* the -enableNotifications: method for an instance. The notifications are
* generated in the thread that instance belongs to.
*
*/
@interface GSThroughput : NSObject
{
void *_data;
}
/**
* Return all the current throughput measuring objects in the current thread.
* NB. This does not return instances from other threads.
*/
+ (NSArray*) allInstances;
/**
* Return a report on all GSThroughput instances in the current thread...
* This calls the [GSThroughput-description] method of the individual instances
* to get a report on each one.
* The results are ordered alphabetically by name of the instances (an
* instance without a name is treated as having an empty string as a name).
*/
+ (NSString*) description;
/**
* Instructs the monitoring system to use a timer at the start of each second
* for keeping its idea of the current time up to date. This timer is used
* to call the +tick method in the current thread.
* Passing a value of NO for aFlag will turn off the timer for the current
* thread.
* For the timer to work, the thread's runloop must be running.
* Keeping the notion of the current time up to date is important for
* instances configured to record stats broken down over a number of periods,
* since the periodic breakdown must be adjusted each second.
*/
+ (void) setTick: (BOOL)aFlag;
/**
* Updates the monitoring system's notion of the current time for all
* instances associated with the current thread.
* This should be called at the start of each second (or more often) if
* you want an accurate breakdown of monitoring by the second.
* If you don't want to call this yourself, you can call +setTick: to
* have it called automatically.
* If you are not using any instances of the class configured to maintain
* a breakdown of stats by periods, you do not need to call this method.
*/
+ (void) tick;
/**
* Add to the count of the number of transactions for the receiver.
* You may use this method only if the receiver was initialised with
* duration logging turned off.
*/
- (void) add: (unsigned)count;
/**
* Adds a record for multiple events of the specified
* total duration.
* This is useful where you know a lot of similar events have completed
* in a particular period of time, but can't afford to measure the
* duration of the individual events because the timing overheads
* would be too great.
* You may use this method only if the receiver was initialised with
* duration logging turned on.
*/
- (void) add: (unsigned)count duration: (NSTimeInterval)length;
/**
* Adds a record for a single event of the specified duration.
* You may use this method only if the receiver was initialised with
* duration logging turned on.
*/
- (void) addDuration: (NSTimeInterval)length;
/**
* Returns a string describing the status of the receiver.
* For an instance configured to maintain a periodic breakdown of stats,
* this reports information for the current second, all seconds in the
* current minute, all minutes in the current period, and all periods
* in the configured number of periods.
* For an instance configured with no periodic breakdown, this produces
* a short summary of the total count of events and, where durations are used,
* the maximum, minimum and average duration of events.
*/
- (NSString*) description;
/** Sets a flag to say whether the receiver will send GSThroughputNotification
* at the end of each minute to provide information about statistics.
* The method returnes the previous setting. The initial setting is NO.
* The notification object is the reciever, and the user info dictionary
* contains some or all of the following keys depending on how the receiver
* was configured:
*
* GSThroughputCountKey
* The number of events recorded (unsigned integer number)
* GSThroughputMaximumKey
* The maximum event duration (double floating point number)
* GSThroughputMinimumKey
* The minimum event duration (double floating point number)
* or -1.0 if no events occurred during the minute.
* GSThroughputTimeKey
* The time of the start of the minute (an NSDate)
* GSThroughputTotalKey
* The sum of event durations (double floating point number)
*
*/
- (BOOL) enableNotifications: (BOOL)flag;
/**
* Ends duration recording for the current event started by a matching
* call to the -startDuration: method.
* Calls to this method without a matching call to -startDuration: are
* quietly ignored. This is useful if you wish to time a function or
* method by starting/ending timing before/after calling it, but also
* want the function/method to be able to end timing of itsself before
* it calls another function/method.
*/
- (void) endDuration;
/**
* Acts like -endDuration but records the duration as a total for
* count events (if count is zero then this ends the interval started
* by the corresponding -startDuration: call, but nothing is logged).
* This can be used when recording multiple events where the overhead of
* timing each event individually would be too great.
*/
- (void) endDuration: (unsigned)count;
/**
* Initialises the receiver for duration logging (in the current thread only)
* for fifteen minute periods over the last twentyfour hours.
*/
- (id) init;
/**
* Initialises the receiver to maintain stats (for the current thread only)
* over a particular time range, specifying whether duration statistics are
* to be maintained, or just event/transaction counts.
*
* If the specified numberOfPeriods or minutesPerPeriod is zero, only a
* running total is maintained rather than a per-second breakdown for the
* current minute and per minute breakdown for the current period and
* period breakdown for the number of periods.
*
* If all instances in a thread are initialised with numberOfPeriods or
* minutesPerPeriod of zero, the +tick method does not need to be called and
* +setTick: should not be used.
*
*/
- (id) initWithDurations: (BOOL)aFlag
forPeriods: (unsigned)numberOfPeriods
ofLength: (unsigned)minutesPerPeriod;
/**
* Return the name of this instance (as set using -setName:).
* This is used in the -description method and for ordering instances
* in the +description method.
*/
- (NSString*) name;
/**
* Sets the name of this instance.
*/
- (void) setName: (NSString*)name;
/**
* Starts recording the duration of an event. This must be followed by
* a matching call to the -endDuration method.
* The name argument is used to identify the location of the call for
* debugging/logging purposes, and you must ensure that the string
* continues to exist up to the point where -endDuration is called,
* as the receiver will not retain it.
* You may use this method only if the receiver was initialised with
* duration logging turned on.
* Use of this method if the reciever does not support duration logging
* or if the method has already been called without a matching call to
* -endDuration will cause an exception to be raised.
*/
- (void) startDuration: (NSString*)name;
@end
#endif
Performance-0.6.0/GSThroughput.m 0000664 0000000 0000000 00000061543 14360262662 0016557 0 ustar 00root root 0000000 0000000 /* -*-objc-*- */
/** Implementation of GSThroughput for GNUStep
Copyright (C) 2005 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
Date: October 2005
This file is part of the Performance Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
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$
*/
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import "GSThroughput.h"
#import "GSTicker.h"
NSString * const GSThroughputNotification = @"GSThroughputNotification";
NSString * const GSThroughputCountKey = @"Count";
NSString * const GSThroughputMaximumKey = @"Maximum";
NSString * const GSThroughputMinimumKey = @"Maximum";
NSString * const GSThroughputTimeKey = @"Time";
NSString * const GSThroughputTotalKey = @"Total";
#define MAXDURATION 24.0*60.0*60.0
@class GSThroughputThread;
static Class NSDateClass = 0;
static SEL tiSel = 0;
static NSTimeInterval (*tiImp)(Class,SEL) = 0;
typedef struct {
unsigned cnt; // Number of events.
unsigned tick; // Start time
} CountInfo;
typedef struct {
unsigned cnt; // Number of events.
NSTimeInterval max; // Longest duration
NSTimeInterval min; // Shortest duration
NSTimeInterval sum; // Total (sum of durations for event)
unsigned tick; // Start time
} DurationInfo;
typedef struct {
void *seconds;
void *minutes;
void *periods;
void *total;
BOOL supportDurations;
BOOL notify;
unsigned numberOfPeriods;
unsigned minutesPerPeriod;
unsigned second;
unsigned minute;
unsigned period;
unsigned last; // last tick used
NSTimeInterval started; // When duration logging started.
NSString *event; // Name of current event
NSString *name; // Name of this instance
GSThroughputThread *thread; // Thread info
} Item;
#define my ((Item*)_data)
#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)
@interface GSThroughputThread : NSObject
{
@public
NSHashTable *instances;
}
@end
@interface GSThroughput (Private)
+ (GSThroughputThread*) _threadInfo;
+ (void) newSecond: (GSThroughputThread*)t;
- (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
{
if (nil != (self = [super init]))
{
instances = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
}
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"];
[t release];
}
return t;
}
+ (void) newSecond: (GSThroughputThread*)t
{
NSHashEnumerator e;
GSThroughput *i;
e = NSEnumerateHashTable(t->instances);
while ((i = (GSThroughput*)NSNextHashEnumeratorItem(&e)) != nil)
{
[i _update];
}
NSEndHashTableEnumeration(&e);
}
- (void) _detach
{
my->thread = nil;
}
- (void) _update
{
NSTimeInterval base;
unsigned tick;
if (my->thread == nil)
{
return;
}
base = GSTickerTimeStart();
tick = GSTickerTimeTick();
if (my->numberOfPeriods > 0)
{
unsigned i;
if (my->supportDurations == YES)
{
while (my->last < tick)
{
DurationInfo *info;
if (my->second++ == 59)
{
info = &dminutes[my->minute];
for (i = 0; i < 60; i++)
{
DurationInfo *from = &dseconds[i];
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;
}
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:
base + my->last - 60],
GSThroughputTimeKey,
nil]];
if (info->min < 0.0)
{
info->min = MAXDURATION;
}
}
if (my->minute++ == my->minutesPerPeriod - 1)
{
info = &dperiods[my->period];
for (i = 0; i < my->minutesPerPeriod; i++)
{
DurationInfo *from = &dminutes[i];
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;
}
if (my->period++ == my->numberOfPeriods - 1)
{
my->period = 0;
}
info = &dperiods[my->period];
info->cnt = 0;
info->max = 0.0;
info->min = MAXDURATION;
info->sum = 0.0;
info->tick = my->last;
my->minute = 0;
}
info = &dminutes[my->minute];
info->cnt = 0;
info->max = 0.0;
info->min = MAXDURATION;
info->sum = 0.0;
info->tick = my->last;
my->second = 0;
}
info = &dseconds[my->second];
info->cnt = 0;
info->max = 0.0;
info->min = MAXDURATION;
info->sum = 0.0;
info->tick = my->last;
my->last++;
}
}
else
{
while (my->last < tick)
{
CountInfo *info;
if (my->second++ == 59)
{
info = &cminutes[my->minute];
for (i = 0; i < 60; i++)
{
info->cnt += cseconds[i].cnt;
}
if (my->notify == YES && my->last > 59)
{
[[NSNotificationCenter defaultCenter]
postNotificationName: GSThroughputNotification
object: self
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt: info->cnt],
GSThroughputCountKey,
[NSDate dateWithTimeIntervalSinceReferenceDate:
base + my->last - 60],
GSThroughputTimeKey,
nil]];
}
if (my->minute++ == my->minutesPerPeriod - 1)
{
info = &cperiods[my->period];
for (i = 0; i < my->minutesPerPeriod; i++)
{
info->cnt += cminutes[i].cnt;
}
if (my->period++ == my->numberOfPeriods - 1)
{
my->period = 0;
}
info = &cperiods[my->period];
info->cnt = 0;
info->tick = my->last;
my->minute = 0;
}
info = &cminutes[my->minute];
info->cnt = 0;
info->tick = my->last;
my->second = 0;
}
info = &cseconds[my->second];
info->cnt = 0;
info->tick = my->last;
my->last++;
}
}
}
else
{
while (my->last < tick)
{
if (my->second++ == 59)
{
my->second = 0;
if (my->supportDurations == YES)
{
DurationInfo *info = &dseconds[1];
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:
base + my->last - 60],
GSThroughputTimeKey,
nil]];
}
info->cnt = 0;
info->max = 0.0;
info->min = MAXDURATION;
info->sum = 0.0;
}
else
{
CountInfo *info = &cseconds[1];
if (my->notify == YES && my->last > 59)
{
[[NSNotificationCenter defaultCenter]
postNotificationName: GSThroughputNotification
object: self
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt: info->cnt],
GSThroughputCountKey,
[NSDate dateWithTimeIntervalSinceReferenceDate:
base + my->last - 60],
GSThroughputTimeKey,
nil]];
}
info->cnt = 0;
}
}
my->last++;
}
}
}
@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;
}
+ (NSString*) description
{
GSThroughputThread *t;
NSMutableString *ms;
ms = [NSMutableString stringWithString: [super description]];
t = [[[NSThread currentThread] threadDictionary]
objectForKey: @"GSThroughput"];
if (t != nil)
{
NSArray *a;
NSEnumerator *e;
GSThroughput *c;
a = [NSAllHashTableObjects(t->instances) sortedArrayUsingSelector:
@selector(compare:)];
e = [a objectEnumerator];
while ((c = (GSThroughput*)[e nextObject]) != nil)
{
[ms appendFormat: @"\n%@", [c description]];
}
}
return ms;
}
+ (void) initialize
{
if (NSDateClass == 0)
{
NSDateClass = [NSDate class];
tiSel = @selector(timeIntervalSinceReferenceDate);
tiImp
= (NSTimeInterval (*)(Class,SEL))[NSDateClass methodForSelector: tiSel];
}
}
+ (void) setTick: (BOOL)aFlag
{
if (aFlag == YES)
{
GSThroughputThread *t = [self _threadInfo];
[GSTicker registerObserver: (id)self userInfo: t];
}
else
{
[GSTicker unregisterObserver: (id)self];
}
}
+ (void) tick
{
[self newSecond: [self _threadInfo]];
}
- (void) add: (unsigned)count
{
if (NO != my->supportDurations)
{
[NSException raise: NSInternalInconsistencyException
format: @"-add: called when set for durations"];
}
if (my->numberOfPeriods == 0)
{
cseconds[0].cnt += count; // Total
cseconds[1].cnt += count; // Current minute
}
else
{
cseconds[my->second].cnt += count;
}
}
- (void) add: (unsigned)count duration: (NSTimeInterval)length
{
if (YES != my->supportDurations)
{
[NSException raise: NSInternalInconsistencyException
format: @"-add:duration: called when not set for durations"];
}
if (count > 0)
{
NSTimeInterval total = length;
unsigned from;
unsigned to;
length /= count;
if (my->numberOfPeriods == 0)
{
from = 0; // total
to = 1; // current minute
}
else
{
from = my->second;
to = from;
}
while (from <= to)
{
DurationInfo *info = &dseconds[from++];
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;
}
}
}
}
}
- (void) addDuration: (NSTimeInterval)length
{
unsigned from;
unsigned to;
if (YES != my->supportDurations)
{
[NSException raise: NSInternalInconsistencyException
format: @"-addDuration: called when not set for durations"];
}
if (my->numberOfPeriods == 0)
{
from = 0; // Total
to = 1; // Current minute
}
else
{
from = my->second;
to = from;
}
while (from <= to)
{
DurationInfo *info = &dseconds[from++];
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;
}
}
}
}
- (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;
}
- (void) dealloc
{
if (_data)
{
if (my->seconds != 0)
{
NSZoneFree(NSDefaultMallocZone(), my->seconds);
}
[my->name release];
if (my->thread != nil)
{
NSHashRemove(my->thread->instances, (void*)self);
my->thread = nil;
}
NSZoneFree(NSDefaultMallocZone(), _data);
_data = 0;
}
[super dealloc];
}
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);
}
- (NSString*) description
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSString *n = my->name;
NSMutableString *m;
unsigned i;
if (n == nil)
{
n = [super description];
}
m = [n mutableCopy];
if (my->thread != nil)
{
NSTimeInterval baseTime = GSTickerTimeStart();
unsigned tick;
if (my->numberOfPeriods == 0)
{
if (my->supportDurations == YES)
{
DurationInfo *info = &dseconds[0];
[m appendFormat: @": cnt %u, max %g, min %g, avg %g",
info->cnt, info->max,
info->min == MAXDURATION ? 0.0 : info->min,
info->cnt == 0 ? 0 : info->sum / info->cnt];
}
else
{
CountInfo *info = &cseconds[0];
[m appendFormat: @": cnt %u", info->cnt];
}
}
else
{
if (my->supportDurations == YES)
{
[m appendString: @"\nSeconds in current minute:\n"];
if (my->second > 0)
{
tick = 0;
for (i = 0; i < my->second; i++)
{
DurationInfo *info = &dseconds[i];
if (info->tick != tick)
{
tick = info->tick;
appendDurationInfo(info, m, baseTime);
}
}
}
[m appendString: @"\nPrevious minutes in current period:\n"];
if (my->minute > 0)
{
tick = 0;
for (i = 0; i < my->minute; i++)
{
DurationInfo *info = &dminutes[i];
if (info->tick != tick)
{
tick = info->tick;
appendDurationInfo(info, m, baseTime);
}
}
}
[m appendString: @"\nPrevious periods:\n"];
if (my->period > 0)
{
tick = 0;
/* Periods from last cycle
*/
for (i = my->period; i < my->numberOfPeriods; i++)
{
DurationInfo *info = &dperiods[i];
if (info->tick != tick)
{
tick = info->tick;
appendDurationInfo(info, m, baseTime);
}
}
/* Periods from current cycle
*/
for (i = 0; i < my->period; i++)
{
DurationInfo *info = &dperiods[i];
if (info->tick != tick)
{
tick = info->tick;
appendDurationInfo(info, m, baseTime);
}
}
}
}
else
{
[m appendString: @"\nSeconds in current minute:\n"];
if (my->second > 0)
{
tick = 0;
for (i = 0; i < my->second; i++)
{
CountInfo *info = &cseconds[i];
if (info->tick != tick)
{
tick = info->tick;
appendCountInfo(info, m, baseTime);
}
}
}
[m appendString: @"\nPrevious minutes in current period:\n"];
if (my->minute > 0)
{
tick = 0;
for (i = 0; i < my->minute; i++)
{
CountInfo *info = &cminutes[i];
if (info->tick != tick)
{
tick = info->tick;
appendCountInfo(info, m, baseTime);
}
}
}
[m appendString: @"\nPrevious periods:\n"];
if (my->period > 0)
{
tick = 0;
/* Periods from last cycle
*/
for (i = my->period; i < my->numberOfPeriods; i++)
{
CountInfo *info = &cperiods[i];
if (info->tick != tick)
{
tick = info->tick;
appendCountInfo(info, m, baseTime);
}
}
/* Periods from current cycle
*/
for (i = 0; i < my->period; i++)
{
CountInfo *info = &cperiods[i];
if (info->tick != tick)
{
tick = info->tick;
appendCountInfo(info, m, baseTime);
}
}
}
}
}
}
[pool release];
return [m autorelease];
}
- (void) endDuration
{
if (my->started > 0.0)
{
NSTimeInterval ti;
ti = (*tiImp)(NSDateClass, tiSel) - my->started;
my->event = nil;
my->started = 0.0;
[self addDuration: ti];
}
}
- (BOOL) enableNotifications: (BOOL)flag
{
BOOL old = my->notify;
my->notify = flag;
return old;
}
- (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;
}
}
- (id) init
{
return [self initWithDurations: YES
forPeriods: 96
ofLength: 15];
}
- (id) initWithDurations: (BOOL)aFlag
forPeriods: (unsigned)numberOfPeriods
ofLength: (unsigned)minutesPerPeriod
{
if (nil != (self = [super init]))
{
NSCalendarDate *c;
unsigned i;
_data = (Item*)NSZoneCalloc(NSDefaultMallocZone(), 1, sizeof(Item));
/*
* Add this instance to the current thread.
*/
my->thread = [[self class] _threadInfo];
NSHashInsert(my->thread->instances, (void*)self);
my->supportDurations = aFlag;
my->notify = NO;
my->last = GSTickerTimeTick();
c = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate:
GSTickerTimeLast()];
my->second = [c secondOfMinute];
i = [c hourOfDay] * 60 + [c minuteOfHour];
if (numberOfPeriods < 1 || minutesPerPeriod < 1)
{
/* 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)
{
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;
}
else
{
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;
}
}
else
{
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;
}
}
[c release];
}
return self;
}
- (NSString*) name
{
return my->name;
}
- (void) setName: (NSString*)name
{
[name retain];
[my->name release];
my->name = name;
}
- (void) startDuration: (NSString*)name
{
if (NO == my->supportDurations)
{
[NSException raise: NSInternalInconsistencyException
format: @"-startDuration: for '%@' when not set for durations", name];
}
if (0.0 != my->started)
{
[NSException raise: NSInternalInconsistencyException
format: @"-startDuration: for '%@' when already started", name];
}
if (my->event != nil)
{
[NSException raise: NSInternalInconsistencyException
format: @"-startDuration: for '%@' nested inside '%@'",
my->event, name];
}
my->started = (*tiImp)(NSDateClass, tiSel);
my->event = name;
}
@end
Performance-0.6.0/GSTicker.h 0000664 0000000 0000000 00000011667 14360262662 0015624 0 ustar 00root root 0000000 0000000 /**
Copyright (C) 2005 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
Date: Nov 2005
This file is part of the Performance Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
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$
*/
#ifndef INCLUDED_GSTicker_H
#define INCLUDED_GSTicker_H
@class NSDate;
/**
* Returns the timestamp of the most recent call to GSTickerTimeNow().
*/
extern NSTimeInterval GSTickerTimeLast();
/**
* Convenience function to provide timing information quickly.
* This returns the current date/time, and stores the value for use
* by the GSTickerTimeLast() function.
*/
extern NSTimeInterval GSTickerTimeNow();
/**
* This returns the timestamp from which GSTicker was first used.
*/
extern NSTimeInterval GSTickerTimeStart();
/**
* A convenience method to return the current clock 'tick' ... which is
* the current second based on the time we started. This does not
* check the current time, but relies on GSTickerTimeLast() returning an
* up to date value (so if you need an accurate tick, you should ensure
* that GSTickerTimeNow() is called at least once a second).
* The returned value is always greater than zero, and is basically
* calculated as (GSTickerTimeLast() - GSTickerTimeStart() + 1).
* In the event that the system clock is reset into the past, the value
* of GSTickerTimeStart() is automatically adjusted to ensure that the
* result of a call to GSTickerTimeTick() is never less than the result
* of any earlier call to the function.
*/
extern unsigned GSTickerTimeTick();
@protocol GSTicker
/**
* Sent to tell observers that the ticker has noticed that a new
* second has occurred. The tick argument is the user information
* provided in when registering the observer.
* This message is sent to each registered observer when the timeout
* for the thread occurs. It is not guaranteed to be called every
* second ... other processing in the thread may delay it.
*/
- (void) newSecond: (id)userInfo;
@end
/**
* Wrapper round the more efficient ticker functions ... this class
* provides convenience methods to get NSDate objects, and also
* provides support for registering observers ofr second by second
* ticks.
*/
@interface GSTicker : NSObject
{
}
/**
* Calls GSTickerTimeLast() and returns the result as an NSDate.
*/
+ (NSDate*) last;
/**
* A dummy method ... does nothing, but allows the GSTicker class itsself
* to act as an observer of regular timeouts.
* Thus, you may register the class as its own observer in order to set
* up a timer to ensure that date/time information is updated at the
* start of every second.
*/
+ (void) newSecond: (id)userInfo;
/**
* Calls GSTickerTimeNow() and returns the result as an NSDate.
*/
+ (NSDate*) now;
/**
* Registers an object to receive a [(GSTicker)-newSecond:] message
* at the start of every second.
* Also starts a timer in the current thread (unless one is already
* running) to notify registered objects of new seconds.
* The observer and the userInfo are retained by the ticker.
* Adding an observer more than once has no effect.
* NB. You must not add or remove observers inside the callback routine.
*/
+ (void) registerObserver: (id)anObject
userInfo: (id)userInfo;
/**
* Returns the result of GSTickerTimeStart() as an NSDate.
*/
+ (NSDate*) start;
/**
* Calls GSTickerTimeTick() and returns the result.
*/
+ (unsigned) tick;
/**
* Unregisters an observer previously set in the current thread using
* the +registerObserver:userInfo: method.
* If all observers in a thread are removed, the timer for the thread
* is cancelled at the start of the next second.
*/
+ (void) unregisterObserver: (id)anObject;
/**
* Calls GSTickerTimeNow();
*/
+ (void) update;
/**
* Calls GSTickerTimeLast() and returns the result as an NSDate.
*/
- (NSDate*) last;
/**
* See +newSecond:
*/
- (void) newSecond: (id)userInfo;
/**
* Calls GSTickerTimeNow() and returns the result as an NSDate.
*/
- (NSDate*) now;
/**
* Returns the result of GSTickerTimeStart() as an NSDate.
*/
- (NSDate*) start;
/**
* Calls GSTickerTimeTick() and returns the result.
*/
- (unsigned) tick;
/**
* Calls GSTickerTimeNow();
*/
- (void) update;
@end
#endif
Performance-0.6.0/GSTicker.m 0000664 0000000 0000000 00000016507 14360262662 0015627 0 ustar 00root root 0000000 0000000 /* -*-objc-*- */
/** Implementation of GSTicker for GNUStep
Copyright (C) 2005 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
Date: November 2005
This file is part of the Performance Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
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$
*/
#import
#import
#import
#import
#import
#import
#import
#import "GSTicker.h"
static Class NSDateClass = 0;
static NSDate *startDate = nil;
static SEL tiSel = 0;
static NSTimeInterval (*tiImp)(Class,SEL) = 0;
static volatile NSTimeInterval baseTime = 0;
static volatile NSTimeInterval lastTime = 0;
@interface GSTickerObservation : NSObject
{
@public
id observer;
id userInfo;
}
- (void) fire: (NSArray*)live;
@end
@implementation GSTickerObservation
- (void) fire: (NSArray*)live
{
if ([live indexOfObjectIdenticalTo: self] != NSNotFound)
{
[observer newSecond: userInfo];
}
}
@end
@interface GSTickerThread : NSObject
{
@public
/* NB. We retain theTimer rather than depending on the run loop to do it.
* This is because tis object is typically deallocated on thread exist,
* so the thread's run loop may be deallocated before this object is
* deallocated, and we want to be sure the timer is not already deallocated
* when we invalidate it.
*/
NSTimer *theTimer;
NSMutableArray *observers;
unsigned last;
}
@end
@implementation GSTickerThread
- (void) dealloc
{
[theTimer invalidate];
[theTimer release];
theTimer = nil;
[observers release];
observers = nil;
[super dealloc];
}
- (id) init
{
if (nil != (self = [super init]))
{
NSTimeInterval ti = GSTickerTimeNow();
observers = [NSMutableArray new];
theTimer = [[NSTimer scheduledTimerWithTimeInterval: ti - (int)ti
target: [GSTicker class]
selector: @selector(_tick:)
userInfo: self
repeats: NO] retain];
}
return self;
}
@end
@interface GSTicker (Private)
+ (void) _tick: (NSTimer*)t;
@end
inline NSTimeInterval GSTickerTimeLast()
{
return lastTime;
}
inline NSTimeInterval GSTickerTimeStart()
{
if (baseTime == 0)
{
[GSTicker class];
}
return baseTime;
}
inline unsigned GSTickerTimeTick()
{
NSTimeInterval start = GSTickerTimeStart();
return (GSTickerTimeLast() - start) + 1;
}
NSTimeInterval GSTickerTimeNow()
{
if (baseTime == 0)
{
[GSTicker class];
}
else
{
NSTimeInterval now;
/*
* If the clock has been reset so that time has gone backwards,
* we adjust the baseTime so that lastTime >= baseTime is true.
*/
now = (*tiImp)(NSDateClass, tiSel);
if (now < lastTime)
{
baseTime -= (lastTime - now);
}
lastTime = now;
}
return lastTime;
}
@implementation GSTicker
+ (void) initialize
{
if (0 == baseTime)
{
NSDateClass = [NSDate class];
tiSel = @selector(timeIntervalSinceReferenceDate);
tiImp
= (NSTimeInterval (*)(Class,SEL))[NSDateClass methodForSelector: tiSel];
baseTime = lastTime = (*tiImp)(NSDateClass, tiSel);
startDate = [[NSDateClass alloc]
initWithTimeIntervalSinceReferenceDate: baseTime];
}
}
+ (NSDate*) last
{
return [NSDateClass dateWithTimeIntervalSinceReferenceDate:
GSTickerTimeLast()];
}
+ (void) newSecond: (id)userInfo
{
return;
}
+ (NSDate*) now
{
return [NSDateClass dateWithTimeIntervalSinceReferenceDate:
GSTickerTimeNow()];
}
+ (void) registerObserver: (id)anObject
userInfo: (id)userInfo
{
GSTickerThread *tt;
GSTickerObservation *to;
unsigned count;
tt = [[[NSThread currentThread] threadDictionary]
objectForKey: @"GSTickerThread"];
if (tt == nil)
{
tt = [GSTickerThread new];
[[[NSThread currentThread] threadDictionary]
setObject: tt forKey: @"GSTickerThread"];
[tt release];
}
count = [tt->observers count];
while (count-- > 0)
{
to = [tt->observers objectAtIndex: count];
if (to->observer == anObject)
{
return; // Already registered.
}
}
to = [GSTickerObservation new];
to->observer = anObject;
to->userInfo = userInfo;
[tt->observers addObject: to];
[to release];
}
+ (NSDate*) start
{
if (startDate == nil)
{
startDate = [NSDateClass alloc];
startDate = [startDate initWithTimeIntervalSinceReferenceDate:
GSTickerTimeStart()];
}
return startDate;
}
+ (unsigned) tick
{
return GSTickerTimeTick();
}
+ (void) unregisterObserver: (id)anObject
{
GSTickerThread *tt;
tt = [[[NSThread currentThread] threadDictionary]
objectForKey: @"GSTickerThread"];
if (tt != nil)
{
GSTickerObservation *to;
unsigned count = [tt->observers count];
while (count-- > 0)
{
to = [tt->observers objectAtIndex: count];
if (to->observer == anObject)
{
[tt->observers removeObjectAtIndex: count];
break;
}
}
}
}
+ (void) update
{
GSTickerTimeNow();
}
- (NSDate*) last
{
return [NSDateClass dateWithTimeIntervalSinceReferenceDate:
GSTickerTimeLast()];
}
- (void) newSecond: (id)userInfo
{
return;
}
- (NSDate*) now
{
return [NSDateClass dateWithTimeIntervalSinceReferenceDate:
GSTickerTimeNow()];
}
- (NSDate*) start
{
return startDate;
}
- (unsigned) tick
{
return GSTickerTimeTick();
}
- (void) update
{
GSTickerTimeNow();
}
@end
@implementation GSTicker (Private)
+ (void) _tick: (NSTimer*)t
{
GSTickerThread *tt = [t userInfo];
if (tt == nil)
{
tt = [[[NSThread currentThread] threadDictionary]
objectForKey: @"GSTickerThread"];
}
if (tt != nil && [tt->observers count] > 0)
{
NSTimeInterval ti;
[tt->theTimer invalidate];
[tt->theTimer release];
tt->theTimer = nil;
if ([tt->observers count] > 0)
{
NSArray *a;
unsigned tick;
GSTickerTimeNow();
tick = GSTickerTimeTick();
if (tick != tt->last)
{
tt->last = tick;
a = [tt->observers copy];
NS_DURING
{
[a makeObjectsPerformSelector: @selector(fire:)
withObject: tt->observers];
}
NS_HANDLER
{
NSLog(@"Problem firing ticker observers: %@", localException);
}
NS_ENDHANDLER
[a release];
}
}
ti = GSTickerTimeNow();
tt->theTimer = [[NSTimer scheduledTimerWithTimeInterval: ti - (int)ti
target: self
selector: @selector(_tick:)
userInfo: tt
repeats: NO] retain];
}
else
{
[[[NSThread currentThread] threadDictionary]
removeObjectForKey: @"GSTickerThread"];
}
}
@end
Performance-0.6.0/GSUniqued.h 0000664 0000000 0000000 00000006365 14360262662 0016014 0 ustar 00root root 0000000 0000000 #if !defined(INCLUDED_GSUNIQUED)
#define INCLUDED_GSUNIQUED 1
/**
Copyright (C) 2014 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
Date: April 2014
This file is part of the Performance Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#import
/** Class used to unique other objects.
* The point of this class is to lower the memory footprint and speed
* up comparisons (pointer equality) in cases where an application
* stores multiple copies of the same object in various maps.
* Since uniquing is performed by storing an immutable copy of the
* original object in a map until there are no further references
* to that object, it's pointless to use this uniquing unless the
* application would be storing at least two copies of the object.
* Also, since this is thread-safe there is a lock management
* overhead wherever a uniqued object is released, so performance
* gains are to be expected only if the uniqued object has a
* relatively long lifetime and is tested for equality with other
* instances frequently.
* In short, use with care; while uniquing can have a big performance
* advantage for some programs, this is actually quite rare.
*
* The internal implementation of the uniquing works by taking
* immutable copies of the objects to be uniqued, storing those copies
* in a hash table, and swizzling their class pointers to a sub-class
* which will automatically remove the instance from the hash table
* before it is deallocated.
* Access to the hash table is protected by locks so that uniqued
* objects may be used freely in multiple threads.
* The name of the subclass used is the name of the original class
* with 'GSUniqued' added as a prefix.
*
*/
@interface GSUniqued : NSObject
/** This method returns a copy of its argument, uniqued so that other
* such copies of equal objects will be the same instance.
* The argument must respond to -copyWithZone: by returning an instance
* of class of immutable objects (ie where the -hash and -isEqual:
* methods are stable for that instance).
*/
+ (id) copyUniqued: (id)anObject;
@end
/** Category for uniquing any copyable object.
* NB. This must only be used by classes for which -copyWithZone:
* produces an instance of an immutable class.
*/
@interface NSObject (GSUniqued)
/** This method returns a copy of the receiver uniqued so that other
* such copies of equal objects content will be the same instance.
*/
- (id) copyUniqued;
@end
#endif
Performance-0.6.0/GSUniqued.m 0000664 0000000 0000000 00000014074 14360262662 0016015 0 ustar 00root root 0000000 0000000 /**
Copyright (C) 2014 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
Date: April 2014
This file is part of the Performance Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#import
#import
#import
#import
#import
#import
#import
#import "GSUniqued.h"
static Class GSUniquedClass = Nil;
static NSLock *uniquedObjectsLock;
static IMP iLock;
static IMP iUnlock;
static NSHashTable *uniquedObjects;
static NSLock *classLock;
static NSMutableDictionary *classMap;
/* Deallocate a uniqued object ... we must remove it from the uniqued
* objects table and then call the real -dealloc method.
*/
static void
uDealloc(id self, SEL _cmd)
{
Class c;
IMP i;
NSHashRemove(uniquedObjects, self);
c = object_getClass(self);
c = class_getSuperclass(c);
i = class_getMethodImplementation(c, _cmd);
(*i)(self, _cmd);
}
/* Release a uniqued object ... we must obtain a lock in case the uniqued
* objects table has to be modified by removal of this instance on
* deallocation.
*/
static void
uRelease(id self, SEL _cmd)
{
Class c;
IMP i;
c = object_getClass(self);
c = class_getSuperclass(c);
i = class_getMethodImplementation(c, _cmd);
(*iLock)(uniquedObjectsLock, @selector(lock));
(*i)(self, _cmd);
(*iUnlock)(uniquedObjectsLock, @selector(unlock));
}
@implementation GSUniqued
static Class NSObjectClass;
+ (void) initialize
{
if (Nil == GSUniquedClass)
{
classLock = [NSLock new];
classMap = [NSMutableDictionary new];
uniquedObjectsLock = [NSLock new];
iLock = [uniquedObjectsLock methodForSelector: @selector(lock)];
iUnlock = [uniquedObjectsLock methodForSelector: @selector(unlock)];
uniquedObjects = NSCreateHashTable(
NSNonRetainedObjectHashCallBacks, 10000);
NSObjectClass = [NSObject class];
GSUniquedClass = [GSUniqued class];
}
}
+ (id) allocWithZone: (NSZone*)z
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to allocate instance of GSUniqued"];
return nil;
}
+ (id) copyUniqued: (id)anObject
{
NSObject *found;
NSAssert(nil != anObject, NSInvalidArgumentException);
(*iLock)(uniquedObjectsLock, @selector(lock));
found = [(NSObject*)NSHashGet(uniquedObjects, anObject) retain];
(*iUnlock)(uniquedObjectsLock, @selector(unlock));
if (nil == found)
{
NSObject *aCopy;
Class c;
Class u;
aCopy = [anObject copyWithZone: NSDefaultMallocZone()];
if (aCopy == anObject)
{
/* Unable to make a copy ... that probably means the object
* is already unique and we can just return it.
*/
if (NO == [aCopy isKindOfClass: [NSString class]])
{
return aCopy;
}
else
{
NSMutableString *m;
/* We have different subclasses of NSString and we can't swizzle
* a constant string, so in that case we need to work with another
* type of string.
*/
m = [aCopy mutableCopy];
[aCopy release];
aCopy = [m copy];
[m release];
}
}
c = object_getClass(aCopy);
[classLock lock];
u = [classMap objectForKey: (id)c];
if (Nil == u)
{
const char *cn = class_getName(c);
char name[strlen(cn) + 20];
Method method;
sprintf(name, "GSUniqued%s", cn);
u = objc_allocateClassPair(c, name, 0);
method = class_getInstanceMethod(NSObjectClass,
@selector(dealloc));
class_addMethod(u, @selector(dealloc),
(IMP)uDealloc, method_getTypeEncoding(method));
method = class_getInstanceMethod(NSObjectClass,
@selector(release));
class_addMethod(u, @selector(release),
(IMP)uRelease, method_getTypeEncoding(method));
method = class_getInstanceMethod(GSUniquedClass,
@selector(copyUniqued));
class_addMethod(u, @selector(copyUniqued),
class_getMethodImplementation(GSUniquedClass,
@selector(copyUniqued)),
method_getTypeEncoding(method));
objc_registerClassPair(u);
[classMap setObject: u forKey: (id)c];
}
[classLock unlock];
(*iLock)(uniquedObjectsLock, @selector(lock));
found = [(NSObject*)NSHashGet(uniquedObjects, anObject) retain];
if (nil == found)
{
found = aCopy;
#if defined(GNUSTEP)
GSClassSwizzle(found, u);
#else
object_setClass(found, u);
#endif
NSHashInsert(uniquedObjects, found);
}
else
{
[aCopy release]; // Already uniqued by another thread
}
(*iUnlock)(uniquedObjectsLock, @selector(unlock));
}
return found;
}
- (id) copyUniqued
{
return [self retain];
}
@end
@implementation NSObject (GSUniqued)
- (id) copyUniqued
{
if (Nil == GSUniquedClass) [GSUniqued class];
return [GSUniquedClass copyUniqued: (id)self];
}
@end
Performance-0.6.0/Info.plist 0000664 0000000 0000000 00000001413 14360262662 0015734 0 ustar 00root root 0000000 0000000
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
org.gnustep.performance
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
FMWK
CFBundleSignature
????
CFBundleVersion
1.0
NSPrincipalClass
Performance-0.6.0/NSObject+GSExtensions.h 0000664 0000000 0000000 00000004117 14360262662 0020175 0 ustar 00root root 0000000 0000000 /** Declaration of extension methods for base additions
Copyright (C) 2003-2010 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
and: Adam Fedor
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import
#if !defined(GNUSTEP)
#define RETAIN(x) ([x retain])
#endif
@class NSHashTable;
@interface NSObject(MemoryFootprint)
/* This method returns the memory usage of the receiver, excluding any
* objects already present in the exclude table.
* The argument is a hash table configured to hold non-retained pointer
* objects and is used to inform the receiver that its size should not
* be counted again if it's already in the table.
* The NSObject implementation returns zero if the receiver is in the
* table, but otherwise adds itself to the table and returns its memory
* footprint (the sum of all of its instance variables, but not any
* memory pointed to by those variables).
* Subclasses should override this method by calling the superclass
* implementation, and either return the result (if it was zero) or
* return that value plus the sizes of any memory owned by the receiver
* (eg found by calling the same method on objects pointed to by the
* receiver's instance variables).
*/
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude;
@end
Performance-0.6.0/NSObject+GSExtensions.m 0000664 0000000 0000000 00000002472 14360262662 0020204 0 ustar 00root root 0000000 0000000 /* Implementation of extension methods to base additions
Copyright (C) 2010 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import
@implementation NSObject (MemoryFootprint)
+ (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
return 0;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
if (0 == NSHashGet(exclude, self))
{
NSHashInsert(exclude, self);
return class_getInstanceSize(object_getClass(self));
}
return 0;
}
@end
Performance-0.6.0/Performance.h 0000664 0000000 0000000 00000002274 14360262662 0016404 0 ustar 00root root 0000000 0000000 /*
JIGS import file for the GNUstep Performance Library.
Copyright (C) 2005 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald
Date: Novb 2005
This file is part of the GNUstep Performance Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import "GSCache.h"
#import "GSFIFO.h"
#import "GSIOThreadPool.h"
#import "GSLinkedList.h"
#import "GSThreadPool.h"
#import "GSThroughput.h"
#import "GSTicker.h"
#import "GSSkipMutableArray.h"
#import "GSUniqued.h"
Performance-0.6.0/Performance.jigs 0000664 0000000 0000000 00000001116 14360262662 0017103 0 ustar 00root root 0000000 0000000 { /* -*-c-*- */
"prerequisite libraries" = (
"gnustep-base"
);
types = {
NSTimeInterval = double;
};
classes = (
{
"java name" = "gnu.gnustep.Performance.GSCache";
"objective-c name" = "GSCache";
"class methods" = (
"allInstances"
);
"instance methods" = (
"currentObjects",
"currentSize",
"lifetime",
"maxObjects",
"maxSize",
"name",
"objectForKey:",
"purge",
"setLifetime:",
"setMaxObjects:",
"setMaxSize:",
"setName:",
"setObject:forKey:",
"setObject:forKey:lifetime:",
"shrinkObjects:andSize:"
);
},
);
}
Performance-0.6.0/Performance.xcodeproj/ 0000775 0000000 0000000 00000000000 14360262662 0020222 5 ustar 00root root 0000000 0000000 Performance-0.6.0/Performance.xcodeproj/project.pbxproj 0000664 0000000 0000000 00000047530 14360262662 0023307 0 ustar 00root root 0000000 0000000 // !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
85872EC11284CFC700B4601E /* GSCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EB01284CFC700B4601E /* GSCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872EC21284CFC700B4601E /* GSCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EB11284CFC700B4601E /* GSCache.m */; };
85872EC31284CFC700B4601E /* GSIndexedSkipList.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EB21284CFC700B4601E /* GSIndexedSkipList.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872EC41284CFC700B4601E /* GSIndexedSkipList.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EB31284CFC700B4601E /* GSIndexedSkipList.m */; };
85872EC51284CFC700B4601E /* GSIOThreadPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EB41284CFC700B4601E /* GSIOThreadPool.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872EC61284CFC700B4601E /* GSIOThreadPool.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EB51284CFC700B4601E /* GSIOThreadPool.m */; };
85872EC71284CFC700B4601E /* GSLinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EB61284CFC700B4601E /* GSLinkedList.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872EC81284CFC700B4601E /* GSLinkedList.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EB71284CFC700B4601E /* GSLinkedList.m */; };
85872EC91284CFC700B4601E /* GSSkipMutableArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EB81284CFC700B4601E /* GSSkipMutableArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872ECA1284CFC700B4601E /* GSSkipMutableArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EB91284CFC700B4601E /* GSSkipMutableArray.m */; };
85872ECB1284CFC700B4601E /* GSThreadPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EBA1284CFC700B4601E /* GSThreadPool.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872ECC1284CFC700B4601E /* GSThreadPool.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EBB1284CFC700B4601E /* GSThreadPool.m */; };
85872ECD1284CFC700B4601E /* GSThroughput.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EBC1284CFC700B4601E /* GSThroughput.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872ECE1284CFC700B4601E /* GSThroughput.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EBD1284CFC700B4601E /* GSThroughput.m */; };
85872ECF1284CFC700B4601E /* GSTicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EBE1284CFC700B4601E /* GSTicker.h */; settings = {ATTRIBUTES = (Public, ); }; };
85872ED01284CFC700B4601E /* GSTicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 85872EBF1284CFC700B4601E /* GSTicker.m */; };
85872ED11284CFC700B4601E /* Performance.h in Headers */ = {isa = PBXBuildFile; fileRef = 85872EC01284CFC700B4601E /* Performance.h */; settings = {ATTRIBUTES = (Public, ); }; };
85B7DBDC1C034FBA00AF3090 /* NSObject+GSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 85B7DBDA1C034FBA00AF3090 /* NSObject+GSExtensions.h */; };
85B7DBDD1C034FBA00AF3090 /* NSObject+GSExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 85B7DBDB1C034FBA00AF3090 /* NSObject+GSExtensions.m */; };
85B7DC031C036A0900AF3090 /* GSFIFO.h in Headers */ = {isa = PBXBuildFile; fileRef = 85B7DC011C036A0900AF3090 /* GSFIFO.h */; };
85B7DC041C036A0900AF3090 /* GSFIFO.m in Sources */ = {isa = PBXBuildFile; fileRef = 85B7DC021C036A0900AF3090 /* GSFIFO.m */; };
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; };
1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; };
85872EB01284CFC700B4601E /* GSCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSCache.h; sourceTree = ""; };
85872EB11284CFC700B4601E /* GSCache.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSCache.m; sourceTree = ""; };
85872EB21284CFC700B4601E /* GSIndexedSkipList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSIndexedSkipList.h; sourceTree = ""; };
85872EB31284CFC700B4601E /* GSIndexedSkipList.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSIndexedSkipList.m; sourceTree = ""; };
85872EB41284CFC700B4601E /* GSIOThreadPool.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSIOThreadPool.h; sourceTree = ""; };
85872EB51284CFC700B4601E /* GSIOThreadPool.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSIOThreadPool.m; sourceTree = ""; };
85872EB61284CFC700B4601E /* GSLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSLinkedList.h; sourceTree = ""; };
85872EB71284CFC700B4601E /* GSLinkedList.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSLinkedList.m; sourceTree = ""; };
85872EB81284CFC700B4601E /* GSSkipMutableArray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSSkipMutableArray.h; sourceTree = ""; };
85872EB91284CFC700B4601E /* GSSkipMutableArray.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSSkipMutableArray.m; sourceTree = ""; };
85872EBA1284CFC700B4601E /* GSThreadPool.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSThreadPool.h; sourceTree = ""; };
85872EBB1284CFC700B4601E /* GSThreadPool.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSThreadPool.m; sourceTree = ""; };
85872EBC1284CFC700B4601E /* GSThroughput.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSThroughput.h; sourceTree = ""; };
85872EBD1284CFC700B4601E /* GSThroughput.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSThroughput.m; sourceTree = ""; };
85872EBE1284CFC700B4601E /* GSTicker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GSTicker.h; sourceTree = ""; };
85872EBF1284CFC700B4601E /* GSTicker.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GSTicker.m; sourceTree = ""; };
85872EC01284CFC700B4601E /* Performance.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Performance.h; sourceTree = ""; };
8591FBED1A13422800923420 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = ""; };
85B560B3128C6E47003BAF08 /* Performance.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Performance.framework; sourceTree = BUILT_PRODUCTS_DIR; };
85B7DBDA1C034FBA00AF3090 /* NSObject+GSExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+GSExtensions.h"; sourceTree = ""; };
85B7DBDB1C034FBA00AF3090 /* NSObject+GSExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+GSExtensions.m"; sourceTree = ""; };
85B7DC011C036A0900AF3090 /* GSFIFO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GSFIFO.h; sourceTree = ""; };
85B7DC021C036A0900AF3090 /* GSFIFO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GSFIFO.m; sourceTree = ""; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; };
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DC2EF560486A6940098B216 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
85B560B3128C6E47003BAF08 /* Performance.framework */,
);
name = Products;
sourceTree = "";
};
0867D691FE84028FC02AAC07 /* Performance */ = {
isa = PBXGroup;
children = (
08FB77AEFE84172EC02AAC07 /* Classes */,
32C88DFF0371C24200C91783 /* Other Sources */,
089C1665FE841158C02AAC07 /* Resources */,
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
034768DFFF38A50411DB9C8B /* Products */,
);
name = Performance;
sourceTree = "";
};
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
);
name = "External Frameworks and Libraries";
sourceTree = "";
};
089C1665FE841158C02AAC07 /* Resources */ = {
isa = PBXGroup;
children = (
8591FBED1A13422800923420 /* ChangeLog */,
8DC2EF5A0486A6940098B216 /* Info.plist */,
089C1666FE841158C02AAC07 /* InfoPlist.strings */,
);
name = Resources;
sourceTree = "";
};
08FB77AEFE84172EC02AAC07 /* Classes */ = {
isa = PBXGroup;
children = (
85B7DC011C036A0900AF3090 /* GSFIFO.h */,
85B7DC021C036A0900AF3090 /* GSFIFO.m */,
85872EB01284CFC700B4601E /* GSCache.h */,
85872EB11284CFC700B4601E /* GSCache.m */,
85872EB21284CFC700B4601E /* GSIndexedSkipList.h */,
85872EB31284CFC700B4601E /* GSIndexedSkipList.m */,
85872EB41284CFC700B4601E /* GSIOThreadPool.h */,
85872EB51284CFC700B4601E /* GSIOThreadPool.m */,
85872EB61284CFC700B4601E /* GSLinkedList.h */,
85872EB71284CFC700B4601E /* GSLinkedList.m */,
85872EB81284CFC700B4601E /* GSSkipMutableArray.h */,
85872EB91284CFC700B4601E /* GSSkipMutableArray.m */,
85872EBA1284CFC700B4601E /* GSThreadPool.h */,
85872EBB1284CFC700B4601E /* GSThreadPool.m */,
85872EBC1284CFC700B4601E /* GSThroughput.h */,
85872EBD1284CFC700B4601E /* GSThroughput.m */,
85872EBE1284CFC700B4601E /* GSTicker.h */,
85872EBF1284CFC700B4601E /* GSTicker.m */,
85872EC01284CFC700B4601E /* Performance.h */,
85B7DBDA1C034FBA00AF3090 /* NSObject+GSExtensions.h */,
85B7DBDB1C034FBA00AF3090 /* NSObject+GSExtensions.m */,
);
name = Classes;
sourceTree = "";
};
1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
isa = PBXGroup;
children = (
1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
);
name = "Linked Frameworks";
sourceTree = "";
};
1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
isa = PBXGroup;
children = (
0867D6A5FE840307C02AAC07 /* AppKit.framework */,
D2F7E79907B2D74100F64583 /* CoreData.framework */,
0867D69BFE84028FC02AAC07 /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "";
};
32C88DFF0371C24200C91783 /* Other Sources */ = {
isa = PBXGroup;
children = (
);
name = "Other Sources";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8DC2EF500486A6940098B216 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
85872EC11284CFC700B4601E /* GSCache.h in Headers */,
85872EC31284CFC700B4601E /* GSIndexedSkipList.h in Headers */,
85872EC51284CFC700B4601E /* GSIOThreadPool.h in Headers */,
85872EC71284CFC700B4601E /* GSLinkedList.h in Headers */,
85872EC91284CFC700B4601E /* GSSkipMutableArray.h in Headers */,
85872ECB1284CFC700B4601E /* GSThreadPool.h in Headers */,
85872ECD1284CFC700B4601E /* GSThroughput.h in Headers */,
85872ECF1284CFC700B4601E /* GSTicker.h in Headers */,
85872ED11284CFC700B4601E /* Performance.h in Headers */,
85B7DBDC1C034FBA00AF3090 /* NSObject+GSExtensions.h in Headers */,
85B7DC031C036A0900AF3090 /* GSFIFO.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8DC2EF4F0486A6940098B216 /* Performance */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Performance" */;
buildPhases = (
8DC2EF500486A6940098B216 /* Headers */,
8DC2EF520486A6940098B216 /* Resources */,
8DC2EF540486A6940098B216 /* Sources */,
8DC2EF560486A6940098B216 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Performance;
productInstallPath = "$(HOME)/Library/Frameworks";
productName = Performance;
productReference = 85B560B3128C6E47003BAF08 /* Performance.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
ORGANIZATIONNAME = gnustep.org;
};
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Performance" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 0867D691FE84028FC02AAC07 /* Performance */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8DC2EF4F0486A6940098B216 /* Performance */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
8DC2EF520486A6940098B216 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8DC2EF540486A6940098B216 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
85872EC21284CFC700B4601E /* GSCache.m in Sources */,
85872EC41284CFC700B4601E /* GSIndexedSkipList.m in Sources */,
85872EC61284CFC700B4601E /* GSIOThreadPool.m in Sources */,
85872EC81284CFC700B4601E /* GSLinkedList.m in Sources */,
85872ECA1284CFC700B4601E /* GSSkipMutableArray.m in Sources */,
85872ECC1284CFC700B4601E /* GSThreadPool.m in Sources */,
85872ECE1284CFC700B4601E /* GSThroughput.m in Sources */,
85872ED01284CFC700B4601E /* GSTicker.m in Sources */,
85B7DBDD1C034FBA00AF3090 /* NSObject+GSExtensions.m in Sources */,
85B7DC041C036A0900AF3090 /* GSFIFO.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C1667FE841158C02AAC07 /* English */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
1DEB91AE08733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_VERSION = A;
GCC_CW_ASM_SYNTAX = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_CPP_EXCEPTIONS = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_ENABLE_EXCEPTIONS = YES;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_ENABLE_PASCAL_STRINGS = NO;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Frameworks";
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES;
PRODUCT_NAME = Performance;
WRAPPER_EXTENSION = framework;
ZERO_LINK = YES;
};
name = Debug;
};
1DEB91AF08733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_VERSION = A;
GCC_ENABLE_CPP_EXCEPTIONS = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_ENABLE_EXCEPTIONS = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Frameworks";
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
PRODUCT_NAME = Performance;
WRAPPER_EXTENSION = framework;
};
name = Release;
};
1DEB91B208733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES;
PRODUCT_NAME = Performance;
SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
SYMROOT = "$(PROJECT_DIR)/build";
};
name = Debug;
};
1DEB91B308733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
GCC_MODEL_TUNING = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES;
PRODUCT_NAME = Performance;
SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
SYMROOT = "$(PROJECT_DIR)/build";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Performance" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91AE08733DA50010E9CD /* Debug */,
1DEB91AF08733DA50010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Performance" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91B208733DA50010E9CD /* Debug */,
1DEB91B308733DA50010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
}