some small fixups

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@36616 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2013-05-13 07:09:41 +00:00
parent 891d7e0f24
commit 360e1f6ec6
5 changed files with 66 additions and 66 deletions

View file

@ -1,3 +1,13 @@
2013-05-13 Richard Frith-Macdonald <rfm@gnu.org>
* Source/ObjectiveC2/runtime.c: when replacing a method, update the
cache so we don't use the old version.
* Source/NSNotificationCenter.m: trivial tweak to map release code
and remove method caching for OSX compatibility :-(
* Source/NSPropertyList.m: Fix bug byte swapping unicode in apple
binary plist generation.
* Tests/base/NSNotification/dynamic.m: Fix crash in testcase.
2013-05-13 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSURLConnection.m: Release delegate immediately after

View file

@ -155,7 +155,6 @@ struct NCTbl; /* Notification Center Table structure */
@public
__weak id observer; /* Object to receive message. */
SEL selector; /* Method selector. */
IMP method; /* Method implementation. */
struct Obs *next; /* Next item in linked list. */
struct NCTbl *link; /* Pointer back to chunk table */
}
@ -169,7 +168,6 @@ struct NCTbl; /* Notification Center Table structure */
typedef struct Obs {
id observer; /* Object to receive message. */
SEL selector; /* Method selector. */
IMP method; /* Method implementation. */
struct Obs *next; /* Next item in linked list. */
int retained; /* Retain count for structure. */
struct NCTbl *link; /* Pointer back to chunk table */
@ -248,8 +246,7 @@ static void obsFree(Observation *o);
#include "GNUstepBase/GSIArray.h"
#define GSI_MAP_RETAIN_KEY(M, X)
#define GSI_MAP_RELEASE_KEY(M, X) ({if ((((uintptr_t)X.obj) & 1) == 0) \
RELEASE(X.obj);})
#define GSI_MAP_RELEASE_KEY(M, X) ({if (YES == M->extra) RELEASE(X.obj);})
#define GSI_MAP_HASH(M, X) doHash(X.obj)
#define GSI_MAP_EQUAL(M, X,Y) doEqual(X.obj, Y.obj)
#define GSI_MAP_RETAIN_VAL(M, X)
@ -258,7 +255,7 @@ static void obsFree(Observation *o);
#define GSI_MAP_KTYPES GSUNION_OBJ|GSUNION_NSINT
#define GSI_MAP_VTYPES GSUNION_PTR
#define GSI_MAP_VEXTRA Observation*
#define GSI_MAP_EXTRA void*
#define GSI_MAP_EXTRA BOOL
#if GS_WITH_GC
#include <gc/gc_typed.h>
@ -313,7 +310,7 @@ typedef struct NCTbl {
#define LOCKCOUNT (TABLE->lockCount)
static Observation *
obsNew(NCTable *t, SEL s, IMP m, id o)
obsNew(NCTable *t, SEL s, id o)
{
Observation *obs;
@ -373,7 +370,6 @@ obsNew(NCTable *t, SEL s, IMP m, id o)
#endif
obs->selector = s;
obs->method = m;
#if GS_WITH_GC
GSAssignZeroingWeakPointer((void**)&obs->observer, (void*)o);
#else
@ -490,6 +486,7 @@ static NCTable *newNCTable(void)
t->named = NSAllocateCollectable(sizeof(GSIMapTable_t), NSScannedOption);
GSIMapInitWithZoneAndCapacity(t->nameless, _zone, 16);
GSIMapInitWithZoneAndCapacity(t->named, _zone, 128);
t->named->extra = YES; // This table retains keys
t->_lock = [NSRecursiveLock new];
return t;
@ -651,10 +648,6 @@ purgeCollectedFromMapNode(GSIMapTable map, GSIMapNode node)
* extra bit. This should be ok for the objects we deal with
* which are all aligned on 4 or 8 byte boundaries on all the machines
* I know of.
*
* We also use this trick to differentiate between map table keys that
* should be treated as objects (notification names) and those that
* should be treated as pointers (notification objects)
*/
#define CHEATGC(X) (id)(((uintptr_t)X) | 1)
@ -795,9 +788,6 @@ static NSNotificationCenter *default_center = nil;
name: (NSString*)name
object: (id)object
{
Class cls;
Method method;
IMP imp;
Observation *list;
Observation *o;
GSIMapTable m;
@ -811,28 +801,17 @@ static NSNotificationCenter *default_center = nil;
[NSException raise: NSInvalidArgumentException
format: @"Null selector passed to addObserver ..."];
cls = object_getClass(observer);
method = class_getInstanceMethod(cls, selector);
imp = method_getImplementation(method);
if (0 == imp)
if ([observer respondsToSelector: selector] == NO)
{
/* A class may not implement the selector (in which case we can't
* cache the method), but if it's going to forward the message to
* some other object it must at least say it responds to the
* selector.
*/
if ([observer respondsToSelector: selector] == NO)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] Observer '%@' does not respond to selector '%@'",
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
observer, NSStringFromSelector(selector)];
}
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] Observer '%@' does not respond to selector '%@'",
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
observer, NSStringFromSelector(selector)];
}
lockNCTable(TABLE);
o = obsNew(TABLE, selector, imp, observer);
o = obsNew(TABLE, selector, observer);
if (object != nil)
{
@ -1231,15 +1210,8 @@ static NSNotificationCenter *default_center = nil;
{
NS_DURING
{
if (0 == o->method)
{
[o->observer performSelector: o->selector
withObject: notification];
}
else
{
(*o->method)(o->observer, o->selector, notification);
}
[o->observer performSelector: o->selector
withObject: notification];
}
NS_HANDLER
{

View file

@ -3723,18 +3723,20 @@ isEqualFunc(const void *item1, const void *item2,
buffer = [dest mutableBytes] + offset;
[string getCharacters: buffer];
// Always store in big-endian, so if machine is little-endian,
// perform byte-swapping.
#if !GS_WORDS_BIGENDIAN
/* Always store in big-endian, so if machine is little-endian,
* perform byte-swapping.
*/
{
int i;
uint8_t *o = (uint8_t*)buffer;
int i;
for (i = 0; i < len; i++)
{
uint8_t o = *buffer++;
uint8_t c = *o++;
buffer[-1] = *buffer;
*buffer++ = o;
o[-1] = *o;
*o++ = c;
}
}
#endif

View file

@ -575,16 +575,22 @@ IMP
class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
{
Method method = class_getInstanceMethodNonrecursive(cls, name);
IMP old;
if (method == NULL)
{
class_addMethod(cls, name, imp, types);
return NULL;
}
old = (IMP) method->method_imp;
method->method_imp = (objc_imp_gnu) imp;
return old;
else
{
IMP old = (IMP) method->method_imp;
method->method_imp = (objc_imp_gnu) imp;
if (CLS_ISRESOLV(cls))
{
__objc_update_dispatch_table_for_class(cls);
}
return old;
}
}

View file

@ -2,26 +2,36 @@
#include <objc/runtime.h>
#import "ObjectTesting.h"
@interface Toggle : NSObject @end
static BOOL notifiedCurrent = NO;
@interface Toggle : NSObject
@end
@implementation Toggle
- (void)foo: (NSNotification*)n
- (void) foo: (NSNotification*)n
{
assert(0);
notifiedCurrent = NO;
}
- (void) bar: (NSNotification*)n
{
notifiedCurrent = YES;
}
- (void)bar: (NSNotification*)n {}
@end
int main(void)
{
[NSAutoreleasePool new];
NSNotificationCenter *nc = [NSNotificationCenter new];
id t = [Toggle new];
[nc addObserver: t selector: @selector(foo:) name: nil object: nil];
class_replaceMethod([Toggle class],
@selector(foo:),
class_getMethodImplementation([Toggle class],
@selector(bar:)),
"v@:@");
[nc postNotificationName: @"foo" object: t];
return 0;
NSNotificationCenter *nc;
id t = [Toggle new];
[NSAutoreleasePool new];
nc = [NSNotificationCenter new];
[nc addObserver: t selector: @selector(foo:) name: nil object: nil];
class_replaceMethod([Toggle class],
@selector(foo:),
class_getMethodImplementation([Toggle class], @selector(bar:)),
"v@:@");
[nc postNotificationName: @"foo" object: t];
[t release];
PASS(YES == notifiedCurrent, "implementation not cached");
return 0;
}