Merged in 'dawn' CVS branch

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3827 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-03-02 08:58:30 +00:00
parent 2c66a6581f
commit fc772ee2e5
26 changed files with 1090 additions and 607 deletions

View file

@ -1,7 +1,7 @@
Announcement Announcement
************ ************
The GNUstep Base Library, version 0.5.0, is now available. The GNUstep Base Library, version 0.5.5, is now available.
What is the GNUstep Base Library? What is the GNUstep Base Library?
================================= =================================
@ -14,8 +14,7 @@ network ports, remote object messaging support (distributed objects),
event loops, and random number generators. event loops, and random number generators.
It provides functionality that aims to implement the non-graphical It provides functionality that aims to implement the non-graphical
portion of the OpenStep standard. In many cases, the `NS*' classes are portion of the OpenStep standard (the Foundation library).
implemented as wrappers around more featureful GNU classes.
There is more information available at the GNUstep homepage at There is more information available at the GNUstep homepage at
`http://www.gnustep.org'. `http://www.gnustep.org'.
@ -23,8 +22,8 @@ implemented as wrappers around more featureful GNU classes.
Where can you get it? How can you compile it? Where can you get it? How can you compile it?
============================================== ==============================================
The gstepbase-0.5.0.tar.gz distribution file has been placed on The gstepbase-0.5.5.tar.gz distribution file has been placed on
`ftp.gnu.org' in `pub/gnu'. `ftp.gnu.org' in `pub/gnu/gstep'.
The library requires gcc 2.8.0 or higher. Significant sections of The library requires gcc 2.8.0 or higher. Significant sections of
the library do not work with the NeXT runtime, so we recommend using the library do not work with the NeXT runtime, so we recommend using

34
AUTHORS
View file

@ -12,7 +12,6 @@ BinaryTreeNode.m
CircularArray.m CircularArray.m
Collection.m Collection.m
ConnectedCoder.m ConnectedCoder.m
Connection.m
Coder.m Coder.m
CStream.m CStream.m
Decoder.m Decoder.m
@ -25,22 +24,16 @@ Invocation.m
KeyedCollection.m KeyedCollection.m
LinkedList.m LinkedList.m
LinkedListNode.m LinkedListNode.m
Lock.m
MachPort.m MachPort.m
Magnitude.m
MallocAddress.m
MappedCollector.m MappedCollector.m
MemoryStream.m MemoryStream.m
Notification.m
NotificationDispatcher.m NotificationDispatcher.m
OrderedCollection.m OrderedCollection.m
Port.m Port.m
Proxy.m
Queue.m Queue.m
RawCStream.m RawCStream.m
RBTree.m RBTree.m
RBTreeNode.m RBTreeNode.m
RNGAdditiveCongruential.m
Set.m Set.m
SplayTree.m SplayTree.m
Stack.m Stack.m
@ -48,34 +41,23 @@ StdioStream.m
Stream.m Stream.m
TcpPort.m TcpPort.m
TextCStream.m TextCStream.m
Time.m
UdpPort.m UdpPort.m
behavior.m behavior.m
preface.m preface.m
mframe.m mframe.m
HashTable.m
List.m
objc/HashTable.h
objc/List.h
NSAllocateObject.m
NSArchiver.m
NSArray.m NSArray.m
NSAutoreleasePool.m NSAutoreleasePool.m
NSCoder.m NSCoder.m
NSCopyObject.m NSCopyObject.m
NSCountedSet.m NSCountedSet.m
NSData.m NSData.m
NSDeallocateObject.m
NSDictionary.m NSDictionary.m
NSEnumerator.m NSEnumerator.m
NSGArchiver.m NSGArchiver.m
NSGArray.m NSGArray.m
NSGCountedSet.m
NSGCString.m NSGCString.m
NSGDictionary.m
NSGSet.m NSGSet.m
NSGString.m NSGString.m
NSInvocation.m
NSMethodSignature.m NSMethodSignature.m
NSNotification.m NSNotification.m
NSNotificationCenter.m NSNotificationCenter.m
@ -93,16 +75,10 @@ NSUser.m
Kresten Krab Thorup: Kresten Krab Thorup:
GapArray.m GapArray.m
objc-gnu2next.m objc-gnu2next.m
Storage.m
objc/Storage.h
Adam Fedor: Adam Fedor:
ostream.m ostream.m
NXStringTable.m
NXStringTable_scan.c
objc/NXStringTable.h
NXStringTable_scan.l
NSAssertionHandler.m NSAssertionHandler.m
NSBitmapCharSet.m NSBitmapCharSet.m
NSBundle.m NSBundle.m
@ -189,12 +165,17 @@ NSZone.m
Richard Frith-Macdonald: Richard Frith-Macdonald:
UnixFileHandle.m UnixFileHandle.m
NSData.m NSData.m
NSDateFormatter.m
NSDebug.m NSDebug.m
NSDistantObject.m NSDistantObject.m
NSDistributedLock.m NSDistributedLock.m
NSDistributedNotificationCenter.m
NSFileHandle.m NSFileHandle.m
NSFormatter.m
NSGDictionary.m
NSPipe.m NSPipe.m
NSPort.m NSPort.m
NSPortNameServer.m
NSProxy.m NSProxy.m
NSTask.m NSTask.m
NSUndoManager.m NSUndoManager.m
@ -209,3 +190,8 @@ NSGString.m
Mike Kienenberger: Mike Kienenberger:
NSProtocolChecker.m NSProtocolChecker.m
Manuel Guesdon:
NSURL.m
NSURLHandle.m

View file

@ -1,3 +1,42 @@
Tue Mar 2 08:04:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Merge in 'dawn' CVS branch.
1999-03-01 Adam Fedor <fedor@gnu.org>
* Update documentation.
1999-02-28 Adam Fedor <fedor@gnu.org>
* Source/Makefile.postamble: Don't install services if not
root. (patches submitted by Christopher Seawood
<cls@seawood.org>).
Tue Feb 23 12:03:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/include/NSObject.h: Fixed bugin in ASSIGNCOPY() macro and added
CREATE_AUTORELEASE_POOL() macro for libFoundation compatibility.
* Source/include/NSRunLoop.h: Added GCFinalization protocol.
* Source/NSRunLoop.m: Tidied a little, added GC macro use, fixed minor
bug, and added slight performance improvement.
Mon Feb 22 5:40:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Merged in alterations from main cvs branch made to wrong place 'cos
dawn branch was already created :-(
* Source/NSData.m: preserve file attributes when writing atomically
* Source/NSUser.m: Bugfixes for consistent naming of current user.
* Source/NSUserDefaults.m: Bugfixes so that running apps as root
doesn't mess up defaults database.
* Source/NSFileManager.m: Create files with correct ownership when
process is setuid to root - and provide facility for NSData to do same.
* Source/NSArray.m: Merged enumerator bugfix - missing @end
1999-02-22 Adam Fedor <fedor@gnu.org>
* Version: update version.
* Source/NSProcessInfo.m: Change missing main message.
Sun Feb 21 19:30:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk> Sun Feb 21 19:30:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSFileManager.m: Attempt to fix problems with directory * Source/NSFileManager.m: Attempt to fix problems with directory

View file

@ -35,9 +35,9 @@ DOCUMENT_NAME = gnustep-base
# The text documents to be generated # The text documents to be generated
DOCUMENT_TEXT_NAME = \ DOCUMENT_TEXT_NAME = \
TODO INSTALL NEWS CODING-STANDARDS README ANNOUNCE STATUS INSTALL NEWS CODING-STANDARDS README ANNOUNCE
TOP_DOC_FILES = TODO INSTALL NEWS README ANNOUNCE STATUS TOP_DOC_FILES = INSTALL NEWS README ANNOUNCE
gnustep-base_TEXI_FILES = \ gnustep-base_TEXI_FILES = \
version.tmpl.texi \ version.tmpl.texi \
@ -47,9 +47,7 @@ announce.tmpl.texi \
coding-standards.tmpl.texi \ coding-standards.tmpl.texi \
install.tmpl.texi \ install.tmpl.texi \
news.tmpl.texi \ news.tmpl.texi \
readme.tmpl.texi \ readme.tmpl.texi
status.tmpl.texi \
todo.tmpl.texi
TODO_TEXI_FILES = version.tmpl.texi TODO_TEXI_FILES = version.tmpl.texi
TODO_TEXT_MAIN = todo.tmpl.texi TODO_TEXT_MAIN = todo.tmpl.texi

View file

@ -6,5 +6,4 @@ remote object messaging support (distributed objects), event loops, and
random number generators. random number generators.
It provides functionality that aims to implement the non-graphical It provides functionality that aims to implement the non-graphical
portion of the OpenStep standard. In many cases, the @samp{NS*} classes portion of the OpenStep standard (the Foundation library).
are implemented as wrappers around more featureful GNU classes.

View file

@ -90,12 +90,6 @@ into another language, under the above conditions for modified versions.
@c News @c News
@include news.texi @include news.texi
@c Status Report
@include status.texi
@c The ToDo
@include todo.texi
@c Generate Short Contents @c Generate Short Contents
@shortcontents @shortcontents

View file

@ -7,6 +7,31 @@
The currently released version of the library is The currently released version of the library is
@samp{@value{GNUSTEP-BASE-VERSION}}. @samp{@value{GNUSTEP-BASE-VERSION}}.
@section Noteworthy changes in version @samp{0.5.5}
Too many changes to mention in detail, but here is a list of a few:
@itemize @bullet
@item
Many base classes have been rewritten with tonnes of performance
improvements that in many cases make it as fast as or faster than the
NeXT implementation.
@item
DO and archiving has received many improvements that help it work on a
variety of different platforms.
@item
Configuration and compilation has been greatly improved and fool
proofed.
@item
There are several new tools for handling services, defaults, and
pasteboards.
@end itemize
@section Noteworthy changes in version @samp{0.5.1} @section Noteworthy changes in version @samp{0.5.1}
@itemize @bullet @itemize @bullet

View file

@ -21,107 +21,13 @@ will be forthcoming, but the library needs to settle first. For now I
recommend reading the header files. recommend reading the header files.
The headers for the classes are in @file{./src/include}. The headers for the classes are in @file{./src/include}.
The FAQ contains an outline of the class heirarchy, as well as a
list of the differences between GNUstep and NeXT's implementation of
OpenStep, and GNUstep's improvements over NeXT's implementation.
@section Overview of the classes
Here is partial list of non-OpenStep classes, grouped by functionality.
There are several GNU-specific protocols also. You can recognize the
protocols by their name: they all end with ``ing''.
@itemize @bullet
@item The collection objects all conform to the @samp{Collecting}
protocol. Reading @samp{src/include/Collecting.h} is a good place to
start. Protocols for collections that store their contents with keys
and with indices can be found in @samp{src/incliude/KeyedCollecting.h} and
@samp{src/include/IndexedCollecting.h} respectively. Examples of generic
collections are @samp{Set} and @samp{Bag}. The keyed collections are
@samp{Dictionary} and @samp{MappedCollector}. The classes @samp{Array},
@samp{Queue}, @samp{GapArray}, @samp{LinkedList}, @samp{BinaryTree},
@samp{RBTree} and @samp{SplayTree} are all indexed collections.
@item The string objects conform to the @samp{String} protocol.
@samp{CString} provides an interface to strings based on ASCII bytes,
and is currently the only concrete subclass of String. The interface
between GNU @samp{String} and OpenStep's @samp{NSString} needs cleaning
up and will change. For now, I recommend using @samp{NSString}.
@item The public magnitude classes are @samp{Time} and @samp{Random}.
The @samp{Random} class works in conjunction with pseudo-random number
generators that conform to the @samp{RandomGenerating} protocol. The
conforming class @samp{RNGBerkeley} provides identical behavior to the
BSD random() function. The class @samp{RNGAdditiveCongruential} is an
implementation of the additive congruential method.
@item Stream objects provide a consistent interface for reading and
writing bytes. Read @samp{src/include/Stream.h} to get the general
idea. @samp{StdioStream} objects work with files, file descriptors,
FILE pointers and pipes to/from executables. @samp{MemoryStream}
objects work with memory buffers.
@item CStream objects provide a way to write C variables to Stream
objects. Read @file{src/include/CStream.h} to understand the interface
of the abstract superclass. @samp{TextCStream} writes C variables in a
human-readable ASCII format that can be manipulated with a text editor
or with your choice of text-processing programs, like @samp{awk} or
@samp{perl}. @samp{BinaryCStream} writes C variables in a compact,
illegible stream of bytes. @samp{TextCStream} and @samp{BinaryCStream}
each write in machine-independant formats---so you can write on one
machine architecture, and successfully read on another.
@samp{RawCStream} is like @samp{BinaryCStream} accept it is
machine-dependant; it useful for efficient Distributed Objects
connections on the same machine.
@item Coders provide a formatted way of writing Objective C objects to
CStream objects. After a coder is initialized with a stream, the coder
can encode/decode interconnected webs of Objective C objects and C types
and successfully keep track of complex interconnections between objects.
See @samp{src/include/Coder.h} for the abstract superclass interface;
see @samp{src/include/Coding.h} for the protocol adopted by objects that
read and write themselves using coders. @samp{Archiver} and
@samp{Unarchiver} are concrete subclasses that are used for
writing/reading with files.
@samp{Coder}s and @samp{CStream}s and @samp{Stream}s can be mixed and
matched so that programmers can choose the destination and the format
separately.
@ignore
@item @samp{Notification}
@samp{NotificationDispatcher}
@end ignore
@item The distributed object support classes are @samp{NSConnection},
@samp{NSProxy}, @samp{ConnectedCoder}, @samp{Port} and @samp{TcpPort}.
This version of the distributed objects only works with sockets. A Mach
port back-end should be on the way.
@end itemize
@section Test Programs
Some of the programs I've used to test the library are in
@samp{./checks}. Many of them are pretty messy, (desperately trying to
tickle that late night bug), but at least they show some code that works
when the library compiles correctly. I'm looking for a volunteer to
write some nicely organized test cases using @samp{dejagnu}. Any
takers?
@section How can you help? @section How can you help?
@itemize @bullet @itemize @bullet
@item Read the projects and questions in the @samp{TODO} file. If you
can volunteer for any of the projects, or if you have any useful
comments send me email!
@item @item
Give me feedback! Tell me what you like; tell me what you think Give us feedback! Tell us what you like; tell us what you think
could be better. Send me bug reports. could be better. Send bug reports to @email{bug-gnustep@@gnu.org}.
@item @item
Donate classes. If you write classes that fit in the libgnustep-base Donate classes. If you write classes that fit in the libgnustep-base
@ -131,9 +37,4 @@ framework, I'd be happy to include them.
@example @example
Happy hacking! Happy hacking!
Andrew McCallum
mccallum@@gnu.org
Adam Fedor
fedor@@gnu.org
@end example @end example

View file

@ -5,6 +5,10 @@
@include version.tmpl.texi @include version.tmpl.texi
@end ifset @end ifset
The gnustep-base library is nearly complete, although a few things could
be fixed here and there and it could be ported to more systems. This
list is probably out of date. In the future we will be primarily adding
features and performance tuning.
Please send corrections to @email{fedor@@gnu.org}. Please send corrections to @email{fedor@@gnu.org}.
@emph{Key:} @emph{Key:}
@ -31,80 +35,62 @@ Unknown status.
(Many classes do not raise the proper NSExceptions yet.) (Many classes do not raise the proper NSExceptions yet.)
@table @strong @table @strong
@item NSArchiver:: [8] @item NSArchiver:: [9]
Doesn't yet call -awakeAfterUsingCoder:.
@item NSArray:: [9] @item NSArray:: [9]
@item NSAssertionHandler:: [9] @item NSAssertionHandler:: [9]
@item NSAttributedString:: [8] @item NSAttributedString:: [9]
@item NSAutoreleasePool:: [9] @item NSAutoreleasePool:: [9]
But not exception- safe But not exception- safe
@item NSBundle:: [8] @item NSBundle:: [9]
@item NSCalendarDate:: [7] @item NSCalendarDate:: [8]
@item NSCharacterSet:: [8] @item NSCharacterSet:: [9]
decomposableCharacterSet and illegalCharacter set missing @item NSCoder:: [9]
@item NSCoder:: [8]
Missing class name substitution methods.
@item NSConditionLock:: [8] @item NSConditionLock:: [8]
@item NSConnection:: [7] @item NSConnection:: [9]
GNU Connection, however, needs: @item NSCountedSet:: [9]
@itemize @bullet @item NSData:: [9]
@item to handle retain/release/dealloc properly @item NSDate:: [9]
@item to be integrated with NSInvocation @item NSDeserializer:: [8]
@item to incorporate futzing with low-level TCP-backend for better speed @item NSDictionary:: [9]
@item to have UDP-backend work @item NSDistantObject:: [8]
@item to cache ConnectedCoder's for better speed @item NSDistributedLock:: [9]
@item Thread-safety overhaul, this is major
@end itemize
@item NSCountedSet:: [8]
@item NSData:: [8]
@item NSDate:: [8]
@item NSDeserializer:: [7]
@item NSDictionary:: [8]
@item NSDistantObject:: [7]
@item NSDistributedLock:: [7]
@item NSEnumerator:: [9] @item NSEnumerator:: [9]
@item NSException:: [9] @item NSException:: [9]
But this needs integration with new, better But this needs integration with new, better
@item NSFileHandle:: [9] @item NSFileHandle:: [9]
@item NSFileManager:: [9] @item NSFileManager:: [9]
@item NSHashTable:: [8] @item NSHashTable:: [9]
@item NSHost:: [8] @item NSHost:: [9]
@item NSInvocation:: [3] @item NSInvocation:: [7]
@item NSLock:: [8] @item NSLock:: [9]
@item NSMapTable:: [8] @item NSMapTable:: [9]
@item NSMethodSignature:: [4] @item NSMethodSignature:: [7]
@item NSMutableArray:: [8] @item NSMutableArray:: [9]
@item NSMutableCharacterSet:: [7] @item NSMutableCharacterSet:: [8]
@item NSMutableData:: [8] @item NSMutableData:: [9]
@item NSMutableDictionary:: [8] @item NSMutableDictionary:: [9]
@item NSMutableSet:: [8] @item NSMutableSet:: [9]
@item NSMutableString:: [8] @item NSMutableString:: [9]
@item NSNotification:: [9] @item NSNotification:: [9]
@item NSNotificationCenter:: [9] @item NSNotificationCenter:: [9]
@item NSNotificationQueue:: [6] @item NSNotificationQueue:: [6]
Needs integration with NSRunLoop, and efficiency improvements
@item NSNumber:: [9] @item NSNumber:: [9]
@item NSObject:: [10] @item NSObject:: [10]
@item NSProcessInfo:: [9] @item NSProcessInfo:: [9]
@item NSProxy:: [7] @item NSProxy:: [8]
@item NSRecursiveLock:: [8] @item NSRecursiveLock:: [9]
@item NSRunLoop:: [8] @item NSRunLoop:: [9]
NSTimer's not yet working, but everything else should be @item NSScanner:: [9]
@item NSScanner:: [8] @item NSSerializer:: [8]
@item NSSerializer:: [7] @item NSSet:: [9]
@item NSSet:: [8] @item NSString:: [9]
@item NSString:: [8]
Careful, relationship with GNU String is tricky; this could
also use fixing.
@item NSTask:: [8] @item NSTask:: [8]
@item NSThread:: [8] @item NSThread:: [8]
@item NSTimeZone:: [8] @item NSTimeZone:: [9]
@item NSTimeZoneDetail:: [8] @item NSTimeZoneDetail:: [9]
@item NSTimer:: [6] @item NSTimer:: [7]
Working out bugs with returning doubles. @item NSUnarchiver:: [9]
@item NSUnarchiver:: [8] @item NSUserDefaults:: [9]
See NSArchvier
@item NSUserDefaults:: [8]
@item NSValue:: [9] @item NSValue:: [9]
@end table @end table

View file

@ -10,161 +10,5 @@
@itemize @bullet @itemize @bullet
@item Implement Formatter classes (NSDateFormatter, etc) [5] (980722).
@item Implement NSDecimalNumber stuff [5] (981119).
@item Write tests for various classes using the testsuite built
by Richard Frith-Macdonald @email{richard@@brainstorm.co.uk}. Contact
him for details. [3, guile] (980629)
@item Check that every class implements coding (correctly). [2, NSCoder] (980721) - contribute to the testuite.
@item Check that every class implements copying (correctly) - i.e. non-mutable classes should just retain, etc. [1, NSCopying] (980721) - contribute to the testsuite.
@item Check that every class raises the NSExceptions it is supposed to.
Change many NSParameterAssert()'s into NSAssert()'s with
explanations. [2, exceptions] (970101) - contribute to the testsuite.
@item Improve initWithFormat related methods for NSString and find out how to implement the locale stuff [4 OPENSTEP/Rhapsody] (980712)
@item Make gstep-base 64bit clean [5, 64bit machine] (980629)
Donating internet access to a 64bit machine for someone else to do the
work on would also be helpful.
@item Make gstep-base smaller. Perhaps we can get rid of classes that
aren't strictly part of OpenStep and put them in an extensions-type
library. [5] (980629)
@item Fix NSLog so it conforms to specs. Need to check that write to
stderr went ok, and if not write to syslog. Also need to serialize
output (with threads). [3, OpenStep specs, threads] (980220)
@item Simplify NSException and NSAssertionHandler and make sure they
don't cause race conditions (if an exception is raised while processing
an exception. [4, exceptions, threads] (980220)
@item Fix all the places marked FIXME or xxx. [3-9] (980629)
@end itemize @end itemize
@ignore
@c ==================================================================
@section Questions
I would greatly appreciate your feedback on the questions
below. Please email your thoughts to mccallum@@gnu.ai.mit.edu.
@itemize @bullet
@item
I want to put method names in texinfo indices, but the colons in the
method names are interfering with info's notion of menu item names and
node names. Help. Any ideas? (Kresten?)
@item
HashTable.m (-initKeyDesc:valueDesc:capacity:) I tried to make it
portable, but I didn't try very hard. Anyone want to send in fixes?
@item
I fixed -emptyCopy in all the subclasses, but the -emptyCopy scheme
seems pretty fragile. How about calling -initFoo: inside -emptyCopy?
This way we avoid having yet another method in which instance vars
must be initialized to some consistent state. -allocCopy would never
even get called. <<ObjC insiders: This is a less well-expressed
version of what we've just been discussing in email.>>
@item
Does anyone really need the ability to set the collection element
comparison function independent of the -compare: method?
@item
How about adding flexibity in the method name that a LinkedList sends a
LinkedListNode to get/set the link ivars. This would enable us to add a
node to more than one linked list.
@item
Something like this needed?
- elementDidChange: (elt*)elementPtr;
Currently you have to remove, change, add, for some classes.
@end itemize
@section Albin's To Do List
I'm sure that there're other things to do, but these are the ones I know now:
@subsection General
@itemize @bullet
@item Make thread-safe all of my code that should be.
@item Fully annotate all of my headers.
@item Document my work and the use of its fruit.
@end itemize
@subsection Critical
@itemize @bullet
@item Code:
@itemize +
@item (@file{src/array.m}) @samp{objects_array_check}
@item (@file{src/array.m}) @samp{objects_array_map_elements}
@item (@file{src/cbs-char-p.m}) @samp{objects_char_p_describe}
@item (@file{src/cbs-int-p.m}) @samp{objects_int_p_describe}
@item (@file{src/cbs-int.m}) @samp{objects_int_describe}
@item (@file{src/hash.m}) @samp{_objects_hash_hash}
@item (@file{src/hash.m}) @samp{objects_hash_check}
@item (@file{src/hash.m}) @samp{objects_hash_description}
@item (@file{src/list.m}) @samp{objects_list_is_equal_to_list}
@item (@file{src/map.m}) @samp{_objects_map_hash}
@item (@file{src/map.m}) @samp{objects_map_check}
@item (@file{src/map.m}) @samp{objects_map_description}
@end itemize
@item Correct:
@itemize +
@item (@file{src/array.m}) @samp{objects_array_dealloc}
@item (@file{src/cbs-int.m}) @samp{_GNUSTEP_BASE_NOT_AN_INT_MARKER}
@end itemize
@item Improve the error handling of:
@itemize +
@item (@file{src/array.m}) @samp{_objects_array_insert_bucket}
@item (@file{src/hash.m}) @samp{objects_hash_add_element_known_absent}
@item (@file{src/list.m}) @samp{objects_list_at_index_insert_element}
@item (@file{src/map.m}) @samp{objects_map_at_key_put_value_known_absent}
@end itemize
@end itemize
@subsection Not So Critical
@itemize @bullet
@item Strengthen my resolve on the correctness of:
@itemize +
@item (@file{src/cbs-char-p.m}) @samp{_GNUSTEP_BASE_NOT_A_CHAR_P_MARKER}
@item (@file{src/cbs-id.m}) @samp{_GNUSTEP_BASE_NOT_AN_ID_MARKER}
@item (@file{src/cbs-int-p.m}) @samp{_GNUSTEP_BASE_NOT_AN_INT_P_MARKER}
@item (@file{src/cbs-int-p.m}) @samp{objects_int_p_is_equal}
@item (@file{src/cbs-void-p.m}) @samp{_GNUSTEP_BASE_NOT_A_VOID_P_MARKER}
@item (@file{src/hash.m}) @samp{objects_hash_rightsize}
@item (@file{src/hash.m}) @samp{objects_hash_all_elements}
@item (@file{src/map.m}) @samp{objects_map_rightsize}
@item (@file{src/map.m}) @samp{objects_map_all_keys}
@item (@file{src/map.m}) @samp{objects_map_all_values}
@end itemize
@item Improve the efficiency of:
@itemize +
@item (@file{src/array.m}) @samp{_objects_array_insert_bucket}
@item (@file{src/hash.m}) @samp{objects_hash_minus_hash}
@item (@file{src/list.m}) @samp{objects_list_at_index_insert_list}
@end itemize
@end itemize
@end ignore

View file

@ -231,8 +231,11 @@ extern NSRecursiveLock *gnustep_global_lock;
#define AUTORELEASE(object) ((id)object) #define AUTORELEASE(object) ((id)object)
#define ASSIGN(object,value) (object = value) #define ASSIGN(object,value) (object = value)
#define ASSIGNCOPY(object,value) (object = [value copy])
#define DESTROY(object) (object = nil) #define DESTROY(object) (object = nil)
#define CREATE_AUTORELEASE_POOL(X)
#else #else
#define RETAIN(object) [object retain] #define RETAIN(object) [object retain]
@ -269,7 +272,7 @@ if (__value != object) \
{ \ { \
if (__value) \ if (__value) \
{ \ { \
[__value copy]; \ __value = [__value copy]; \
} \ } \
if (object) \ if (object) \
{ \ { \
@ -285,6 +288,10 @@ if (__value != object) \
* object later. * object later.
*/ */
#define DESTROY(object) ([object release], object = nil) #define DESTROY(object) ([object release], object = nil)
#define CREATE_AUTORELEASE_POOL(X) \
NSAutoreleasePool *(X) = [NSAutoreleasePool new]
#endif #endif
#endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */ #endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */

View file

@ -26,7 +26,11 @@
#include <Foundation/NSObject.h> #include <Foundation/NSObject.h>
@class NSMutableSet; @class NSArray;
@class NSConnection;
@class NSDate;
@class NSRunLoop;
@class NSString;
extern NSString *NSPortTimeoutException; /* OPENSTEP */ extern NSString *NSPortTimeoutException; /* OPENSTEP */
@ -39,16 +43,29 @@ extern NSString *NSPortTimeoutException; /* OPENSTEP */
+ (NSPort*) port; + (NSPort*) port;
+ (NSPort*) portWithMachPort: (int)machPort; + (NSPort*) portWithMachPort: (int)machPort;
- delegate; - (id) delegate;
- init; - (id) init;
- initWithMachPort: (int)machPort; - (id) initWithMachPort: (int)machPort;
- (void) invalidate; - (void) invalidate;
- (BOOL) isValid; - (BOOL) isValid;
- machPort; - (int) machPort;
- (void) setDelegate: anObject; - (void) setDelegate: (id)anObject;
#ifndef STRICT_OPENSTEP
- (void) addConnection: (NSConnection*)aConnection
toRunLoop: (NSRunLoop*)aLoop
forMode: (NSString*)aMode;
- (void) removeConnection: (NSConnection*)aConnection
fromRunLoop: (NSRunLoop*)aLoop
forMode: (NSString*)aMode;
- (unsigned) reservedSpaceLength;
- (void) sendBeforeDate: (NSDate*)when
components: (NSArray*)components
from: (NSPort*)receivingPort
reserved: (unsigned) length;
#endif
@end @end
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP

View file

@ -42,6 +42,10 @@
- (NSPort*) receivePort; - (NSPort*) receivePort;
- (void) setMsgid: (unsigned)anId; - (void) setMsgid: (unsigned)anId;
- (unsigned) msgid; - (unsigned) msgid;
#ifndef NO_GNUSTEP
- (void) addComponent: (id)aComponent;
#endif
@end @end
#endif #endif

View file

@ -32,7 +32,7 @@
/* Mode strings. */ /* Mode strings. */
extern id NSDefaultRunLoopMode; extern id NSDefaultRunLoopMode;
@interface NSRunLoop : NSObject @interface NSRunLoop : NSObject <GCFinalization>
{ {
@private id _current_mode; @private id _current_mode;
@private NSMapTable *_mode_2_timers; @private NSMapTable *_mode_2_timers;

View file

@ -74,7 +74,6 @@ after-distclean::
configure: configure.in configure: configure.in
autoconf autoconf
autoheader
# Regenerate automatically generated files # Regenerate automatically generated files
regenerate: stamp-regenerate regenerate: stamp-regenerate
@ -84,36 +83,3 @@ stamp-regenerate: ChangeLog configure
(cd $$i; $(MAKE) $(MAKEDEFINES) regenerate); \ (cd $$i; $(MAKE) $(MAKEDEFINES) regenerate); \
done done
touch stamp-regenerate touch stamp-regenerate
snapshot:
@echo Making $(PACKAGE_NAME) snapshot
cvs export -r snapshot-`date +%y%m%d` $(PACKAGE_NAME)
rm -f .name
echo $(PACKAGE_NAME)-`date +%y%m%d` >.name
rm -rf `cat .name`
mv $(PACKAGE_NAME) `cat .name`
tar -chvf `cat .name`.tar `cat .name`
rm -f `cat .name`.tar.gz
gzip -9 `cat .name`.tar
rm -rf `cat .name`
dist:
@echo Making $(PACKAGE_NAME) release $(VERSION)
cvs export -r release-`echo $(VERSION) | tr . -` $(PACKAGE_NAME)
mv $(PACKAGE_NAME) $(PACKAGE_NAME)-$(VERSION)
tar -chvf $(PACKAGE_NAME)-$(VERSION).tar \
$(PACKAGE_NAME)-$(VERSION)
rm -f $(PACKAGE_NAME)-$(VERSION).tar.gz
gzip -9 $(PACKAGE_NAME)-$(VERSION).tar
rm -rf $(PACKAGE_NAME)-$(VERSION)
snapshot-rtag:
@echo Tagging current base HEAD for snapshot `date +%y%m%d`
cvs rtag snapshot-`date +%y%m%d` $(PACKAGE_NAME)
dist-rtag:
@echo Tagging current base HEAD for release $(VERSION)
cvs rtag release-`echo $(VERSION) | tr . -` $(PACKAGE_NAME)
rdiff:
cvs rdiff -u -r $(OLD) $(PACKAGE_NAME)

20
NEWS
View file

@ -1,7 +1,25 @@
News News
**** ****
The currently released version of the library is `0.5.0'. The currently released version of the library is `0.5.5'.
Noteworthy changes in version `0.5.5'
=====================================
Too many changes to mention in detail, but here is a list of a few:
* Many base classes have been rewritten with tonnes of performance
improvements that in many cases make it as fast as or faster than
the NeXT implementation.
* DO and archiving has received many improvements that help it work
on a variety of different platforms.
* Configuration and compilation has been greatly improved and fool
proofed.
* There are several new tools for handling services, defaults, and
pasteboards.
Noteworthy changes in version `0.5.1' Noteworthy changes in version `0.5.1'
===================================== =====================================

99
README
View file

@ -9,8 +9,7 @@ remote object messaging support (distributed objects), event loops, and
random number generators. random number generators.
It provides functionality that aims to implement the non-graphical It provides functionality that aims to implement the non-graphical
portion of the OpenStep standard. In many cases, the `NS*' classes are portion of the OpenStep standard (the Foundation library).
implemented as wrappers around more featureful GNU classes.
Here is some introductory info to get you started: Here is some introductory info to get you started:
@ -30,106 +29,14 @@ documentation will be forthcoming, but the library needs to settle
first. For now I recommend reading the header files. The headers for first. For now I recommend reading the header files. The headers for
the classes are in `./src/include'. the classes are in `./src/include'.
The FAQ contains an outline of the class heirarchy, as well as a
list of the differences between GNUstep and NeXT's implementation of
OpenStep, and GNUstep's improvements over NeXT's implementation.
Overview of the classes
=======================
Here is partial list of non-OpenStep classes, grouped by
functionality.
There are several GNU-specific protocols also. You can recognize the
protocols by their name: they all end with "ing".
* The collection objects all conform to the `Collecting' protocol.
Reading `src/include/Collecting.h' is a good place to start.
Protocols for collections that store their contents with keys and
with indices can be found in `src/incliude/KeyedCollecting.h' and
`src/include/IndexedCollecting.h' respectively. Examples of
generic collections are `Set' and `Bag'. The keyed collections are
`Dictionary' and `MappedCollector'. The classes `Array', `Queue',
`GapArray', `LinkedList', `BinaryTree', `RBTree' and `SplayTree'
are all indexed collections.
* The string objects conform to the `String' protocol. `CString'
provides an interface to strings based on ASCII bytes, and is
currently the only concrete subclass of String. The interface
between GNU `String' and OpenStep's `NSString' needs cleaning up
and will change. For now, I recommend using `NSString'.
* The public magnitude classes are `Time' and `Random'. The
`Random' class works in conjunction with pseudo-random number
generators that conform to the `RandomGenerating' protocol. The
conforming class `RNGBerkeley' provides identical behavior to the
BSD random() function. The class `RNGAdditiveCongruential' is an
implementation of the additive congruential method.
* Stream objects provide a consistent interface for reading and
writing bytes. Read `src/include/Stream.h' to get the general
idea. `StdioStream' objects work with files, file descriptors,
FILE pointers and pipes to/from executables. `MemoryStream'
objects work with memory buffers.
* CStream objects provide a way to write C variables to Stream
objects. Read `src/include/CStream.h' to understand the interface
of the abstract superclass. `TextCStream' writes C variables in a
human-readable ASCII format that can be manipulated with a text
editor or with your choice of text-processing programs, like `awk'
or `perl'. `BinaryCStream' writes C variables in a compact,
illegible stream of bytes. `TextCStream' and `BinaryCStream' each
write in machine-independant formats--so you can write on one
machine architecture, and successfully read on another.
`RawCStream' is like `BinaryCStream' accept it is
machine-dependant; it useful for efficient Distributed Objects
connections on the same machine.
* Coders provide a formatted way of writing Objective C objects to
CStream objects. After a coder is initialized with a stream, the
coder can encode/decode interconnected webs of Objective C objects
and C types and successfully keep track of complex
interconnections between objects. See `src/include/Coder.h' for
the abstract superclass interface; see `src/include/Coding.h' for
the protocol adopted by objects that read and write themselves
using coders. `Archiver' and `Unarchiver' are concrete subclasses
that are used for writing/reading with files.
`Coder's and `CStream's and `Stream's can be mixed and matched so
that programmers can choose the destination and the format
separately.
* The distributed object support classes are `NSConnection',
`NSProxy', `ConnectedCoder', `Port' and `TcpPort'. This version
of the distributed objects only works with sockets. A Mach port
back-end should be on the way.
Test Programs
=============
Some of the programs I've used to test the library are in
`./checks'. Many of them are pretty messy, (desperately trying to
tickle that late night bug), but at least they show some code that works
when the library compiles correctly. I'm looking for a volunteer to
write some nicely organized test cases using `dejagnu'. Any takers?
How can you help? How can you help?
================= =================
* Read the projects and questions in the `TODO' file. If you can * Give us feedback! Tell us what you like; tell us what you think
volunteer for any of the projects, or if you have any useful could be better. Send bug reports to <bug-gnustep@gnu.org>.
comments send me email!
* Give me feedback! Tell me what you like; tell me what you think
could be better. Send me bug reports.
* Donate classes. If you write classes that fit in the * Donate classes. If you write classes that fit in the
libgnustep-base framework, I'd be happy to include them. libgnustep-base framework, I'd be happy to include them.
Happy hacking! Happy hacking!
Andrew McCallum
mccallum@gnu.org
Adam Fedor
fedor@gnu.org

View file

@ -58,19 +58,22 @@ after-install::
$(INSTALL_DATA) $(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/mframe.h \ $(INSTALL_DATA) $(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/mframe.h \
$(GNUSTEP_HEADERS)/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS) $(GNUSTEP_HEADERS)/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)
if [ "$(INSTALL_ROOT_DIR)" = "" ]; then \ if [ "$(INSTALL_ROOT_DIR)" = "" ]; then \
if [ "`whoami`" != root ]; then \
echo "WARNING: Please add the following lines yourself"; \
fi; \
services=/etc/services; \ services=/etc/services; \
else \ else \
mkdir -p $(INSTALL_ROOT_DIR)/etc; \ mkdir -p $(INSTALL_ROOT_DIR)/etc; \
services=$(INSTALL_ROOT_DIR)/etc/services.add; \ services=$(INSTALL_ROOT_DIR)/etc/services.add; \
echo "GNUstep addons for /etc/services written to $$services"; \
fi; \ fi; \
if [ "`whoami`" != root ]; then \
echo "WARNING: Please add the following lines to $$services"; \
echo "gdomap 538/tcp # GNUstep distrib objects"; \
echo "gdomap 538/udp # GNUstep distrib objects"; \
else \
if [ "`fgrep gdomap $$services 2>/dev/null`" = "" ]; then \ if [ "`fgrep gdomap $$services 2>/dev/null`" = "" ]; then \
echo "GNUstep addons for /etc/services written to $$services"; \
set -x; \ set -x; \
echo "gdomap 538/tcp # GNUstep distrib objects" >> $$services; \ echo "gdomap 538/tcp # GNUstep distrib objects" >> $$services; \
echo "gdomap 538/udp # GNUstep distrib objects" >> $$services; \ echo "gdomap 538/udp # GNUstep distrib objects" >> $$services; \
fi; \
fi fi
# Things to do before uninstalling # Things to do before uninstalling

View file

@ -47,6 +47,8 @@
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSLock.h> #include <Foundation/NSLock.h>
#include <Foundation/NSThread.h> #include <Foundation/NSThread.h>
#include <Foundation/NSPort.h>
#include <Foundation/NSPortMessage.h>
#include <Foundation/NSNotification.h> #include <Foundation/NSNotification.h>
NSString* NSConnectionReplyMode = @"NSConnectionReplyMode"; NSString* NSConnectionReplyMode = @"NSConnectionReplyMode";
@ -184,6 +186,7 @@ static unsigned local_object_counter = 0;
@interface NSConnection (Private) @interface NSConnection (Private)
- _superInit; - _superInit;
- (void) handlePortMessage: (NSPortMessage*)msg;
+ setDebug: (int)val; + setDebug: (int)val;
@end @end
@ -411,6 +414,11 @@ static int messages_received_count;
return delegate; return delegate;
} }
- (void) handlePortMessage: (NSPortMessage*)msg
{
[self notImplemented: _cmd];
}
- (BOOL) independantConversationQueueing - (BOOL) independantConversationQueueing
{ {
return independant_queueing; return independant_queueing;

View file

@ -22,6 +22,7 @@
*/ */
#include <config.h> #include <config.h>
#include <Foundation/NSException.h>
#include <Foundation/NSString.h> #include <Foundation/NSString.h>
#include <Foundation/NSNotificationQueue.h> #include <Foundation/NSNotificationQueue.h>
#include <Foundation/NSPort.h> #include <Foundation/NSPort.h>
@ -38,17 +39,17 @@ NSString *NSPortTimeoutException
+ (NSPort*) port + (NSPort*) port
{ {
return [[[NSPort alloc] init] autorelease]; return AUTORELEASE([NSPort new]);
} }
+ (NSPort*) portWithMachPort: (int)machPort + (NSPort*) portWithMachPort: (int)machPort
{ {
return [[[NSPort alloc] initWithMachPort: machPort] autorelease]; return AUTORELEASE([[NSPort alloc] initWithMachPort: machPort]);
} }
- (id) copyWithZone: (NSZone*)aZone - (id) copyWithZone: (NSZone*)aZone
{ {
return [self retain]; return RETAIN(self);
} }
- (id) delegate - (id) delegate
@ -75,7 +76,7 @@ NSString *NSPortTimeoutException
- (id) initWithMachPort: (int)machPort - (id) initWithMachPort: (int)machPort
{ {
[self notImplemented: _cmd]; [self shouldNotImplement: _cmd];
return nil; return nil;
} }
@ -96,10 +97,10 @@ NSString *NSPortTimeoutException
return is_valid; return is_valid;
} }
- (id) machPort - (int) machPort
{ {
[self notImplemented: _cmd]; [self shouldNotImplement: _cmd];
return nil; return 0;
} }
- (void) release - (void) release
@ -126,8 +127,38 @@ NSString *NSPortTimeoutException
- (void) setDelegate: anObject - (void) setDelegate: anObject
{ {
NSAssert([anObject respondsToSelector: @selector(handlePortMessage:)],
NSInvalidArgumentException);
delegate = anObject; delegate = anObject;
} }
- (void) addConnection: (NSConnection*)aConnection
toRunLoop: (NSRunLoop*)aLoop
forMode: (NSString*)aMode
{
[self subclassResponsibility: _cmd];
}
- (void) removeConnection: (NSConnection*)aConnection
fromRunLoop: (NSRunLoop*)aLoop
forMode: (NSString*)aMode
{
[self subclassResponsibility: _cmd];
}
- (unsigned) reservedSpaceLength
{
[self subclassResponsibility: _cmd];
return 0;
}
- (void) sendBeforeDate: (NSDate*)when
components: (NSArray*)components
from: (NSPort*)receivingPort
reserved: (unsigned) length
{
[self subclassResponsibility: _cmd];
}
@end @end

View file

@ -32,20 +32,20 @@
- (void) dealloc - (void) dealloc
{ {
[components release]; RELEASE(components);
[super dealloc]; [super dealloc];
} }
/* PortMessages MUST be initialised with ports and data. */ /* PortMessages MUST be initialised with ports and data. */
- (id) init - (id) init
{ {
[self notImplemented: _cmd]; [self shouldNotImplement: _cmd];
return nil; return nil;
} }
- (id) initWithMachMessage: (void*)buffer - (id) initWithMachMessage: (void*)buffer
{ {
[self notImplemented: _cmd]; [self shouldNotImplement: _cmd];
return nil; return nil;
} }
@ -55,7 +55,8 @@
components: (NSArray*)items components: (NSArray*)items
{ {
self = [super init]; self = [super init];
if (self) { if (self)
{
components = [[NSMutableArray allocWithZone: [self zone]] components = [[NSMutableArray allocWithZone: [self zone]]
initWithCapacity: [items count] + 2]; initWithCapacity: [items count] + 2];
[components addObject: aPort]; [components addObject: aPort];
@ -65,9 +66,12 @@
return self; return self;
} }
- (void) sendBeforeDate: (NSDate*)when - (void) addComponent: (id)aComponent
{ {
[self notImplemented: _cmd]; NSAssert([aComponent isKindOfClass: [NSData class]]
|| [aComponent isKindOfClass: [NSPort class]],
NSInvalidArgumentException);
[components addObject: aComponent];
} }
- (NSArray*) components - (NSArray*) components
@ -77,9 +81,9 @@
return [components subarrayWithRange: r]; return [components subarrayWithRange: r];
} }
- (NSPort*) sendPort - (unsigned) msgid
{ {
return [components objectAtIndex: 0]; return msgid;
} }
- (NSPort*) receivePort - (NSPort*) receivePort
@ -87,14 +91,24 @@
return [components objectAtIndex: 1]; return [components objectAtIndex: 1];
} }
- (void) sendBeforeDate: (NSDate*)when
{
NSPort *port = [self sendPort];
[port sendBeforeDate: when
components: [self components]
from: [self receivePort]
reserved: [port reservedSpaceLength]];
}
- (NSPort*) sendPort
{
return [components objectAtIndex: 0];
}
- (void) setMsgid: (unsigned)anId - (void) setMsgid: (unsigned)anId
{ {
msgid = anId; msgid = anId;
} }
- (unsigned) msgid
{
return msgid;
}
@end @end

View file

@ -74,12 +74,11 @@
/* This error message should be called only if the private main function /* This error message should be called only if the private main function
* was not executed successfully. This may heppen ONLY if onother library * was not executed successfully. This may heppen ONLY if onother library
* or kit defines its own main function (as libobjects does). * or kit defines its own main function (as gnustep-base does).
*/ */
#define _GNU_MISSING_MAIN_FUNCTION_CALL @"Libobjects internal error: \ #define _GNU_MISSING_MAIN_FUNCTION_CALL @"GNUSTEP Internal Error: \
the private libobjects function to establish the argv and environment \ The private GNUstep function to establish the argv and environment \
variables was not called. Please contact Tuparev@EMBL-Heidelberg.de for \ variables was not called. Please report this error to bug-gnustep@gnu.org."
further information."
/************************************************************************* /*************************************************************************
*** _NSConcreteProcessInfo *** _NSConcreteProcessInfo

View file

@ -107,10 +107,11 @@ static int debug_run_loop = 0;
* NB. This class is private to NSRunLoop and must not be subclassed. * NB. This class is private to NSRunLoop and must not be subclassed.
*/ */
@interface RunLoopWatcher: NSObject @interface RunLoopWatcher: NSObject <GCFinalization>
{ {
@public @public
BOOL invalidated; BOOL invalidated;
BOOL handleEvent; // New-style event handling
void *data; void *data;
id receiver; id receiver;
RunLoopEventType type; RunLoopEventType type;
@ -130,9 +131,9 @@ static int debug_run_loop = 0;
- (void) dealloc - (void) dealloc
{ {
[self invalidate]; [self gcFinalize];
[limit release]; RELEASE(limit);
[receiver release]; RELEASE(receiver);
[super dealloc]; [super dealloc];
} }
@ -144,8 +145,7 @@ static int debug_run_loop = 0;
return; return;
} }
if ([receiver respondsToSelector: if (handleEvent)
@selector(receivedEvent:type:extra:forMode:)])
{ {
[receiver receivedEvent: data type: type extra: info forMode: mode]; [receiver receivedEvent: data type: type extra: info forMode: mode];
} }
@ -155,21 +155,27 @@ static int debug_run_loop = 0;
{ {
case ET_RDESC: case ET_RDESC:
case ET_RPORT: case ET_RPORT:
[receiver readyForReadingOnFileDescriptor: (int)info]; [receiver readyForReadingOnFileDescriptor: (int)(gsaddr)info];
break; break;
case ET_WDESC: case ET_WDESC:
[receiver readyForWritingOnFileDescriptor: (int)info]; [receiver readyForWritingOnFileDescriptor: (int)(gsaddr)info];
break; break;
} }
} }
} }
- initWithType: (RunLoopEventType)aType - (void) gcFinalize
{
[self invalidate];
}
- (id) initWithType: (RunLoopEventType)aType
receiver: (id)anObj receiver: (id)anObj
data: (void*)item data: (void*)item
{ {
invalidated = NO; invalidated = NO;
switch (aType) switch (aType)
{ {
case ET_RDESC: type = aType; break; case ET_RDESC: type = aType; break;
@ -179,7 +185,12 @@ static int debug_run_loop = 0;
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"NSRunLoop - unknown event type"]; format: @"NSRunLoop - unknown event type"];
} }
receiver = [anObj retain]; receiver = RETAIN(anObj);
if ([receiver respondsToSelector:
@selector(receivedEvent:type:extra:forMode:)])
handleEvent = YES;
else
handleEvent = NO;
data = item; data = item;
return self; return self;
} }
@ -224,7 +235,7 @@ static int debug_run_loop = 0;
* messages which are due to be sent to objects once a particular * messages which are due to be sent to objects once a particular
* runloop iteration has passed. * runloop iteration has passed.
*/ */
@interface RunLoopPerformer: NSObject @interface RunLoopPerformer: NSObject <GCFinalization>
{ {
SEL selector; SEL selector;
id target; id target;
@ -252,10 +263,10 @@ static int debug_run_loop = 0;
- (void) dealloc - (void) dealloc
{ {
[timer invalidate]; [self gcFinalize];
[target release]; RELEASE(target);
[argument release]; RELEASE(argument);
[modes release]; RELEASE(modes);
[super dealloc]; [super dealloc];
} }
@ -264,13 +275,18 @@ static int debug_run_loop = 0;
if (timer != nil) if (timer != nil)
{ {
timer = nil; timer = nil;
[[self retain] autorelease]; AUTORELEASE(RETAIN(self));
[[[NSRunLoop currentInstance] _timedPerformers] [[[NSRunLoop currentInstance] _timedPerformers]
removeObjectIdenticalTo: self]; removeObjectIdenticalTo: self];
} }
[target performSelector: selector withObject: argument]; [target performSelector: selector withObject: argument];
} }
- (void) gcFinalize
{
[timer invalidate];
}
- initWithSelector: (SEL)aSelector - initWithSelector: (SEL)aSelector
target: (id)aTarget target: (id)aTarget
argument: (id)anArgument argument: (id)anArgument
@ -281,8 +297,8 @@ static int debug_run_loop = 0;
if (self) if (self)
{ {
selector = aSelector; selector = aSelector;
target = [aTarget retain]; target = RETAIN(aTarget);
argument = [anArgument retain]; argument = RETAIN(anArgument);
order = theOrder; order = theOrder;
modes = [theModes copy]; modes = [theModes copy];
} }
@ -331,8 +347,8 @@ static int debug_run_loop = 0;
NSMutableArray *array; NSMutableArray *array;
int i; int i;
[target retain]; RETAIN(target);
[arg retain]; RETAIN(arg);
array = [[NSRunLoop currentInstance] _timedPerformers]; array = [[NSRunLoop currentInstance] _timedPerformers];
for (i = [array count]; i > 0; i--) for (i = [array count]; i > 0; i--)
{ {
@ -343,8 +359,8 @@ static int debug_run_loop = 0;
[array removeObjectAtIndex: i-1]; [array removeObjectAtIndex: i-1];
} }
} }
[arg release]; RELEASE(arg);
[target release]; RELEASE(target);
} }
- (void) performSelector: (SEL)aSelector - (void) performSelector: (SEL)aSelector
@ -366,7 +382,7 @@ static int debug_run_loop = 0;
selector: @selector(fire) selector: @selector(fire)
userInfo: nil userInfo: nil
repeats: NO]]; repeats: NO]];
[item release]; RELEASE(item);
} }
- (void) performSelector: (SEL)aSelector - (void) performSelector: (SEL)aSelector
@ -398,7 +414,7 @@ static int debug_run_loop = 0;
userInfo: nil userInfo: nil
repeats: NO]; repeats: NO];
[item setTimer: timer]; [item setTimer: timer];
[item release]; RELEASE(item);
for (i = 0; i < [modes count]; i++) for (i = 0; i < [modes count]; i++)
{ {
[loop addTimer: timer forMode: [modes objectAtIndex: i]]; [loop addTimer: timer forMode: [modes objectAtIndex: i]];
@ -438,8 +454,8 @@ static int debug_run_loop = 0;
if (watchers == nil) if (watchers == nil)
{ {
watchers = [NSMutableArray new]; watchers = [NSMutableArray new];
NSMapInsert (_mode_2_watchers, mode, watchers); NSMapInsert(_mode_2_watchers, mode, watchers);
[watchers release]; RELEASE(watchers);
count = 0; count = 0;
} }
else else
@ -592,7 +608,7 @@ static int debug_run_loop = 0;
data: data]; data: data];
/* Add the object to the array for the mode. */ /* Add the object to the array for the mode. */
[self _addWatcher:info forMode:mode]; [self _addWatcher:info forMode:mode];
[info release]; /* Now held in array. */ RELEASE(info); /* Now held in array. */
} }
} }
@ -683,11 +699,12 @@ static int debug_run_loop = 0;
/* Positive values are in the future. */ /* Positive values are in the future. */
while (ti > 0 && mayDoMore == YES) while (ti > 0 && mayDoMore == YES)
{ {
id arp = [NSAutoreleasePool new]; CREATE_AUTORELEASE_POOL(arp);
if (debug_run_loop) if (debug_run_loop)
printf ("\tNSRunLoop run until date %f seconds from now\n", ti); printf ("\tNSRunLoop run until date %f seconds from now\n", ti);
mayDoMore = [self runMode: mode beforeDate: date]; mayDoMore = [self runMode: mode beforeDate: date];
[arp release]; RELEASE(arp);
ti = [date timeIntervalSinceNow]; ti = [date timeIntervalSinceNow];
} }
} }
@ -698,7 +715,7 @@ static int debug_run_loop = 0;
@implementation NSRunLoop @implementation NSRunLoop
+ currentRunLoop + (NSRunLoop*) currentRunLoop
{ {
static NSString *key = @"NSRunLoopThreadKey"; static NSString *key = @"NSRunLoopThreadKey";
NSRunLoop* r; NSRunLoop* r;
@ -710,7 +727,7 @@ static int debug_run_loop = 0;
{ {
r = [NSRunLoop new]; r = [NSRunLoop new];
[[t threadDictionary] setObject: r forKey: key]; [[t threadDictionary] setObject: r forKey: key];
[r release]; RELEASE(r);
} }
return r; return r;
} }
@ -722,7 +739,7 @@ static int debug_run_loop = 0;
} }
/* This is the designated initializer. */ /* This is the designated initializer. */
- init - (id) init
{ {
[super init]; [super init];
_current_mode = NSDefaultRunLoopMode; _current_mode = NSDefaultRunLoopMode;
@ -736,12 +753,17 @@ static int debug_run_loop = 0;
} }
- (void) dealloc - (void) dealloc
{
[self gcFinalize];
RELEASE(_performers);
RELEASE(_timedPerformers);
[super dealloc];
}
- (void) gcFinalize
{ {
NSFreeMapTable(_mode_2_timers); NSFreeMapTable(_mode_2_timers);
NSFreeMapTable(_mode_2_watchers); NSFreeMapTable(_mode_2_watchers);
[_performers release];
[_timedPerformers release];
[super dealloc];
} }
- (NSString*) currentMode - (NSString*) currentMode
@ -762,7 +784,7 @@ static int debug_run_loop = 0;
{ {
timers = [Heap new]; timers = [Heap new];
NSMapInsert (_mode_2_timers, mode, timers); NSMapInsert (_mode_2_timers, mode, timers);
[timers release]; RELEASE(timers);
} }
/* xxx Should we make sure it isn't already there? */ /* xxx Should we make sure it isn't already there? */
[timers addObject: timer]; [timers addObject: timer];
@ -801,7 +823,7 @@ static int debug_run_loop = 0;
break; break;
} }
[min_timer retain]; RETAIN(min_timer);
[timers removeFirstObject]; [timers removeFirstObject];
/* Firing will also increment its fireDate, if it is repeating. */ /* Firing will also increment its fireDate, if it is repeating. */
[min_timer fire]; [min_timer fire];
@ -809,7 +831,7 @@ static int debug_run_loop = 0;
{ {
[timers addObject: min_timer]; [timers addObject: min_timer];
} }
[min_timer release]; RELEASE(min_timer);
min_timer = nil; min_timer = nil;
[NSNotificationQueue runLoopASAP]; /* Post notifications. */ [NSNotificationQueue runLoopASAP]; /* Post notifications. */
} }
@ -871,11 +893,11 @@ static int debug_run_loop = 0;
* If the watcher has been given a revised limit date - * If the watcher has been given a revised limit date -
* re-insert it into the queue in the correct place. * re-insert it into the queue in the correct place.
*/ */
[min_watcher retain]; RETAIN(min_watcher);
ASSIGN(min_watcher->limit, nxt); ASSIGN(min_watcher->limit, nxt);
[watchers removeObjectAtIndex: 0]; [watchers removeObjectAtIndex: 0];
[self _addWatcher: min_watcher forMode: mode]; [self _addWatcher: min_watcher forMode: mode];
[min_watcher release]; RELEASE(min_watcher);
} }
else else
{ {
@ -1204,14 +1226,14 @@ static int debug_run_loop = 0;
{ {
id watcher = (id) NSMapGet (wfd_2_object, (void*)fd_index); id watcher = (id) NSMapGet (wfd_2_object, (void*)fd_index);
NSAssert(watcher, NSInternalInconsistencyException); NSAssert(watcher, NSInternalInconsistencyException);
[watcher eventFor:(void*)fd_index mode:_current_mode]; [watcher eventFor: (void*)(gsaddr)fd_index mode: _current_mode];
[NSNotificationQueue runLoopASAP]; [NSNotificationQueue runLoopASAP];
} }
if (FD_ISSET (fd_index, &read_fds)) if (FD_ISSET (fd_index, &read_fds))
{ {
id watcher = (id) NSMapGet (rfd_2_object, (void*)fd_index); id watcher = (id) NSMapGet (rfd_2_object, (void*)fd_index);
NSAssert(watcher, NSInternalInconsistencyException); NSAssert(watcher, NSInternalInconsistencyException);
[watcher eventFor:(void*)fd_index mode:_current_mode]; [watcher eventFor: (void*)(gsaddr)fd_index mode: _current_mode];
[NSNotificationQueue runLoopASAP]; [NSNotificationQueue runLoopASAP];
} }
} }
@ -1250,12 +1272,12 @@ static int debug_run_loop = 0;
} }
/* Use the earlier of the two dates we have. */ /* Use the earlier of the two dates we have. */
d = [[d earlierDate:date] retain]; d = RETAIN([d earlierDate: date]);
/* Wait, listening to our input sources. */ /* Wait, listening to our input sources. */
[self acceptInputForMode: mode beforeDate: d]; [self acceptInputForMode: mode beforeDate: d];
[d release]; RELEASE(d);
return YES; return YES;
} }
@ -1297,8 +1319,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
int count = [_performers count]; int count = [_performers count];
int i; int i;
[target retain]; RETAIN(target);
[argument retain]; RETAIN(argument);
for (i = count; i > 0; i--) for (i = count; i > 0; i--)
{ {
item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)]; item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)];
@ -1308,8 +1330,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
[_performers removeObjectAtIndex:(i-1)]; [_performers removeObjectAtIndex:(i-1)];
} }
} }
[argument release]; RELEASE(argument);
[target release]; RELEASE(target);
} }
- (void) configureAsServer - (void) configureAsServer
@ -1353,7 +1375,7 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
[_performers addObject:item]; [_performers addObject:item];
} }
} }
[item release]; RELEASE(item);
} }
- (void) removePort: (NSPort*)port - (void) removePort: (NSPort*)port

View file

@ -44,6 +44,10 @@
#include <base/Invocation.h> #include <base/Invocation.h>
#include <Foundation/NSData.h> #include <Foundation/NSData.h>
#include <Foundation/NSDate.h> #include <Foundation/NSDate.h>
#include <Foundation/NSHashTable.h>
#include <Foundation/NSHost.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSPortMessage.h>
#include <Foundation/NSPortNameServer.h> #include <Foundation/NSPortNameServer.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -108,6 +112,698 @@ static int debug_tcp_port = 0;
/* Private interfaces */ /* Private interfaces */
@class GSTcpPort;
typedef struct {
gsu32 sendAddr;
gsu32 recvAddr;
gsu16 sendPort;
gsu16 recvPort;
gsu32 mesgId;
gsu32 mesgElems;
gsu32 remaining;
} GSTcpHeader;
@interface GSTcpHandle : NSObject <GCFinalization>
{
int desc; // Unix file descriptor.
NSLock *myLock; // Lock for This handle.
unsigned rLength; // Length of item read so far.
NSPortMessage *rMsg; // Message in progress.
unsigned rItem; // Index of current message item.
NSMutableData *rHeader; // Buffer for item data.
unsigned wLength;
NSPortMessage *wMsg;
unsigned wItem;
NSHashTable *ports;
}
+ (GSTcpHandle*) handleWithDescriptor: (int)descriptor;
- (void) addPort: (GSTcpPort*)p;
- (void) invalidate;
- (void) readData;
- (void) removePort: (GSTcpPort*)p;
- (void) writeData;
@end
@implementation GSTcpHandle
static NSRecursiveLock *tcpHandleLock = nil;
static NSHashTable *tcpHandleTable = 0;
+ (id) allocWithZone: (NSZone*)zone
{
[NSException raise: NSGenericException
format: @"attempt to alloc a GSTcpHandle!"];
return nil;
}
+ (void) initialize
{
if (tcpHandleLock == nil)
{
[gnustep_global_lock lock];
if (tcpHandleLock == nil)
{
tcpHandleLock = [NSRecursiveLock new];
tcpHandleTable =
NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
}
[gnustep_global_lock unlock];
}
}
+ (GSTcpHandle*) handleWithDescriptor: (int)descriptor
{
static GSTcpHandle *dummy = nil;
GSTcpHandle *handle;
if (descriptor < 0)
{
NSLog(@"illegal descriptor (%d) for Tcp Handle", descriptor);
return nil;
}
[tcpHandleLock lock];
if (dummy == nil)
dummy = (GSTcpHandle*)NSAllocateObject(self, 0, NSDefaultMallocZone());
dummy->desc = descriptor;
handle = (GSTcpHandle*)NSHashGet(tcpHandleTable, (void*)dummy);
if (handle == nil)
{
int e;
BOOL ok = YES;
if ((e = fcntl(descriptor, F_GETFL, 0)) >= 0)
{
e |= NBLK_OPT;
if (fcntl(descriptor, F_SETFL, e) < 0)
{
NSLog(@"unable to set non-blocking mode - %s", strerror(errno));
ok = NO;
}
}
else
{
NSLog(@"unable to get non-blocking mode - %s", strerror(errno));
ok = NO;
}
if (ok)
{
handle = (GSTcpHandle*)NSAllocateObject(self,0,NSDefaultMallocZone());
handle->desc = descriptor;
handle->ports =
NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
NSHashInsert(tcpHandleTable, (void*)handle);
AUTORELEASE(handle);
}
}
[tcpHandleLock unlock];
return handle;
}
- (void) addPort: (GSTcpPort*)p
{
[myLock lock];
NSHashInsert(ports, (void*)p);
[myLock unlock];
}
- (void) gcFinalize
{
[myLock lock];
[tcpHandleLock lock];
NSHashRemove(tcpHandleTable, (void*)self);
[tcpHandleLock unlock];
(void) close(desc);
desc = -1;
NSFreeHashTable(ports);
RELEASE(rHeader);
RELEASE(rMsg);
RELEASE(wMsg);
[myLock unlock];
RELEASE(myLock);
}
- (unsigned) hash
{
return (unsigned)desc;
}
- (void) invalidate
{
[myLock lock];
[myLock unlock];
}
- (BOOL) isEqual: (id)anObject
{
if (anObject == self)
return YES;
if ([anObject class] == [self class]
&& ((GSTcpHandle*)anObject)->desc == desc)
return YES;
return NO;
}
- (void) readData
{
int result;
unsigned want;
void *bytes = 0;
[myLock lock];
do
{
/*
* Get address and length of buffer for incoming data if we don't already
* have it from an earlier iteration of the loop. Create the buffer if
* necessary.
*/
if (bytes == 0)
{
if (rHeader == nil)
{
if (rItem == 0)
want = sizeof(GSTcpHeader);
else
want = 6;
rHeader = [[NSMutableData alloc] initWithLength: want];
bytes = [rHeader mutableBytes];
rLength = 0;
}
else
{
want = [rHeader length];
bytes = [rHeader mutableBytes];
}
}
/*
* Now we attempt to fill the buffer.
*/
result = read(desc, bytes + rLength, want - rLength);
if (result == 0)
{
NSLog(@"Unexpected EOF on descriptor %d", desc);
[self invalidate];
}
else if (result < 0)
{
if (errno != EAGAIN)
{
NSLog(@"Error reading on descriptor %d - %s",
desc, strerror(errno));
[self invalidate];
}
}
else
{
rLength += result;
if (rLength == want)
{
if (rItem == 0)
{
if (want == sizeof(GSTcpHeader))
{
}
else
{
}
}
else
{
}
}
}
}
while (result > 0);
[myLock unlock];
}
- (void) release
{
if ([self retainCount] == 1)
{
[super retain];
[self gcFinalize];
[super release];
}
[super release];
}
- (void) removePort: (GSTcpPort*)p
{
[myLock lock];
NSHashRemove(ports, (void*)p);
[myLock unlock];
}
- (void) writeData
{
[myLock lock];
[myLock unlock];
}
@end
@interface GSTcpPort : NSPort <GCFinalization>
{
NSRecursiveLock *myLock;
struct sockaddr_in addr;
int listener;
NSHashTable *handles;
}
+ (GSTcpPort*) portWithNumber: (gsu16)number
onHost: (NSHost*)host
beforeDate: (NSDate*)limit;
+ (GSTcpPort*) portWithAddress: (struct sockaddr_in*)address
andHandle: (GSTcpHandle*)handle
beforeDate: (NSDate*)limit;
- (void) addHandle: (GSTcpHandle*)h;
- (void) removeHandle: (GSTcpHandle*)h;
@end
@implementation GSTcpPort
static NSRecursiveLock *tcpPortLock = nil;
static NSMapTable *tcpPortMap = 0;
static GSTcpPort *dummyPort = nil;
+ (void) initialize
{
if (tcpPortLock == nil)
{
[gnustep_global_lock lock];
if (tcpPortLock == nil)
{
tcpPortLock = [NSRecursiveLock new];
tcpPortMap = NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
dummyPort = (GSTcpPort*)NSAllocateObject(self, 0,
NSDefaultMallocZone());
}
[gnustep_global_lock unlock];
}
}
+ (GSTcpPort*) portWithAddress: (struct sockaddr_in*)sockaddr
andHandle: (GSTcpHandle*)handle
beforeDate: (NSDate*)limit
{
GSTcpPort *port = nil;
NSMapTable *thePorts;
[tcpPortLock lock];
thePorts = (NSMapTable*)NSMapGet(tcpPortMap,
(void*)(gsaddr)sockaddr->sin_port);
if (thePorts == 0)
{
thePorts = NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
NSMapInsert(tcpPortMap,
(void*)(gsaddr)sockaddr->sin_port,
(void*)thePorts);
}
port = (GSTcpPort*)NSMapGet(tcpPortMap,
(void*)(gsaddr)sockaddr->sin_addr.s_addr);
if (port == nil)
{
port = (GSTcpPort*)NSAllocateObject(self,0,NSDefaultMallocZone());
port->listener = -1;
memcpy(&port->addr, sockaddr, sizeof(port->addr));
port->myLock = [NSRecursiveLock new];
port->handles = NSCreateHashTable(NSObjectHashCallBacks, 0);
NSMapInsert(thePorts, (void*)(gsaddr)sockaddr->sin_addr.s_addr,
(void*)port);
AUTORELEASE(port);
}
if (port != nil && handle != nil)
{
NSHashInsert(port->handles, (void*)handle);
[handle addPort: port];
}
[tcpPortLock unlock];
return port;
}
+ (GSTcpPort*) portWithNumber: (gsu16)number
onHost: (NSHost*)host
beforeDate: (NSDate*)limit
{
unsigned i;
GSTcpPort *port = nil;
NSHost *thisHost = [NSHost currentHost];
NSArray *addresses;
NSMapTable *thePorts;
if (host == nil)
{
host = thisHost;
}
addresses = [host addresses];
if ([addresses count] == 0)
{
NSLog(@"attempt to get port on host with no IP address");
return nil;
}
[tcpPortLock lock];
memset(&dummyPort->addr, '\0', sizeof(dummyPort->addr));
dummyPort->addr.sin_family = AF_INET;
dummyPort->addr.sin_port = GSSwapHostI16ToBig(number);
/*
* Get the map table of ports with the specified number.
*/
thePorts = (NSMapTable*)NSMapGet(tcpPortMap,
(void*)(gsaddr)dummyPort->addr.sin_port);
if (thePorts)
{
/*
* Check to see if we have a port for any one of the hosts IP addresses.
*/
for (i = 0; port == nil && i < [addresses count]; i++)
{
const char *a = [[addresses objectAtIndex: i] cString];
#ifndef HAVE_INET_ATON
dummyPort->sin_addr.s_addr = inet_addr(a);
#else
if (inet_aton(a, &dummyPort->addr.sin_addr) == 0)
{
NSLog(@"attempt to get port on host with bad address - '%s'", a);
continue;
}
#endif
port = (GSTcpPort*)NSMapGet(thePorts,
(void*)(gsaddr)dummyPort->addr.sin_addr.s_addr);
if (port != nil)
{
break;
}
}
}
if (port == nil)
{
if (host == thisHost)
{
int status = 1;
int desc;
port = (GSTcpPort*)NSAllocateObject(self,0,NSDefaultMallocZone());
port->listener = -1;
port->handles =
NSCreateHashTable(NSObjectHashCallBacks, 0);
port->addr.sin_addr.s_addr = GSSwapHostI32ToBig(INADDR_ANY);
if ((desc = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0)
{
NSLog(@"unable to create socket - %s", strerror(errno));
DESTROY(port);
}
else if (setsockopt(desc, SOL_SOCKET, SO_REUSEADDR, (char *)&status,
sizeof(status)) < 0)
{
(void) close(desc);
NSLog(@"unable to set reuse on socket - %s", strerror(errno));
DESTROY(port);
}
else if (bind(desc, (struct sockaddr *)&port->addr,
sizeof(port->addr)) < 0)
{
NSLog(@"unable to bind to port %s:%d - %s",
inet_ntoa(port->addr.sin_addr), number, strerror(errno));
(void) close(desc);
DESTROY(port);
}
else if (listen(desc, 5) < 0)
{
NSLog(@"unable to listen on port - %s", strerror(errno));
(void) close(desc);
DESTROY(port);
}
else if (getsockname(desc, (struct sockaddr*)&port->addr, &i) < 0)
{
NSLog(@"unable to get socket name - %s", strerror(errno));
(void) close(desc);
DESTROY(port);
}
else
{
port->listener = desc;
port->myLock = [NSRecursiveLock new];
/*
* Ok - now add the port for all the IP addresses it listens on.
*/
for (i = 0; i < [addresses count]; i++)
{
const char *a = [[addresses objectAtIndex: i] cString];
gsaddr val;
#ifndef HAVE_INET_ATON
dummyPort->addr.sin_addr.s_addr = inet_addr(a);
#else
if (inet_aton(a, &dummyPort->addr.sin_addr) == 0)
{
continue;
}
#endif
val = (gsaddr)dummyPort->addr.sin_addr.s_addr;
if (thePorts == 0)
{
/*
* No known ports within this port number -
* create the map table to add the new port to.
*/
thePorts = NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
NSMapInsert(tcpPortMap,
(void*)(gsaddr)port->addr.sin_port,
(void*)thePorts);
}
NSMapInsert(thePorts, (void*)val, (void*)port);
}
}
}
else if (number != 0) /* Can't connect to port zero */
{
for (i = 0; port == nil && i < [addresses count]; i++)
{
int desc;
const char *a = [[addresses objectAtIndex: i] cString];
port = (GSTcpPort*)NSAllocateObject(self,0,NSDefaultMallocZone());
port->listener = -1;
#ifndef HAVE_INET_ATON
port->addr.sin_addr.s_addr = inet_addr(a);
#else
if (inet_aton(a, &port->addr.sin_addr) == 0)
{
NSLog(@"opening port on host with bad address - '%s'", a);
continue;
}
#endif
if ((desc = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0)
{
NSLog(@"unable to create socket - %s", strerror(errno));
DESTROY(port);
}
else if (connect(desc, (struct sockaddr*)&port->addr,
sizeof(port->addr)) < 0)
{
NSLog(@"unable to make connection to %s:%d - %s", a,
GSSwapBigI16ToHost(port->addr.sin_port), strerror(errno));
DESTROY(port);
}
else
{
GSTcpHandle *handle;
port->myLock = [NSRecursiveLock new];
port->handles =
NSCreateHashTable(NSObjectHashCallBacks, 0);
handle = [GSTcpHandle handleWithDescriptor: desc];
NSHashInsert(port->handles, (void*)handle);
if (thePorts == 0)
{
/*
* No known ports within this port number -
* create the map table to add the new port to.
*/
thePorts = NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
NSMapInsert(tcpPortMap,
(void*)(gsaddr)port->addr.sin_port,
(void*)thePorts);
}
NSMapInsert(thePorts,
(void*)(gsaddr)port->addr.sin_addr.s_addr, (void*)port);
}
}
}
AUTORELEASE(port);
}
[tcpPortLock unlock];
return port;
}
- (void) addHandle: (GSTcpHandle*)h
{
[myLock lock];
NSHashInsert(handles, (void*)h);
[myLock unlock];
}
- (id) copyWithZone: (NSZone*)zone
{
return RETAIN(self);
}
- (void) gcFinalize
{
[self invalidate];
}
- (unsigned) hash
{
return (unsigned)(addr.sin_addr.s_addr ^ addr.sin_port);
}
- (void) invalidate
{
[myLock lock];
if ([self isValid])
{
NSMapTable *thePorts;
NSArray *handleArray;
unsigned i;
[tcpPortLock lock];
thePorts = NSMapGet(tcpPortMap, (void*)(gsaddr)addr.sin_port);
if (thePorts)
{
gsaddr val;
if (listener == -1)
{
val = (gsaddr)addr.sin_addr.s_addr;
NSMapRemove(thePorts, (void*)val);
}
else
{
unsigned i;
NSArray *addresses = [[NSHost currentHost] addresses];
for (i = 0; i < [addresses count]; i++)
{
const char *a = [[addresses objectAtIndex: i] cString];
#ifndef HAVE_INET_ATON
addr,sin_addr.s_addr = inet_addr(a);
#else
if (inet_aton(a, &addr.sin_addr) == 0)
{
continue;
}
#endif
val = (gsaddr)addr.sin_addr.s_addr;
NSMapRemove(thePorts, (void*)val);
}
}
}
[tcpPortLock unlock];
if (listener >= 0)
{
(void)close(listener);
listener = -1;
}
handleArray = NSAllHashTableObjects(handles);
i = [handleArray count];
while (i > 0)
{
GSTcpHandle *handle = [handleArray objectAtIndex: i];
[handle removePort: self];
}
NSFreeHashTable(handles);
[super invalidate];
}
[myLock unlock];
RELEASE(myLock);
}
- (BOOL) isEqual: (id)anObject
{
if (anObject == self)
return YES;
if ([anObject class] == [self class])
{
GSTcpPort *o = (GSTcpPort*)anObject;
if (o->addr.sin_port == addr.sin_port &&
o->addr.sin_addr.s_addr == addr.sin_addr.s_addr)
return YES;
}
return NO;
}
- (void) release
{
if ([self retainCount] == 1)
{
[super retain];
[self gcFinalize];
[super release];
}
[super release];
}
- (void) removeHandle: (GSTcpHandle*)h
{
[myLock lock];
NSHashRemove(handles, (void*)h);
[myLock unlock];
}
@end
@interface TcpInPort (Private) @interface TcpInPort (Private)
- (int) _port_socket; - (int) _port_socket;
- (struct sockaddr_in*) _listeningSockaddr; - (struct sockaddr_in*) _listeningSockaddr;

View file

@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <Foundation/NSObject.h>
#include <Foundation/NSConnection.h> #include <Foundation/NSConnection.h>
#include <Foundation/NSDistantObject.h> #include <Foundation/NSDistantObject.h>
#include <Foundation/NSDictionary.h> #include <Foundation/NSDictionary.h>
@ -11,7 +12,10 @@
#include <assert.h> #include <assert.h>
#include "server.h" #include "server.h"
int main(int argc, char *argv[]) @class TcpInPort;
@class PortDecoder;
int main (int argc, char *argv[])
{ {
id a; id a;
id p; id p;
@ -36,13 +40,18 @@ int main(int argc, char *argv[])
const char *type; const char *type;
NSAutoreleasePool *arp = [NSAutoreleasePool new]; NSAutoreleasePool *arp = [NSAutoreleasePool new];
GSDebugAllocationActive(YES);
[NSConnection setDebug: 10];
[NSDistantObject setDebug: 10];
[TcpInPort setDebug: 10];
[Coder setDebugging:YES]; [Coder setDebugging:YES];
[BinaryCStream setDebugging:YES]; [BinaryCStream setDebugging:YES];
#if NeXT_runtime #if NeXT_runtime
[NSDistantObject setProtocolForProxies:@protocol(AllProxies)]; [NSDistantObject setProtocolForProxies:@protocol(AllProxies)];
#endif #endif
printf("oneway %d\n", _F_ONEWAY);
if (argc > 1) if (argc > 1)
{ {
if (argc > 2) if (argc > 2)
@ -60,12 +69,16 @@ int main(int argc, char *argv[])
[c setReplyTimeout:180.0]; [c setReplyTimeout:180.0];
localObj = [[NSObject alloc] init]; localObj = [[NSObject alloc] init];
[p outputStats:localObj]; [p outputStats:localObj];
fprintf(stderr, "XXXXXXXXXXXXXXXXA %d\n", GSDebugAllocationCount([PortDecoder class]));
[p getLong:&i];
fprintf(stderr,"XXXXXXXXXXXXXXXXB %d\n", GSDebugAllocationCount([PortDecoder class]));
[p getLong:&i]; [p getLong:&i];
[p outputStats:localObj]; [p outputStats:localObj];
fprintf(stderr,"XXXXXXXXXXXXXXXXC %d\n", GSDebugAllocationCount([PortDecoder class]));
type = [c typeForSelector:sel_get_any_uid("name") type = [c typeForSelector:sel_get_any_uid("name")
remoteTarget:[p targetForProxy]]; remoteTarget:[p targetForProxy]];
printf("XXXXXXXXXXXXXXXXD %d\n", GSDebugAllocationCount([PortDecoder class]));
printf(">>type = %s\n", type); printf(">>type = %s\n", type);
printf(">>list proxy's hash is 0x%x\n", printf(">>list proxy's hash is 0x%x\n",
(unsigned)[p hash]); (unsigned)[p hash]);
printf(">>list proxy's self is 0x%x = 0x%x\n", printf(">>list proxy's self is 0x%x = 0x%x\n",
@ -149,9 +162,11 @@ int main(int argc, char *argv[])
id remote_peer_obj = [p objectAt:j]; id remote_peer_obj = [p objectAt:j];
printf("triangle %d object proxy's hash is 0x%x\n", printf("triangle %d object proxy's hash is 0x%x\n",
j, (unsigned)[remote_peer_obj hash]); j, (unsigned)[remote_peer_obj hash]);
#if 0
/* xxx look at this again after we use release/retain everywhere */ /* xxx look at this again after we use release/retain everywhere */
if ([remote_peer_obj isProxy]) if ([remote_peer_obj isProxy])
[remote_peer_obj release]; [remote_peer_obj release];
#endif
remote_peer_obj = [p objectAt:j]; remote_peer_obj = [p objectAt:j];
printf("repeated triangle %d object proxy's hash is 0x%x\n", printf("repeated triangle %d object proxy's hash is 0x%x\n",
j, (unsigned)[remote_peer_obj hash]); j, (unsigned)[remote_peer_obj hash]);
@ -170,9 +185,14 @@ int main(int argc, char *argv[])
printf("%s - %s\n", [k cString], [[v description] cString]); printf("%s - %s\n", [k cString], [[v description] cString]);
} }
[arp release];
arp = [NSAutoreleasePool new];
printf("%d\n", [c retainCount]);
printf("%s\n", [[[c statistics] description] cString]);
// printf("%s\n", GSDebugAllocationList(YES));
[NSRunLoop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 20 * 60]]; [NSRunLoop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 20 * 60]];
[c invalidate]; [c invalidate];
[arp release]; [arp release];
exit(0); exit(0);
} }

View file

@ -7,12 +7,12 @@ GCC_VERSION=2.8.0
# The version number of this release. # The version number of this release.
MAJOR_VERSION=0 MAJOR_VERSION=0
MINOR_VERSION=5 MINOR_VERSION=5
SUBMINOR_VERSION=0 SUBMINOR_VERSION=5
GNUSTEP_BASE_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${SUBMINOR_VERSION} GNUSTEP_BASE_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${SUBMINOR_VERSION}
VERSION=${GNUSTEP_BASE_VERSION} VERSION=${GNUSTEP_BASE_VERSION}
GNUSTEP_BASE_FTP_MACHINE=ftp.gnu.org GNUSTEP_BASE_FTP_MACHINE=ftp.gnu.org
GNUSTEP_BASE_FTP_DIRECTORY=pub/gnu GNUSTEP_BASE_FTP_DIRECTORY=pub/gnu/gstep
GNUSTEP_BASE_SNAP_FTP_MACHINE=alpha.gnu.org GNUSTEP_BASE_SNAP_FTP_MACHINE=alpha.gnu.org
GNUSTEP_BASE_SNAP_FTP_DIRECTORY=gnu/gnustep GNUSTEP_BASE_SNAP_FTP_DIRECTORY=gnu/gnustep