123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- package objc_Foundation
- import "base:intrinsics"
- import "base:builtin"
- import "core:mem"
- @(objc_class="NSBlock")
- Block :: struct {using _: Object}
- @(objc_type=Block, objc_name="createGlobal", objc_is_class_method=true)
- Block_createGlobal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error {
- return Block_createInternal(true, user_data, user_proc, allocator)
- }
- @(objc_type=Block, objc_name="createLocal", objc_is_class_method=true)
- Block_createLocal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr)) -> ^Block {
- b, _ := Block_createInternal(false, user_data, user_proc, {})
- return b
- }
- @(objc_type=Block, objc_name="createGlobalWithParam", objc_is_class_method=true)
- Block_createGlobalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error {
- return Block_createInternalWithParam(true, user_data, user_proc, allocator)
- }
- @(objc_type=Block, objc_name="createLocalWithParam", objc_is_class_method=true)
- Block_createLocalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T)) -> ^Block {
- b, _ := Block_createInternalWithParam(false, user_data, user_proc, {})
- return b
- }
- @(private)
- Internal_Block_Literal_Base :: struct {
- isa: ^intrinsics.objc_class,
- flags: u32,
- reserved: u32,
- invoke: rawptr, // contains a pointer to a proc "c" (^Internal_Block_Literal, ...)
- descriptor: ^Block_Descriptor,
- }
- @(private)
- Internal_Block_Literal :: struct {
- using base: Internal_Block_Literal_Base,
- // Imported Variables
- user_proc: rawptr, // contains a pointer to a proc "c" (user_data: rawptr, ...)
- user_data: rawptr,
- }
- @(private)
- Block_Descriptor :: struct {
- reserved: uint,
- size: uint,
- copy_helper: proc "c" (dst, src: rawptr),
- dispose_helper: proc "c" (src: rawptr),
- signature: cstring,
- }
- @(private)
- global_block_descriptor := Block_Descriptor{
- reserved = 0,
- size = size_of(Internal_Block_Literal),
- }
- foreign import libSystem "system:System.framework"
- foreign libSystem {
- _NSConcreteGlobalBlock: intrinsics.objc_class
- _NSConcreteStackBlock: intrinsics.objc_class
- }
- @(private="file")
- internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr, allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
- _init :: proc(bl: ^Internal_Block_Literal, is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr) {
- // Set to true on blocks that have captures (and thus are not true
- // global blocks) but are known not to escape for various other
- // reasons. For backward compatibility with old runtimes, whenever
- // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
- // non-escaping block returns the original block and releasing such a
- // block is a no-op, which is exactly how global blocks are handled.
- BLOCK_IS_NOESCAPE :: (1 << 23)|BLOCK_IS_GLOBAL
- BLOCK_HAS_COPY_DISPOSE :: 1 << 25
- BLOCK_HAS_CTOR :: 1 << 26 // helpers have C++ code
- BLOCK_IS_GLOBAL :: 1 << 28
- BLOCK_HAS_STRET :: 1 << 29 // IFF BLOCK_HAS_SIGNATURE
- BLOCK_HAS_SIGNATURE :: 1 << 30
- bl.isa = is_global ? &_NSConcreteGlobalBlock : &_NSConcreteStackBlock
- bl.flags = BLOCK_IS_GLOBAL if is_global else 0
- bl.invoke = invoke
- bl.descriptor = &global_block_descriptor
- bl.user_proc = auto_cast user_proc
- bl.user_data = user_data
- }
- if is_global {
- bl := builtin.new (Internal_Block_Literal, allocator) or_return
- _init(bl, true, user_data, user_proc, invoke)
- return auto_cast bl, .None
- } else {
- // malloc blocks are created by calling 'copy' on a stack block
- bl: Internal_Block_Literal
- _init(&bl, false, user_data, user_proc, invoke)
- return auto_cast copy(cast(^Copying(Block))(&bl)), .None
- }
- }
- @(private="file")
- Block_createInternal :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
- invoke :: proc "c" (bl: ^Internal_Block_Literal) {
- user_proc := (proc "c" (rawptr))(bl.user_proc)
- user_proc(bl.user_data)
- }
- return internal_block_literal_make(is_global, user_data, auto_cast user_proc, auto_cast invoke, allocator)
- }
- @(private="file")
- Block_createInternalWithParam :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
- invoke :: proc "c" (bl: ^Internal_Block_Literal, t: T) {
- user_proc := (proc "c" (rawptr, T))(bl.user_proc)
- user_proc(bl.user_data, t)
- }
- return internal_block_literal_make(is_global, user_data, auto_cast user_proc, auto_cast invoke, allocator)
- }
|