| #include <stdint.h> |
| #import <Foundation/Foundation.h> |
| #import <objc/message.h> |
| #import "isolate_test.h" |
| |
| #if !__has_feature(objc_arc) |
| #error "This file must be compiled with ARC enabled" |
| #endif |
| |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wundeclared-selector" |
| |
| typedef struct { |
| int64_t version; |
| void* (*newWaiter)(void); |
| void (*awaitWaiter)(void*); |
| void* (*currentIsolate)(void); |
| void (*enterIsolate)(void*); |
| void (*exitIsolate)(void); |
| int64_t (*getMainPortId)(void); |
| bool (*getCurrentThreadOwnsIsolate)(int64_t); |
| } DOBJC_Context; |
| |
| id objc_retainBlock(id); |
| |
| #define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ |
| assert(ctx->version >= 1); \ |
| void* targetIsolate = ctx->currentIsolate(); \ |
| int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ |
| return BLOCK_SIG { \ |
| void* currentIsolate = ctx->currentIsolate(); \ |
| bool mayEnterIsolate = \ |
| currentIsolate == NULL && \ |
| ctx->getCurrentThreadOwnsIsolate != NULL && \ |
| ctx->getCurrentThreadOwnsIsolate(targetPort); \ |
| if (currentIsolate == targetIsolate || mayEnterIsolate) { \ |
| if (mayEnterIsolate) { \ |
| ctx->enterIsolate(targetIsolate); \ |
| } \ |
| INVOKE_DIRECT; \ |
| if (mayEnterIsolate) { \ |
| ctx->exitIsolate(); \ |
| } \ |
| } else { \ |
| void* waiter = ctx->newWaiter(); \ |
| INVOKE_LISTENER; \ |
| ctx->awaitWaiter(waiter); \ |
| } \ |
| }; |
| |
| |
| typedef void (^_ListenerTrampoline)(int32_t arg0); |
| __attribute__((visibility("default"))) __attribute__((used)) |
| _ListenerTrampoline _rdx59v_wrapListenerBlock_1bqef4y(_ListenerTrampoline block) NS_RETURNS_RETAINED { |
| return ^void(int32_t arg0) { |
| objc_retainBlock(block); |
| block(arg0); |
| }; |
| } |
| |
| typedef void (^_BlockingTrampoline)(void * waiter, int32_t arg0); |
| __attribute__((visibility("default"))) __attribute__((used)) |
| _ListenerTrampoline _rdx59v_wrapBlockingBlock_1bqef4y( |
| _BlockingTrampoline block, _BlockingTrampoline listenerBlock, |
| DOBJC_Context* ctx) NS_RETURNS_RETAINED { |
| BLOCKING_BLOCK_IMPL(ctx, ^void(int32_t arg0), { |
| objc_retainBlock(block); |
| block(nil, arg0); |
| }, { |
| objc_retainBlock(listenerBlock); |
| listenerBlock(waiter, arg0); |
| }); |
| } |
| #undef BLOCKING_BLOCK_IMPL |
| |
| #pragma clang diagnostic pop |