// // PSDefines.m // Perforce // // Created by Adam Czubernat on 07.05.2013. // Copyright (c) 2013 Perforce Software, Inc. All rights reserved. // #import "PSDefines.h" // Constant strings NSString * const PSException = @"Perforce Exception"; NSString * const PSDomain = @"com.perforce"; // Queue definitions const char * PSDispatchGlobalQueueLabel = "com.perforce.globalQueue"; dispatch_queue_t PSDispatchGlobalQueue = NULL; static dispatch_once_t PSDispatchOnceToken; // Queue invocations count static int PSDispatchGlobalQueueWaiting = 0; static int PSDispatchMainQueueWaiting = 0; void PSDispatchInBackgroundThreadAndWait(dispatch_block_t block); // Logging NSString * const PSDebugLogNotification = @"PSDebugLogNotification"; static NSMutableArray *_PSLogBuffer; static int _PSLogBufferSize = 128; static int _PSLogBufferPointer; static NSMutableDictionary *_PSLogStorage; void _PSDebugLogSave(NSString *path, NSString *header); // Crash handling private void _PSDebugCrash(NSString *description, NSArray *callstack); void _PSDebugExceptionCallback(NSException *exception); void _PSDebugSignalCallback(int signal); #pragma mark - GCD void PSDispatchInBackgroundThread(dispatch_block_t block) { dispatch_once(&PSDispatchOnceToken, ^{ PSDispatchGlobalQueue = dispatch_queue_create(PSDispatchGlobalQueueLabel, NULL); }); dispatch_async(PSDispatchGlobalQueue, block); } void PSDispatchInMainThread(dispatch_block_t block) { PSDispatchMainQueueWaiting++; if (dispatch_get_current_queue() == dispatch_get_main_queue()) { // PSLogf(@"Already in main queue: performing block in-place"); block(); // Already in main queue: performing block in-place } else { if (PSDispatchGlobalQueueWaiting > 0) PSLogf(@"Possible deadlock"); dispatch_sync(dispatch_get_main_queue(), block); } PSDispatchMainQueueWaiting--; } extern void PSDispatchAfter(NSTimeInterval interval, dispatch_block_t block) { dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC); dispatch_after(time, dispatch_get_main_queue(), block); } void PSDispatchInBackgroundThreadAndWait(dispatch_block_t block) { PSDispatchGlobalQueueWaiting++; if (dispatch_get_current_queue() == PSDispatchGlobalQueue) { PSLogf(@"Already in background queue: performing block in-place"); block(); } else { dispatch_once(&PSDispatchOnceToken, ^{ PSDispatchGlobalQueue = dispatch_queue_create(PSDispatchGlobalQueueLabel, NULL); }); if (PSDispatchMainQueueWaiting > 0) PSLogf(@"Possible deadlock"); dispatch_sync(PSDispatchGlobalQueue, block); } PSDispatchGlobalQueueWaiting--; } PSTimeStamp PSTimeStampMake(void) { return CACurrentMediaTime(); } NSTimeInterval PSTimeInterval(PSTimeStamp timestamp) { return CACurrentMediaTime() - timestamp; } #pragma mark - Runtime NSDictionary * PSRuntimeIvarsForClass(Class class) { NSMutableDictionary *ivarsDict = [NSMutableDictionary dictionary]; unsigned int count; Ivar *ivars = class_copyIvarList(class, &count); for(int i=0; i