Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion iphone/TitaniumKit/TitaniumKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

/* Begin PBXBuildFile section */
4A175276218B64E70094C7B6 /* KrollTimerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A175274218B64E70094C7B6 /* KrollTimerManager.h */; };
4A175277218B64E70094C7B6 /* KrollTimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A175275218B64E70094C7B6 /* KrollTimerManager.m */; };
4A175277218B64E70094C7B6 /* KrollTimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A175275218B64E70094C7B6 /* KrollTimerManager.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
4A1FF4432523262A00A0F923 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A1FF4422523262A00A0F923 /* ErrorView.swift */; };
B106A6FD24535CB800B1305E /* JSValue+Addons.h in Headers */ = {isa = PBXBuildFile; fileRef = B106A6FB24535CB800B1305E /* JSValue+Addons.h */; settings = {ATTRIBUTES = (Public, ); }; };
B106A6FE24535CB800B1305E /* JSValue+Addons.m in Sources */ = {isa = PBXBuildFile; fileRef = B106A6FC24535CB800B1305E /* JSValue+Addons.m */; };
Expand Down
31 changes: 17 additions & 14 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/Mimetypes.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,24 @@

const NSString *svgMimeType = @"image/svg+xml";

static NSDictionary *mimeTypeFromExtensionDict = nil;
static NSDictionary *MimeTypesDict(void)
{
static NSDictionary *dict = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// This dictionary contains info on mimetypes currently missing on iOS platform.
dict = [[NSDictionary alloc] initWithObjectsAndKeys:
@"text/css", @"css",
@"video/x-m4v", @"m4v",
nil];
});
return dict;
}

@implementation Mimetypes

+ (void)initialize
{
// This dictionary contains info on mimetypes surrently missing on IOS platform.
// This should be updated on a case by case basis.
if (mimeTypeFromExtensionDict == nil) {
mimeTypeFromExtensionDict = [[NSDictionary alloc] initWithObjectsAndKeys:
@"text/css", @"css",
@"video/x-m4v", @"m4v",
nil];
}
}

+ (NSString *)extensionForMimeType:(NSString *)mimetype
Expand All @@ -40,9 +44,9 @@ + (NSString *)extensionForMimeType:(NSString *)mimetype

if (extension == NULL) {
// Missing info is retrieved from dictionary
[Mimetypes initialize];
for (NSString *key in mimeTypeFromExtensionDict) {
NSString *value = [mimeTypeFromExtensionDict objectForKey:key];
NSDictionary *extra = MimeTypesDict();
for (NSString *key in extra) {
NSString *value = [extra objectForKey:key];
if ([value isEqualToString:mimetype]) {
return key;
}
Expand All @@ -67,8 +71,7 @@ + (NSString *)mimeTypeForExtension:(NSString *)ext

if (mimetype == NULL) {
// Missing info is retrieved from dictionary
[Mimetypes initialize];
NSString *result = [mimeTypeFromExtensionDict objectForKey:[ext pathExtension]];
NSString *result = [MimeTypesDict() objectForKey:[ext pathExtension]];

if (result == nil)
result = @"application/octet-stream";
Expand Down
8 changes: 5 additions & 3 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/OperationQueue.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#import "OperationQueue.h"
#import "TiBase.h"

OperationQueue *sharedQueue = nil;
// Use dispatch_once to ensure thread-safe, one-time singleton init.
static OperationQueue *sharedQueue = nil;

@interface OperationQueueOp : NSOperation {
SEL selector;
Expand Down Expand Up @@ -93,9 +94,10 @@ - (void)dealloc

+ (OperationQueue *)sharedQueue
{
if (sharedQueue == nil) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedQueue = [[OperationQueue alloc] init];
}
});
return sharedQueue;
}

Expand Down
86 changes: 42 additions & 44 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiLayoutQueue.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,61 +10,35 @@
#import "TiLayoutQueue.h"
#import "TiViewProxy.h"
#import <CoreFoundation/CoreFoundation.h>
#import <pthread.h>
#import <dispatch/dispatch.h>
#import <os/lock.h>

#define LAYOUT_TIMER_INTERVAL 0.05
#define LAYOUT_START_INTERVAL 0.01

NSMutableArray *layoutArray = nil;
CFRunLoopTimerRef layoutTimer = NULL;
pthread_mutex_t layoutMutex;

void performLayoutRefresh(CFRunLoopTimerRef timer, void *info)
{
NSArray *localLayoutArray = nil;

// This prevents deadlock if, while laying out, a relayout is requested
// (as in the case of redrawing text in a reproxy)
pthread_mutex_lock(&layoutMutex);
localLayoutArray = layoutArray;
layoutArray = nil;

if ((layoutTimer != NULL) && ([localLayoutArray count] == 0)) {
// Might as well stop the timer for now.
CFRunLoopTimerInvalidate(layoutTimer);
CFRelease(layoutTimer);
layoutTimer = NULL;
}

pthread_mutex_unlock(&layoutMutex);

for (TiViewProxy *thisProxy in localLayoutArray) {
[TiLayoutQueue layoutProxy:thisProxy];
}

RELEASE_TO_NIL(localLayoutArray);
}
static NSMutableArray *layoutArray = nil;
static dispatch_source_t layoutTimer = NULL;
static os_unfair_lock layoutLock = OS_UNFAIR_LOCK_INIT;

@implementation TiLayoutQueue

+ (void)initialize
{
pthread_mutex_init(&layoutMutex, NULL);
// nothing to initialize; layoutLock is static-initialized
}

+ (void)resetQueue
{
pthread_mutex_lock(&layoutMutex);
os_unfair_lock_lock(&layoutLock);
[layoutArray release];
layoutArray = nil;

if (layoutTimer != NULL) {
CFRunLoopTimerInvalidate(layoutTimer);
CFRelease(layoutTimer);
dispatch_source_cancel(layoutTimer);
layoutTimer = NULL;
}

pthread_mutex_unlock(&layoutMutex);
os_unfair_lock_unlock(&layoutLock);
}

+ (void)layoutProxy:(TiViewProxy *)thisProxy
Expand All @@ -78,12 +52,12 @@ + (void)layoutProxy:(TiViewProxy *)thisProxy

+ (void)addViewProxy:(TiViewProxy *)newViewProxy
{
pthread_mutex_lock(&layoutMutex);
os_unfair_lock_lock(&layoutLock);

if (layoutArray == nil) {
layoutArray = [[NSMutableArray alloc] initWithObjects:newViewProxy, nil];
} else if ([layoutArray containsObject:newViewProxy]) { // Nothing to do here. Already added.
pthread_mutex_unlock(&layoutMutex);
os_unfair_lock_unlock(&layoutLock);
return;
} else if ([layoutArray containsObject:[newViewProxy parent]]) { // For safety reasons, we do add this to the list. But since the parent's already here,
// We add it to the FIRST so that children draw before parents, giving us good layout values for later!
Expand All @@ -94,14 +68,38 @@ + (void)addViewProxy:(TiViewProxy *)newViewProxy
}

if (layoutTimer == NULL) {
layoutTimer = CFRunLoopTimerCreate(NULL,
CFAbsoluteTimeGetCurrent() + LAYOUT_START_INTERVAL,
LAYOUT_TIMER_INTERVAL,
0, 0, performLayoutRefresh, NULL);
CFRunLoopAddTimer(CFRunLoopGetMain(), layoutTimer, kCFRunLoopCommonModes);
// create GCD timer on main queue to coalesce layout flushes
dispatch_queue_t queue = dispatch_get_main_queue();
layoutTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
uint64_t startNsec = (uint64_t)(LAYOUT_START_INTERVAL * NSEC_PER_SEC);
uint64_t intervalNsec = (uint64_t)(LAYOUT_TIMER_INTERVAL * NSEC_PER_SEC);
dispatch_source_set_timer(layoutTimer,
dispatch_time(DISPATCH_TIME_NOW, startNsec),
intervalNsec,
(uint64_t)(0.001 * NSEC_PER_SEC)); // 1ms leeway

dispatch_source_set_event_handler(layoutTimer, ^{
NSArray *localLayoutArray = nil;
os_unfair_lock_lock(&layoutLock);
localLayoutArray = layoutArray;
layoutArray = nil;
BOOL shouldStop = (localLayoutArray == nil) || ([localLayoutArray count] == 0);
os_unfair_lock_unlock(&layoutLock);

for (TiViewProxy *thisProxy in localLayoutArray) {
[TiLayoutQueue layoutProxy:thisProxy];
}
RELEASE_TO_NIL(localLayoutArray);

if (shouldStop) {
// no queued work: stop timer to save cycles
dispatch_source_cancel(layoutTimer);
layoutTimer = NULL;
}
});
dispatch_resume(layoutTimer);
}

pthread_mutex_unlock(&layoutMutex);
os_unfair_lock_unlock(&layoutLock);
}

@end
Expand Down
12 changes: 6 additions & 6 deletions iphone/TitaniumKit/TitaniumKit/Sources/Kroll/KrollCallback.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
#import "KrollBridge.h"
#import "KrollObject.h"
#import "TiExceptionHandler.h"
#import <os/lock.h>

static NSMutableArray *callbacks;
static NSLock *callbackLock;
static os_unfair_lock callbackLock = OS_UNFAIR_LOCK_INIT;

@interface KrollCallback ()
@property (nonatomic, assign) KrollContext *context;
Expand All @@ -22,19 +23,18 @@ @implementation KrollCallback

+ (void)shutdownContext:(KrollContext *)context
{
[callbackLock lock];
os_unfair_lock_lock(&callbackLock);
for (KrollCallback *callback in callbacks) {
if ([callback context] == context) {
callback.context = nil;
}
}
[callbackLock unlock];
os_unfair_lock_unlock(&callbackLock);
}

+ (void)initialize
{
if (callbacks == nil) {
callbackLock = [[NSLock alloc] init];
callbacks = TiCreateNonRetainingArray();
}
}
Expand All @@ -56,9 +56,9 @@ - (id)initWithCallback:(JSValueRef)function_ thisObject:(JSObjectRef)thisObject_

- (void)dealloc
{
[callbackLock lock];
os_unfair_lock_lock(&callbackLock);
[callbacks removeObject:self];
[callbackLock unlock];
os_unfair_lock_unlock(&callbackLock);

[type release];
if ([KrollBridge krollBridgeExists:bridge]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/**
* The method that will be triggered when a timer fires.
*/
- (void)timerFired:(nonnull NSTimer *)timer;
- (void)timerFired:(nullable NSTimer *)timer;

@end

Expand All @@ -38,9 +38,10 @@
@interface KrollTimerManager : NSObject

/**
* Map of timer identifiers and the underlying native NSTimer.
* Map of timer identifiers to the underlying native timer objects.
* Backed by GCD timers for lower overhead and better accuracy.
*/
@property (nonatomic, strong, nullable) NSMapTable<NSNumber *, NSTimer *> *timers;
@property (nonatomic, strong, nullable) NSMapTable<NSNumber *, id> *timers;

/**
* Initializes the timer manager in the given JS context. Exposes the global set/clear
Expand Down
Loading
Loading