261 lines
14 KiB
Lua
261 lines
14 KiB
Lua
|
|
||
|
--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
|