Header :
#interface CodeTest : NSObject {
BOOL cancelThread;
}
-(void) testCode;
-(void) stopRunning;
-(void) startRunning;
#property (assign) BOOL cancelThread;
#end
Implementation :
-(void)stopRunning{
self.cancelThread = YES;
}
-(void)startRunning{
self.cancelThread = NO;
[NSThread detachNewThreadSelector:#selector(testCode) toTarget:self withObject:nil];
}
-(void)testCode{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"STARTED");
/* Std C99 code */
while( conditions ){
if(self.cancelThread){
conditions = NO;
}
...
...
}
/* end of C code */
[pool release];
}
As you can see, it tires to execute testCode on a separate thread and using the cancelThread BOOL as a stop execution flag in the separate thread.
I have the following issue :
The compiler signals that self.cancelThread in the middle of the std c code is not valid (self is not defined). I think, it tries to interpret that statement as c code but this is obj-c.
There is something missing ?
UPDATE : It's not related to missing {}'s as one of you suggested... The code works perfectly without the if(self.cancelThread){ conditions = NO; }.
-[CodeTest setCancelThread:]: unrecognized selector.
Means that you don't have a setter defined for the cancelThread property. You're missing
#synthesize cancelThread;
(in your #implementation section)
What do you mean by " /* Std C99 code */"?
If that code is really being compiled as C99 code, then self.cancelThread is problematic because it is an Objective-C expression. First, it is the equivalent of [self cancelThread], a method call and, secondly, it requiresself` which wouldn't be present in the body of a C99 function.
However, given that the code you showed has it in a method, the comment doesn't make sense.
Related
I have a simple function that takes a completion handler as a JSValue. It's a JSValue because I'm using this function as part of JSExport protocol.
This function then calls another internal method with another completion handler. When this second handler is called, I want to callWithArguments on the JSValue.
This all works as expected when I callWithArguments from outside the second completion handler, but I get a BAD_ACCESS when calling from the second handler.
func myFunction(completion: JSValue) {
// If I put completion.callWithAttributes([]) here, everything works fine.
self.mySecondFunction(completion: {(result: Dictionary<String, AnyObject>) -> Void in
// If I put completion.callWithAttributes([]) here, I get a BAD_ACCESS
})
}
Any help greatly appreciated. Thanks!
I strongly suggest you to do the following
[self.callback.context[#"setTimeout"]
callWithArguments:#[callback, #0, items]];
when you are going to send response to the JavaScriptCore counterpart. This will prevent the TVML UI MainThread to hang. As you can see it's a call of the setTimeout javascript function with delay 0, your callback and items as parameters like:
setTimeout(callback,0,items)
I'm not sure how you are creating the alert anyways here is one from Apple:
createAlert : function(title, description) {
var alertString = `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<alertTemplate>
<title>${title}</title>
<description>${description}</description>
<button class="btn_close">
<text>OK</text>
</button>
</alertTemplate>
</document>`
var parser = new DOMParser();
var alertDoc = parser.parseFromString(alertString, "application/xml");
return alertDoc
}
There is no direct relationship with the alert and the behavior you are seeing here, it's more a side effect of calling this
completion.callWithArguments([])
in a unexpected way. It's better that you save your completion somewhere, and get a reference to it on the object instance. Then, when the long task ends, you call it. Also if you are performing a long task, it's reasonable that you move everything in a NSOperation like this:
/** JavaScriptCore Callback Operation */
#interface JSCallbackOperation: NSOperation
#property(nonatomic, strong) JSValue*callback;
#property(nonatomic, strong) id items;
#end
#implementation JSCallbackOperation
- (id)initWithItems:(id)items callback:(JSValue*)callback {
if(self = [super init]) {
self.items=items;
self.callback=callback;
}
return self;
}
- (void)main {
#autoreleasepool {
if(self.callback) {
NSLog(#"Dispatching %#", self.callback);
[self.callback.context[#"setTimeout"]
callWithArguments:#[self.callback, #0, self.items]];
}
}
}
At this point you define a helper a call the callbacks with parameters then:
#pragma mark - API Helper
- (void)handleResponseWithItems:(id)items callback:(JSValue*)callback {
NSArray *active_and_pending_operations = operationQueue.operations;
NSInteger count_of_operations = operationQueue.operationCount;
NSLog(#"Running operations: %ld of %ld", active_and_pending_operations.count, count_of_operations);
JSCallbackOperation *op = [[JSCallbackOperation alloc] initWithItems:items callback:callback];
[op setQueuePriority:NSOperationQueuePriorityNormal];
[op setCompletionBlock:^{
NSLog(#"Operation completed.");
}];
[operationQueue addOperation:op];
}
To make use of global variables and methods I implemented Singleton as a healthy coding practice. I followed Apple documents, john wordsworth blog before implementing it. In the first, I did not make my singleton thread safe and I implemented this method along with all other mentioned in the blog and Apple document.
+ (SingletonClass *)sharedManager
{
static SingletonClass *sharedManager = nil;
if (sharedManager == nil) {
sharedManager = [[super allocWithZone:NULL] init];
}
return sharedManager;
}
After that to make Singleton thread safe I made changes to + (SingletonClass *)sharedManager class like this and my app stops launching. I put break points and observed dispatch_once gets called twice and then code stops executing further.
+(SingletonClass *)sharedManager
{
static SingletonClass *sharedManager = nil;
if (sharedManager !=nil)
{
return sharedManager;
}
static dispatch_once_t pred;
dispatch_once(&pred, ^{
sharedManager = [SingletonClass alloc];
sharedManager=[sharedManager init];
});
return sharedManager;
}
If i remove this thread safe code snippet and revert back to previous code it works fine and code gets executed.
Please note that I also looked at the bbum's answer here in which he has mentioned possible deadlock situation before asking question but I am not able to figure out the issue. Any explanation or solution will be helpful for me. Thanks.
Edit 1:
In case someone wants to look at the complete code, I have created gist for that. Please follow there. Thanks.
Let's consider what happens if two threads call second version of sharedManager almost simultaneously.
Thread 1 calls first. It checks sharedManager !=nil, which is false, so it goes on to the dispatch_once. In the dispatch_once block, it executes [SingletonClass alloc] and stores the result in sharedManager.
Now, before thread 1 continues on to the next line, thread 2 comes along and calls sharedManager. Thread 2 checks sharedManager !=nil, which is now true. So it returns sharedManager, and the caller then tries to use sharedManager. But at this time, sharedManager hasn't been fully initialized yet. That's bad.
You cannot set sharedManager until you have a fully initialized object to set it to. Also (as borrrden pointed out), you don't need the sharedManager !=nil check at the top, because dispatch_once is very efficient anyway.
+ (SingletonClass *)sharedManager {
static dispatch_once_t pred;
static SingletonClass *sharedManager;
dispatch_once(&pred, ^{
sharedManager = [[SingletonClass alloc] init];
});
return sharedManager;
}
Now, I've looked at your gist and your problem is here:
+ (id)allocWithZone:(NSZone*)zone {
return [[self sharedManager] retain];
}
Your +[SingletonClass sharedManager] method calls +[SingletonClass alloc] in the dispatch_once block. Since you don't override alloc, +[SingletonClass alloc] calls +[SingletonClass allocWithZone:NULL]. And +[SingletonClass allocWithZone:] method calls +[SingletonClass sharedManager]. On this second call to sharedManager, your program hangs in dispatch_once, because you're still inside the first call to dispatch_once.
The simplest fix is to remove your implementation of allocWithZone:. Just document that sharedManager is the only supported way to get an instance of SingletonClass and move on.
If you want to be obtuse and make [[SingletonClass alloc] init] return the singleton, even if you do it repeatedly, it's complicated. Don't try to override alloc or allocWithZone:. Do this:
static SingletonClass *sharedManager; // outside of any method
+ (SingletonClass *)sharedManager {
return sharedManager ? sharedManager : [[SingletonClass alloc] init];
}
- (id)init {
static dispatch_once_t once;
dispatch_once(&once, ^{
if (self = [super init]) {
// initialization here...
sharedManager = self;
}
});
self = sharedManager;
return self;
}
You don't need the check on the top, get rid of the if statement. The dispatch_once guarantees that the block will only be executed once in the lifetime of the application so the first check is redundant.
More Info:
http://cocoasamurai.blogspot.jp/2011/04/singletons-your-doing-them-wrong.html
I am developing an Objective-C application, and what I want to do, is something like the following:
+-----------------+ +---------------+
| Some Object | <---------- | Synchronize |
|(Not Thread Safe)| | Proxy |
+-----------------+ / +---------------+
/
/ Intercepts [someobject getCount]
/ #synchronize (someObject)
/
[someObject getCount] /
+----------------------+
| Some Calling Object |
+----------------------+
What I've asking is, how can I create an object in objective-c, that intercepts messages sent to another object, in order to perform code before the message is sent to that object.
Some things that I think will not work:
Categories (I need this to only happen for certain instances of a class)
Rewriting the object (I don't have access to the source of the object)
Method swizzling (once again, this need to only happen for certain instances of a class)
You would implement an NSProxy that forwards messages to your non-thread-safe object.
Here is a nice writeup of message forwarding in Objective-C, and here is Apple's documentation.
To handle thread safety, it depends on what you need. If your non-thread-safe object must run on a specific thread then you can use a NSRunLoop on said thread to serialize messages to that object.
Here is an example of using NSInvocation in conjunction with NSRunLoop. In that example they're using performSelector:withObject:afterDelay: but to use it with performSelector:onThread:withObject:waitUntilDone: would be very similar.
Otherwise, just use a single NSRecursiveLock in your proxy.
If you know exactly what instances should have the behavior you are trying to achieve you can go with method swizzling and call the base implementation if the instance is not the one you are looking for.
You can have a global shared object that lists the "interesting" instances and use it in the swizzling implementation whether you have to call the base one or your custom one.
So, I bit the bullet, and decided to make my own proxy class. To subclass, you simply override the 'forwardInvocation:' message, and you call any code you need there, before calling [super forwardInvocation:]. Please not this will NOT work with vardic methods, as NSInvocation doesn't work with vardic methods.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/objc.h>
#import <objc/message.h>
#interface RJProxy : NSObject {
#private
NSObject *target;
}
#property(readwrite, retain) NSObject *target;
-(NSObject *) getTarget;
#end
#implementation RJProxy
#synthesize target;
-(NSMethodSignature *) methodSignatureForSelector:(SEL)aSelector
{
if (objc_getAssociatedObject(self, "isProxy"))
{
IMP NSObjectImp = [NSObject instanceMethodForSelector:#selector(methodSignatureForSelector:)];
NSMethodSignature *methodSignature = (NSMethodSignature *) NSObjectImp(self, #selector(methodSignatureForSelector:), aSelector);
if (methodSignature)
return methodSignature;
return [target methodSignatureForSelector:aSelector];
}
else
{
Class subClass = self->isa;
#try {
self->isa = objc_getAssociatedObject(self, "realSuperclass");
return [super methodSignatureForSelector:aSelector];
}
#finally {
self->isa = subClass;
}
}
}
-(void) forwardInvocation:(NSInvocation *)anInvocation
{
if (objc_getAssociatedObject(self, "isProxy"))
{
Class subClass = target->isa;
target->isa = objc_getAssociatedObject(self, "realSuperclass");
[anInvocation invokeWithTarget:target];
target->isa = subClass;
}
else
{
Class realSuperclass = objc_getAssociatedObject(self, "realSuperclass");
Class subclass = self->isa;
self->isa = realSuperclass;
if ([self respondsToSelector:[anInvocation selector]])
{
[anInvocation invokeWithTarget:self];
}
else
{
[self doesNotRecognizeSelector:[anInvocation selector]];
}
self->isa = subclass;
}
}
-(NSObject *) getTarget
{
if (objc_getAssociatedObject(self, "isProxy"))
{
return target;
}
return self;
}
#end
BOOL object_setProxy(NSObject *object, RJProxy *proxy);
BOOL object_setProxy(NSObject *object, RJProxy *proxy)
{
proxy.target = object;
Class objectClass = object_getClass(object);
Class objectSub = objc_allocateClassPair(objectClass, [[NSString stringWithFormat:#"%s_sub%i", class_getName(objectClass), objc_getAssociatedObject(objectClass, "subclassTimes")] UTF8String], 0);
objc_setAssociatedObject(objectClass, "subclassTimes", (id) ((int) objc_getAssociatedObject(objectClass, "subclassTimes") + 1), OBJC_ASSOCIATION_ASSIGN);
objc_registerClassPair(objectSub);
Class proxyClass = object_getClass(proxy);
Class proxySub = objc_allocateClassPair(proxyClass, [[NSString stringWithFormat:#"%s_sub%i", class_getName(proxyClass), objc_getAssociatedObject(proxyClass, "subclassTimes")] UTF8String], 0);
objc_setAssociatedObject(proxyClass, "subclassTimes", (id) ((int) objc_getAssociatedObject(proxyClass, "subclassTimes") + 1), OBJC_ASSOCIATION_ASSIGN);
objc_registerClassPair(proxySub);
object_setClass(object, proxySub);
object_setClass(proxy, proxySub);
objc_setAssociatedObject(object, "isProxy", (id) NO, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(proxy, "isProxy", (id) YES, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(object, "realSuperclass", objectClass, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(proxy, "realSuperclass", proxyClass, OBJC_ASSOCIATION_ASSIGN);
return NO;
}
#interface SynchronizeProxy : RJProxy
#end
#implementation SynchronizeProxy
-(void) forwardInvocation:(NSInvocation *)anInvocation {
#synchronized ([self getTarget])
{
[super forwardInvocation:anInvocation];
}
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
NSArray *arrayToSynchronize = [NSArray arrayWithObjects:#"This, is, a, test!", nil];
SynchronizeProxy *myProxy = [SynchronizeProxy new];
object_setProxy(arrayToSynchronize, myProxy);
// now all calls will be synchronized!
NSLog(#"Array at address 0x%X with count of %lu, and Objects %# ", (unsigned) arrayToSynchronize, [arrayToSynchronize count], arrayToSynchronize);
[myProxy release];
[arrayToSynchronize release];
}
return 0;
}
is there any difference between the two methods?
```
// MACRO FUNCTION
#define SAFELY_RELEASE(__POINTER) { [__POINTER release]; __POINTER = nil; }
// C FUNCTION
void SAFELY_RELEASE(id __POINTER) {
[__POINTER release]; __POINTER = nil;
}
```
Yes. The function won't do what you expect it to, because the pointer will have been passed into it by value, rather than by reference.
Imagine this:
- (void)method {
id object = [[NSObject alloc] init];
SAFELY_RELEASE( object );
}
SAFELY_RELEASE gets object. It can send it messages, but setting it to nil will not change its value in method.
An equivalent function would be:
void SAFELY_RELEASE(id *__POINTER) {
[*__POINTER release]; *__POINTER = nil;
}
Then you'd use it by using:
SAFELY_RELEASE( &object );
The macro has another downside, though: Xcode's refactoring tools will probably not be able to change the parameter inside. For instance:
#interface Foo {
NSObject *var;
}
#implementation Foo
- (id)init {
if (( self = [super init] )) {
var = [[NSObject alloc] init];
}
return self;
}
- (void)dealloc {
SAFELY_RELEASE(var);
[super dealloc];
}
If you try to rename var using the refactor tool, you'll probably find that it won't be able to rename the var in dealloc.
Really, unless you have a really good reason to do this you should be using ARC.
void SAFELY_RELEASE(id __POINTER) is guaranted to __POINTER be an releasable object.
Both of them is wrong, because __POINTER = nil; will have no effects. You should nil it in object (controller)
I was using one of these macros, then I cam across this post.
Makes sense that you don't want to set to nil while in development as you want it to crash on a dealloc reference and not sending it to nil.
I'm trying to create recursion using blocks. It works for a while, but eventually it crashes and gives me a bad access exception. This is my code:
BOOL (^Block)(Square *square, NSMutableArray *processedSquares) = ^(Square *square, NSMutableArray *processedSquares) {
[processedSquares addObject:square];
if (square.nuked) {
return YES; // Found a nuked square, immediately return
}
for (Square *adjacentSquare in square.adjacentSquares) {
if ([processedSquares containsObject:adjacentSquare]) {
continue; // Prevent infinite recursion
}
if (Block(adjacentSquare, processedSquares)) {
return YES;
}
}
return NO;
};
__block NSMutableArray *processedSquares = [NSMutableArray array];
BOOL foundNukedSquare = Block(square, processedSquares);
Explanation: I have a Square class that has a BOOL nuked. It also has an NSArray adjacentSquares containing other Squares.
I want to check whether a square, or one of its 'connected' squares, is nuked or not.
The array processedSquares is to keep track of the squares I have checked to prevent infinite recursion.
When I run this, it's doing a lot of calls of this block (as expected). But at some point, it crashes at the last line with a bad access exception.
I also get this in the console:
Cannot access memory at address 0x1
Cannot access memory at address 0x1
Cannot access memory at address 0x1
Cannot access memory at address 0x1
warning: Cancelling call - objc code on the current thread's stack makes this unsafe.
I'm not that familiar with blocks and recursion. Any ideas?
Edit 1
As requested, the backtrace:
#0 0x00000001 in ??
#1 0x000115fb in -[Square connectedToNukedSquare] at Square.m:105
#2 0x00010059 in __-[Bot makeMove]_block_invoke_1 at Bot.m:94
#3 0x91f3f024 in _dispatch_call_block_and_release
#4 0x91f31a8c in _dispatch_queue_drain
#5 0x91f314e8 in _dispatch_queue_invoke
#6 0x91f312fe in _dispatch_worker_thread2
#7 0x91f30d81 in _pthread_wqthread
#8 0x91f30bc6 in start_wqthread
You need a __block on Block, change the declaration to:
__block BOOL (^Block)(Square *square, NSMutableArray *processedSquares);
Block = ^(Square *square, NSMutableArray *processedSquares) {
When a variable (Block) is referenced within a block then its current value is copied into the block. In your code Block hasn't yet been given a value, as you are constructing the block in the assignment...
The __block prefix passes the variable by reference - by the time your block makes its recursive call Block has a value, the reference to it is used to obtain that value, and the recursive call is OK.
I don't know why its worked at all for you without the __block - failed straightaway for me. With the modifier however I can recurse to at least a depth of 10,000 - so stack space isn't a problem!
You're liking doing something wrong with the setup -- your Square objects are probably messed up somehow. Here's a complete example that works fine for me, maybe it can help you find your mistake:
#include <stdio.h>
#include <Foundation/Foundation.h>
#interface Square : NSObject
{
BOOL nuked;
NSArray *adjacentSquares;
}
#property(nonatomic) BOOL nuked;
#property(nonatomic, retain) NSArray *adjacentSquares;
#end
#implementation Square
#synthesize nuked;
#synthesize adjacentSquares;
#end;
BOOL (^Block)(Square *square, NSMutableArray *processedSquares) = ^(Square *square, NSMutableArray *processedSquares) {
[processedSquares addObject:square];
if (square.nuked) {
return YES; // Found a nuked square, immediately return
}
for (Square *adjacentSquare in square.adjacentSquares) {
if ([processedSquares containsObject:adjacentSquare]) {
continue; // Prevent infinite recursion
}
if (Block(adjacentSquare, processedSquares)) {
return YES;
}
}
return NO;
};
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Square *s1, *s2;
s1 = [[Square alloc] init];
s2 = [[Square alloc] init];
s1.adjacentSquares = [NSArray arrayWithObjects:s2, nil];
s2.adjacentSquares = [NSArray arrayWithObjects:s1, nil];
__block NSMutableArray *processedSquares = [NSMutableArray array];
BOOL foundNukedSquare = Block(s1, processedSquares);
printf("%d\n", foundNukedSquare);
[s1 release];
[s2 release];
[pool release];
return 0;
}
You seem to be adding squares to the array while traversing the array. I'm speaking of this line:
[processedSquares addObject:square];
Might that have to do with it? You're adding an object while traversing. I'm surprised that this works at all.