rsi/objc/objc_dispatch.lua

261 lines
14 KiB
Lua
Raw Permalink Normal View History

2023-08-27 12:32:38 +00:00
--Grand Central Dispatch binding by Fjölnir Ásgeirsson (c) 2012, MIT license.
--modified for luapower/objc by Cosmin Apreutesei, public domain.
--not used yet, thus not finished. the API will probably change in the future.
local ffi = require'ffi'
local objc = require'objc'
local C = ffi.C
local dispatch = {}
objc.dispatch = dispatch
ffi.cdef[[
// base.h
typedef void *dispatch_object_t;
typedef void (*dispatch_function_t)(void *);
// object.h
void dispatch_debug(dispatch_object_t object, const char *message, ...);
void dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
void dispatch_retain(dispatch_object_t object);
void dispatch_release(dispatch_object_t object);
void *dispatch_get_context(dispatch_object_t object);
void dispatch_set_context(dispatch_object_t object, void *context);
void dispatch_set_finalizer_f(dispatch_object_t object, dispatch_function_t finalizer);
void dispatch_suspend(dispatch_object_t object);
void dispatch_resume(dispatch_object_t object);
// time.h
typedef uint64_t dispatch_time_t;
dispatch_time_t dispatch_time(dispatch_time_t when, int64_t delta);
dispatch_time_t dispatch_walltime(const struct timespec *when, int64_t delta);
// queue.h
typedef struct dispatch_queue_s *dispatch_queue_t;
typedef struct dispatch_queue_attr_s *dispatch_queue_attr_t;
typedef long dispatch_queue_priority_t;
struct dispatch_queue_s _dispatch_main_q;
struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent;
typedef id dispatch_block_t;
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_async_f(dispatch_queue_t queue, void *context, dispatch_function_t work);
void dispatch_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work);
void dispatch_apply_f(size_t iterations, dispatch_queue_t queue, void *context, void (*work)(void *, size_t));
dispatch_queue_t dispatch_get_current_queue(void);
dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority, unsigned long flags);
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
const char *dispatch_queue_get_label(dispatch_queue_t queue);
void dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t queue);
void dispatch_main(void);
void dispatch_after_f(dispatch_time_t when, dispatch_queue_t queue, void *context, dispatch_function_t work);
void dispatch_barrier_async_f(dispatch_queue_t queue, void *context, dispatch_function_t work);
void dispatch_barrier_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work);
void dispatch_queue_set_specific(dispatch_queue_t queue, const void *key, void *context, dispatch_function_t destructor);
void *dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);
void *dispatch_get_specific(const void *key);
// source.h
typedef struct dispatch_source_s *dispatch_source_t;
typedef const struct dispatch_source_type_s *dispatch_source_type_t;
typedef unsigned long dispatch_source_mach_send_flags_t;
typedef unsigned long dispatch_source_proc_flags_t;
typedef unsigned long dispatch_source_vnode_flags_t;
const struct dispatch_source_type_s _dispatch_source_type_data_add;
const struct dispatch_source_type_s _dispatch_source_type_data_or;
const struct dispatch_source_type_s _dispatch_source_type_mach_send;
const struct dispatch_source_type_s _dispatch_source_type_mach_recv;
const struct dispatch_source_type_s _dispatch_source_type_proc;
const struct dispatch_source_type_s _dispatch_source_type_read;
const struct dispatch_source_type_s _dispatch_source_type_signal;
const struct dispatch_source_type_s _dispatch_source_type_timer;
const struct dispatch_source_type_s _dispatch_source_type_vnode;
const struct dispatch_source_type_s _dispatch_source_type_write;
dispatch_source_t dispatch_source_create(dispatch_source_type_t type, uintptr_t handle,
unsigned long mask, dispatch_queue_t queue);
void dispatch_source_set_event_handler_f(dispatch_source_t source, dispatch_function_t handler);
void dispatch_source_set_cancel_handler_f(dispatch_source_t source, dispatch_function_t cancel_handler);
void dispatch_source_cancel(dispatch_source_t source);
long dispatch_source_testcancel(dispatch_source_t source);
uintptr_t dispatch_source_get_handle(dispatch_source_t source);
unsigned long dispatch_source_get_mask(dispatch_source_t source);
unsigned long dispatch_source_get_data(dispatch_source_t source);
void dispatch_source_merge_data(dispatch_source_t source, unsigned long value);
void
dispatch_source_set_timer(dispatch_source_t source, dispatch_time_t start, uint64_t interval, uint64_t leeway);
void dispatch_source_set_registration_handler_f(dispatch_source_t source, dispatch_function_t registration_handler);
// group.h
typedef struct dispatch_group_s *dispatch_group_t;
dispatch_group_t dispatch_group_create(void);
void dispatch_group_async_f(dispatch_group_t group, dispatch_queue_t queue, void *context, dispatch_function_t work);
long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
void dispatch_group_notify_f(dispatch_group_t group, dispatch_queue_t queue, void *context, dispatch_function_t work);
void dispatch_group_enter(dispatch_group_t group);
void dispatch_group_leave(dispatch_group_t group);
// semaphore.h
typedef struct dispatch_semaphore_s *dispatch_semaphore_t;
dispatch_semaphore_t dispatch_semaphore_create(long value);
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
// once.h
typedef long dispatch_once_t;
void dispatch_once_f(dispatch_once_t *predicate, void *context, dispatch_function_t function);
// data.h (Requires blocks for all of it's functionality, see http://github.com/aptiva/tlc if you need it)
typedef struct dispatch_data_s *dispatch_data_t;
struct dispatch_data_s _dispatch_data_empty;
// io.h (Requires blocks for all of it's functionality, see http://github.com/aptiva/tlc if you need it)
typedef int dispatch_fd_t;
]]
-- Types
dispatch.object_t = ffi.typeof'dispatch_object_t'
dispatch.function_t = ffi.typeof'dispatch_function_t'
dispatch.time_t = ffi.typeof'dispatch_time_t'
dispatch.queue_t = ffi.typeof'dispatch_queue_t'
dispatch.queue_attr_t = ffi.typeof'dispatch_queue_attr_t'
dispatch.queue_priority_t = ffi.typeof'dispatch_queue_priority_t'
dispatch.source_t = ffi.typeof'dispatch_source_t'
dispatch.source_type_t = ffi.typeof'dispatch_source_type_t'
dispatch.source_mach_send_flags_t = ffi.typeof'dispatch_source_mach_send_flags_t'
dispatch.source_proc_flags_t = ffi.typeof'dispatch_source_proc_flags_t'
dispatch.source_vnode_flags_t = ffi.typeof'dispatch_source_vnode_flags_t'
dispatch.group_t = ffi.typeof'dispatch_group_t'
dispatch.semaphore_t = ffi.typeof'dispatch_semaphore_t'
dispatch.once_ = ffi.typeof'dispatch_once_t'
dispatch.data_t = ffi.typeof'dispatch_data_t'
dispatch.fd_t = ffi.typeof'dispatch_fd_t'
if ffi.os ~= 'OSX' then
error('platform not OSX', 2)
end
-- Contants
dispatch.emptyData = ffi.cast(dispatch.data_t, C._dispatch_data_empty)
dispatch.defaultDataDestructor = nil
dispatch.nsecPerSec = 1000000000ULL
dispatch.nsecPerMsec = 1000000ULL
dispatch.usecPerSec = 1000000ULL
dispatch.nsecPerUsec = 1000ULL
dispatch.timeNow = 0
dispatch.timeForever = bit.bnot(0)
objc.DISPATCH_QUEUE_PRIORITY_HIGH = ffi.cast(dispatch.queue_priority_t, 2)
objc.DISPATCH_QUEUE_PRIORITY_DEFAULT = ffi.cast(dispatch.queue_priority_t, 0)
objc.DISPATCH_QUEUE_PRIORITY_LOW = ffi.cast(dispatch.queue_priority_t, -2)
objc.DISPATCH_QUEUE_PRIORITY_BACKGROUND = ffi.cast(dispatch.queue_priority_t, -32768) -- INT16_MIN
dispatch.main_queue = C._dispatch_main_q
dispatch.serialQueueAttr = nil
dispatch.queue_attr_concurrent = C._dispatch_queue_attr_concurrent
dispatch.defaultTargetQueue = nil
dispatch.machSendDead = ffi.cast(dispatch.source_proc_flags_t, 0x1)
dispatch.procExit = ffi.cast(dispatch.source_proc_flags_t, 0x80000000)
dispatch.procFork = ffi.cast(dispatch.source_proc_flags_t, 0x40000000)
dispatch.procExec = ffi.cast(dispatch.source_proc_flags_t, 0x20000000)
dispatch.procSignal = ffi.cast(dispatch.source_proc_flags_t, 0x08000000)
dispatch.sourceTypeDataAdd = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_data_add)
dispatch.sourceTypeDataOr = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_data_or)
dispatch.sourceTypeMachSend = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_mach_send)
dispatch.sourceTypeMachRecv = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_mach_recv)
dispatch.sourceTypeProc = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_proc)
dispatch.sourceTypeRead = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_read)
dispatch.sourceTypeSignal = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_signal)
dispatch.sourceTypeTimer = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_timer)
dispatch.sourceTypeVnode = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_vnode)
dispatch.sourceTypeWrite = ffi.cast(dispatch.source_type_t, C._dispatch_source_type_write)
dispatch.vNodeDelete = ffi.cast(dispatch.source_vnode_flags_t, 0x1)
dispatch.vNodeWrite = ffi.cast(dispatch.source_vnode_flags_t, 0x2)
dispatch.vNodeExtend = ffi.cast(dispatch.source_vnode_flags_t, 0x4)
dispatch.vNodeAttrib = ffi.cast(dispatch.source_vnode_flags_t, 0x8)
dispatch.vNodeLink = ffi.cast(dispatch.source_vnode_flags_t, 0x10)
dispatch.vNodeRename = ffi.cast(dispatch.source_vnode_flags_t, 0x20)
dispatch.vNodeRevoke = ffi.cast(dispatch.source_vnode_flags_t, 0x40)
-- Functions
dispatch.debug = C.dispatch_debug
dispatch.debugv = C.dispatch_debugv
dispatch.retain = C.dispatch_retain
dispatch.release = C.dispatch_release
dispatch.dispatch_get_context = C.dispatch_get_context
dispatch.set_context = C.dispatch_set_context
dispatch.set_finalizer = C.dispatch_set_finalizer_f
dispatch.suspend = C.dispatch_suspend
dispatch.resume = C.dispatch_resume
dispatch.time = C.dispatch_time
dispatch.walltime = C.dispatch_walltime
dispatch.async_f = C.dispatch_async_f
dispatch.sync_f = C.dispatch_sync_f
dispatch.apply = C.dispatch_apply_f
dispatch.get_current_queue = C.dispatch_get_current_queue
dispatch.get_global_queue = C.dispatch_get_global_queue
dispatch.queue_create = C.dispatch_queue_create
dispatch.dispatch_queue_get_label = C.dispatch_queue_get_label
dispatch.set_target_queue = C.dispatch_set_target_queue
dispatch.main = C.dispatch_main
dispatch.after = C.dispatch_after_f
dispatch.barrier_async = C.dispatch_barrier_async_f
dispatch.barrier_sync = C.dispatch_barrier_sync_f
dispatch.queue_set_specific = C.dispatch_queue_set_specific
dispatch.dispatch_queue_get_specific = C.dispatch_queue_get_specific
dispatch.dispatch_get_specific = C.dispatch_get_specific
dispatch.source_create = C.dispatch_source_create
dispatch.source_set_event_handler = C.dispatch_source_set_event_handler_f
dispatch.source_set_cancel_handler = C.dispatch_source_set_cancel_handler_f
dispatch.source_cancel = C.dispatch_source_cancel
dispatch.source_testcancel = C.dispatch_source_testcancel
dispatch.source_get_handle = C.dispatch_source_get_handle
dispatch.source_get_mask = C.dispatch_source_get_mask
dispatch.source_get_data = C.dispatch_source_get_data
dispatch.source_merge_data = C.dispatch_source_merge_data
dispatch.source_set_timer = C.dispatch_source_set_timer
dispatch.source_set_registration_handler = C.dispatch_source_set_registration_handler_f
dispatch.group_create = C.dispatch_group_create
dispatch.group_async = C.dispatch_group_async_f
dispatch.group_wait = C.dispatch_group_wait
dispatch.group_notify = C.dispatch_group_notify_f
dispatch.group_enter = C.dispatch_group_enter
dispatch.group_leave = C.dispatch_group_leave
dispatch.semaphore_create = C.dispatch_semaphore_create
dispatch.semaphore_wait = C.dispatch_semaphore_wait
dispatch.semaphore_signal = C.dispatch_semaphore_signal
dispatch.once = C.dispatch_once_f
dispatch.DISPATCH_QUEUE_SERIAL = nil
--note: do not use with queues that call back from a different thread!
function dispatch.async(queue, block)
C.dispatch_async(queue, objc.block(block))
end
jit.off(dispatch.async)
function dispatch.sync(queue, block)
C.dispatch_sync(queue, objc.block(block))
end
return dispatch