Fixed NSUndoManager bug #14448 by extending NSInvocation with the possibility to retain or not the target

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21721 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
qmathe 2005-09-17 21:41:12 +00:00
parent a27efb2586
commit 1c3d59ee22
4 changed files with 79 additions and 32 deletions

View file

@ -1,3 +1,18 @@
2005-09-17 Saso Kiselkov <diablos@manga.sk>
* Headers/Foundation/NSInvocation.h:
* Source/NSInvocation.m:
(-targetRetained, -retainArgumentsIncludingTarget:):
Added new methods which allow target to be not retained when arguments
are and to check whether it is retained or not (-retainsArguments code
moved in -retainArgumentsIncludingTarged and simplified by removing a
redundant nested branch statement).
* Source/NSUndoManager.m (-forwardInvocation:,
-registerUndoWithTarget:selector:object:): Fixed bug #14488 by relying
on previous new methods to retain undo invocation (taking in account
the fact arguments may have been released before it is called).
Patch committed by Quentin Mathe.
2005-09-01 Adam Fedor <fedor@gnu.org>
* Source/NSSortDescriptor.m ([NSArray

View file

@ -42,6 +42,7 @@
void *_dummy;
#endif
BOOL _argsRetained;
BOOL _targetRetained;
BOOL _validReturn;
BOOL _sendToSuper;
}
@ -71,6 +72,11 @@
- (BOOL) argumentsRetained;
- (void) retainArguments;
#if OS_API_VERSION(GS_API_NONE,GS_API_NONE) && GS_API_VERSION(011201,GS_API_LATEST)
- (BOOL) targetRetained;
- (void) retainArgumentsIncludingTarget: (BOOL)retainTargetFlag;
#endif
/*
* Dispatching an Invocation.
*/

View file

@ -189,9 +189,13 @@ _arg_addr(NSInvocation *inv, int index)
- (void) dealloc
{
if (_targetRetained)
{
_targetRetained = NO;
RELEASE(_target);
}
if (_argsRetained)
{
RELEASE(_target);
_argsRetained = NO;
if (_cframe && _sig)
{
@ -437,11 +441,14 @@ _arg_addr(NSInvocation *inv, int index)
*/
- (void) setTarget: (id)anObject
{
if (_argsRetained)
if (_targetRetained)
{
ASSIGN(_target, anObject);
}
else
{
_target = anObject;
}
}
/**
@ -467,23 +474,35 @@ _arg_addr(NSInvocation *inv, int index)
*/
- (void) retainArguments
{
if (_argsRetained)
{
return;
}
else
[self retainArgumentsIncludingTarget: YES];
}
/**
* Returns YES if target has been retained yet, NO otherwise.
*/
- (BOOL) targetRetained
{
return _targetRetained;
}
/**
* Similar to -[NSInvocation retainArguments], but allows the sender to
* explicitly control whether the target is retained as well. Retaining
* the target is sometimes not desirable (such as in NSUndoManager), as
* retain loops could result.
*/
- (void) retainArgumentsIncludingTarget: (BOOL)retainTargetFlag
{
if (_argsRetained == NO)
{
unsigned int i;
_argsRetained = YES;
IF_NO_GC(RETAIN(_target));
if (_cframe == 0)
{
return;
}
for (i = 3; i <= _numArgs; i++)
{
if (*_info[i].type == _C_ID || *_info[i].type == _C_CHARPTR)
{
if (*_info[i].type == _C_ID)
{
@ -495,7 +514,7 @@ _arg_addr(NSInvocation *inv, int index)
IF_NO_GC(RETAIN(old));
}
}
else
else if (*_info[i].type == _C_CHARPTR)
{
char *str;
@ -511,6 +530,12 @@ _arg_addr(NSInvocation *inv, int index)
}
}
}
if (retainTargetFlag && _targetRetained == NO)
{
_targetRetained = YES;
IF_NO_GC(RETAIN(_target));
}
}

View file

@ -425,6 +425,7 @@
format: @"forwardInvocation without beginUndoGrouping"];
}
}
[anInvocation retainArgumentsIncludingTarget: NO];
[anInvocation setTarget: _nextTarget];
_nextTarget = nil;
[_group addInvocation: anInvocation];
@ -726,7 +727,7 @@
g = _group;
sig = [target methodSignatureForSelector: aSelector];
inv = [NSInvocation invocationWithMethodSignature: sig];
[inv retainArguments];
[inv retainArgumentsIncludingTarget: NO];
[inv setTarget: target];
[inv setSelector: aSelector];
[inv setArgument: &anObject atIndex: 2];