91 lines
2.4 KiB
Objective-C
91 lines
2.4 KiB
Objective-C
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <Foundation/NSDate.h>
|
|
#import <Foundation/NSThread.h>
|
|
#import <dispatch/dispatch.h>
|
|
|
|
#include "ffi.h"
|
|
#include "include/dart_api_dl.h"
|
|
#include "os_version.h"
|
|
|
|
_Atomic bool _mainThreadIsListening = false;
|
|
|
|
FFI_EXPORT intptr_t DOBJC_initializeApi(void* data) {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
_mainThreadIsListening = true;
|
|
});
|
|
return Dart_InitializeApiDL(data);
|
|
}
|
|
|
|
FFI_EXPORT void DOBJC_runOnMainThread(void (*fn)(void *), void *arg) {
|
|
if (!_mainThreadIsListening || [NSThread isMainThread]) {
|
|
fn(arg);
|
|
} else {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
fn(arg);
|
|
});
|
|
}
|
|
}
|
|
|
|
@interface DOBJCWaiter : NSObject {}
|
|
@property(strong) NSCondition* cond;
|
|
@property bool done;
|
|
-(void)signal;
|
|
-(void)wait;
|
|
@end
|
|
|
|
@implementation DOBJCWaiter
|
|
-(instancetype)init {
|
|
if (self) {
|
|
_cond = [[NSCondition alloc] init];
|
|
_done = false;
|
|
}
|
|
return self;
|
|
}
|
|
-(void)signal {
|
|
[_cond lock];
|
|
_done = true;
|
|
[_cond signal];
|
|
[_cond unlock];
|
|
}
|
|
-(void)wait {
|
|
[_cond lock];
|
|
while (!_done) {
|
|
[_cond wait];
|
|
}
|
|
[_cond unlock];
|
|
}
|
|
@end
|
|
|
|
FFI_EXPORT void* DOBJC_newWaiter(void) {
|
|
DOBJCWaiter* w = [[DOBJCWaiter alloc] init];
|
|
// __bridge_retained increments the ref count, __bridge_transfer decrements
|
|
// it, and __bridge doesn't change it. One of the __bridge_retained calls is
|
|
// balanced by the __bridge_transfer in signalWaiter, and the other is
|
|
// balanced by the one in awaitWaiter. In other words, this function returns
|
|
// an object with a +2 ref count, and signal and await each decrement the
|
|
// ref count.
|
|
return (__bridge_retained void*)(__bridge id)(__bridge_retained void*)(w);
|
|
}
|
|
|
|
FFI_EXPORT void DOBJC_signalWaiter(void* waiter) {
|
|
if (waiter) [(__bridge_transfer DOBJCWaiter*)waiter signal];
|
|
}
|
|
|
|
FFI_EXPORT void DOBJC_awaitWaiter(void* waiter) {
|
|
[(__bridge_transfer DOBJCWaiter*)waiter wait];
|
|
}
|
|
|
|
FFI_EXPORT Version DOBJC_getOsVesion(void) {
|
|
NSOperatingSystemVersion objc_version =
|
|
[[NSProcessInfo processInfo] operatingSystemVersion];
|
|
Version c_version;
|
|
c_version.major = (int)objc_version.majorVersion;
|
|
c_version.minor = (int)objc_version.minorVersion;
|
|
c_version.patch = (int)objc_version.patchVersion;
|
|
return c_version;
|
|
}
|