Move toydispatch into libobjc2.

Some build system tidies.

Add -retain / release to Protocol.

Initial work on clang-specific makefile.
main
theraven 15 years ago
parent b5f4782dbf
commit a83428b883

@ -9,9 +9,6 @@ include $(GNUSTEP_MAKEFILES)/common.make
LIBRARY_NAME = libobjc LIBRARY_NAME = libobjc
SUBPROJECTS = toydispatch
libobjc_VERSION = 4 libobjc_VERSION = 4
libobjc_OBJC_FILES = \ libobjc_OBJC_FILES = \
@ -40,7 +37,8 @@ libobjc_C_FILES = \
sarray2.c\ sarray2.c\
selector_table.c\ selector_table.c\
sendmsg2.c\ sendmsg2.c\
statics_loader.c statics_loader.c\
toydispatch.c
ifneq ($(enable_legacy), no) ifneq ($(enable_legacy), no)
libobjc_C_FILES += legacy_malloc.c libobjc_C_FILES += legacy_malloc.c
@ -60,14 +58,15 @@ libobjc_HEADER_FILES = \
runtime.h\ runtime.h\
slot.h\ slot.h\
objc.h\ objc.h\
objc-api.h objc-api.h\
toydispatch.h
endif endif
ifneq ($(tdd), no) ifneq ($(tdd), no)
libobjc_CPPFLAGS += -DTYPE_DEPENDENT_DISPATCH libobjc_CPPFLAGS += -DTYPE_DEPENDENT_DISPATCH
endif endif
libobjc_LIBRARIES_DEPEND_UPON += -lpthread -ltoydispatch libobjc_LIBRARIES_DEPEND_UPON += -lpthread
# Deprecated functions are only deprecated for external use, not for us because # Deprecated functions are only deprecated for external use, not for us because
# we are special, precious, little flowers. # we are special, precious, little flowers.
@ -75,9 +74,9 @@ libobjc_CPPFLAGS += -D__OBJC_RUNTIME_INTERNAL__=1 -D_XOPEN_SOURCE=500
# Note to Riccardo. Please do not 'fix' C99isms in this. The new ABI is only # Note to Riccardo. Please do not 'fix' C99isms in this. The new ABI is only
# useful on compilers that support C99 (currently only clang), so there is no # useful on compilers that support C99 (currently only clang), so there is no
# benefit from supporting platforms with no C99 compiler. # benefit from supporting platforms with no C99 compiler.
libobjc_CFLAGS += -std=c99 -g -fexceptions -fno-inline libobjc_CFLAGS += -std=c99 -g -fexceptions #-fvisibility=hidden
libobjc_OBJCFLAGS += $(libobjc_CFLAGS) libobjc_OBJCFLAGS += $(libobjc_CFLAGS) $(libobjc_CFLAGS)
libobjc_LDFLAGS += -g libobjc_LDFLAGS += -g
libobjc_LIB_DIRS += -L toydispatch/obj libobjc_LIB_DIRS += -L toydispatch/obj
libobjc_CFLAGS += -O3 libobjc_CFLAGS += -O3

@ -5,7 +5,7 @@ VERSION = 4
#CC=clang #CC=clang
CFLAGS += -std=c99 -fPIC CFLAGS += -std=c99 -fPIC
CPPFLAGS += -DTYPE_DEPENDENT_DISPATCH CPPFLAGS += -DTYPE_DEPENDENT_DISPATCH -DGNUSTEP
CPPFLAGS += -D__OBJC_RUNTIME_INTERNAL__=1 -D_XOPEN_SOURCE=500 CPPFLAGS += -D__OBJC_RUNTIME_INTERNAL__=1 -D_XOPEN_SOURCE=500
PREFIX?= /usr/local PREFIX?= /usr/local

@ -0,0 +1,79 @@
.POSIX:
.SUFFIXES: .c .bc .m
VERSION = 4
#CC=clang
CFLAGS += -fPIC
CPPFLAGS += -DTYPE_DEPENDENT_DISPATCH -DGNUSTEP
CPPFLAGS += -D__OBJC_RUNTIME_INTERNAL__=1 -D_XOPEN_SOURCE=500
PREFIX?= /usr/local
LIB_DIR= ${PREFIX}/lib
HEADER_DIR= ${PREFIX}/include
OBJECTS = \
NSBlocks.bc\
Protocol2.bc\
abi_version.bc\
blocks_runtime.bc\
caps.bc\
category_loader.bc\
class_table.bc\
dtable.bc\
eh_personality.bc\
encoding2.bc\
hash_table.bc\
hooks.bc\
ivar.bc\
legacy_malloc.bc\
loader.bc\
mutation.bc\
properties.bc\
protocol.bc\
runtime.bc\
sarray2.bc\
selector_table.bc\
sendmsg2.bc\
statics_loader.bc\
sync.bc\
toydispatch.bc
all: libobjc.so.$(VERSION) libobjc.a
libobjc.so.$(VERSION): libobjc.o
@echo Linking shared library...
@ld -shared -o $@ libobjc.o
libobjc.a: libobjc.o
@echo Linking static library...
@ld -r -s -o $@ libobjc.o
libobjc.o: libobjc.bc
llc -O3 -filetype=obj -o libobjc.o libobjc.bc
libobjc.bc: $(OBJECTS)
@echo Linking bitcode...
pwd
llvm-ld -internalize-public-api-file=../exports.txt -link-as-library -native -o libobjc.bc $(OBJECTS)
.c.bc: obj
clang $(CPPFLAGS) $(CFLAGS) -emit-llvm -c $< -o $@
.m.bc: obj
clang $(CPPFLAGS) $(CFLAGS) -emit-llvm -c $< -o $@
obj:
mkdir obj
install: all
install -m 444 libobjc.so.$(VERSION) $(LIB_DIR)
install -m 444 libobjc.a $(LIB_DIR)
ln -sf $(LIB_DIR)/libobjc.so.$(VERSION) $(LIB_DIR)/libobjc.so
install -d $(HEADER_DIR)/objc
install -m 444 objc/*.h $(HEADER_DIR)/objc
clean:
rm -f obj/*

@ -15,6 +15,11 @@
{ {
return protocol_conformsToProtocol(self, p); return protocol_conformsToProtocol(self, p);
} }
- (id)retain
{
return self;
}
- (void)release {}
@end @end
@implementation Protocol2 @implementation Protocol2
+ (void)load + (void)load

@ -29,6 +29,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <assert.h>
#define fprintf(...)
/* Makes the compiler happy even without Foundation */ /* Makes the compiler happy even without Foundation */
@interface Dummy @interface Dummy
@ -36,10 +39,24 @@
- (void)release; - (void)release;
@end @end
// Descriptor attributes static void *_HeapBlockByRef = (void*)1;
enum {
/**
* Block descriptor flags.
*/
enum block_flags
{
/**
* The block descriptor contains copy and dispose helpers.
*/
BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code /**
* The helpers have C++ code.
*/
BLOCK_HAS_CTOR = (1 << 26),
/**
* Block is stored in global memory and does not need to be copied.
*/
BLOCK_IS_GLOBAL = (1 << 28), BLOCK_IS_GLOBAL = (1 << 28),
/** /**
* Block function uses a calling convention that returns a structure via a * Block function uses a calling convention that returns a structure via a
@ -49,13 +66,36 @@ enum {
/** /**
* Block has an Objective-C type encoding. * Block has an Objective-C type encoding.
*/ */
BLOCK_HAS_SIGNATURE = (1 << 30) BLOCK_HAS_SIGNATURE = (1 << 30),
/**
* Mask for the reference count in byref structure's flags field. The low
* 3 bytes are reserved for the reference count, the top byte for the
* flags.
*/
BLOCK_REFCOUNT_MASK = 0x00ffffffff
}; };
// _Block_object_assign() and _Block_object_dispose() flag helpers. /**
enum { * Flags used in the final argument to _Block_object_assign() and
BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ... * _Block_object_dispose(). These indicate the type of copy or dispose to
BLOCK_FIELD_IS_BLOCK = 7, // a block variable * perform.
*/
enum
{
/**
* The value is of some id-like type, and should be copied as an
* Objective-C object: i.e. by sending -retain or via the GC assign
* functions in GC mode (not yet supported).
*/
BLOCK_FIELD_IS_OBJECT = 3,
/**
* The field is a block. This must be copied by the block copy functions.
*/
BLOCK_FIELD_IS_BLOCK = 7,
/**
* The field is an indirect reference to a variable declared with the
* __block storage qualifier.
*/
BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
BLOCK_FIELD_IS_WEAK = 16, // declared __weak BLOCK_FIELD_IS_WEAK = 16, // declared __weak
@ -68,6 +108,9 @@ enum {
*/ */
struct block_descriptor_copydispose struct block_descriptor_copydispose
{ {
/**
* Reserved for future use. Currently always 0.
*/
unsigned long int reserved; unsigned long int reserved;
/** Size of the block. */ /** Size of the block. */
unsigned long int size; unsigned long int size;
@ -91,6 +134,9 @@ struct block_descriptor_copydispose
*/ */
struct block_descriptor struct block_descriptor
{ {
/**
* Reserved for future use, currently always 0.
*/
unsigned long int reserved; unsigned long int reserved;
/** Size of the block. */ /** Size of the block. */
unsigned long int size; unsigned long int size;
@ -101,27 +147,86 @@ struct block_descriptor
}; };
// Helper structure // Helper structure
struct psy_block_literal { struct block_literal
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock {
/**
* Class pointer. Always initialised to &_NSConcreteStackBlock for blocks
* that are created on the stack or &_NSConcreteGlobalBlock for blocks that
* are created in global storage.
*/
void *isa;
/**
* Flags. See the block_flags enumerated type for possible values.
*/
int flags; int flags;
/**
* Reserved - always initialised to 0 by the compiler. Used for the
* reference count in this implementation.
*/
int reserved; int reserved;
/**
* The function that implements the block. The first argument is this
* structure, the subsequent arguments are the block's explicit parameters.
* If the BLOCK_USE_SRET flag is set, there is an additional hidden
* argument, which is a pointer to the space on the stack allocated to hold
* the return value.
*/
void (*invoke)(void *, ...); void (*invoke)(void *, ...);
/**
* The block's descriptor. This is either block_descriptor or
* block_descriptor_copydispose, depending on whether the
* BLOCK_HAS_COPY_DISPOSE flag is set.
*/
struct block_descriptor_copydispose *descriptor; struct block_descriptor_copydispose *descriptor;
/**
* Block variables are appended to this structure.
*/
}; };
// Helper structure /**
struct psy_block_byref_obj { * Structure used for on-stack variables that are referenced by blocks.
void *isa; // uninitialized */
struct psy_block_byref_obj *forwarding; struct block_byref_obj
{
/**
* Class pointer. Currently unused and always NULL. Could be used in the
* future to support introspection.
*/
void *isa;
/**
* The pointer to the structure that contains the real version of the data.
* All accesses go via this pointer. If an on-stack byref structure is
* copied to the heap, then its forwarding pointer should point to the heap
* version. Otherwise it should point to itself.
*/
struct block_byref_obj *forwarding;
/**
* Flags and reference count.
*/
int flags; //refcount; int flags; //refcount;
/**
* Size of this structure.
*/
int size; int size;
void (*byref_keep)(struct psy_block_byref_obj *dst, const struct psy_block_byref_obj *src); /**
void (*byref_dispose)(struct psy_block_byref_obj *); * Copy function.
*/
void (*byref_keep)(struct block_byref_obj *dst, const struct block_byref_obj *src);
/**
* Dispose function.
*/
void (*byref_dispose)(struct block_byref_obj *);
/**
* __block-qualified variables are copied here.
*/
}; };
/**
* Returns the Objective-C type encoding for the block.
*/
const char *block_getType_np(void *b) const char *block_getType_np(void *b)
{ {
struct psy_block_literal *block = b; struct block_literal *block = b;
if ((NULL == block) || !(block->flags & BLOCK_HAS_SIGNATURE)) if ((NULL == block) || !(block->flags & BLOCK_HAS_SIGNATURE))
{ {
return NULL; return NULL;
@ -133,6 +238,33 @@ const char *block_getType_np(void *b)
return block->descriptor->encoding; return block->descriptor->encoding;
} }
static int increment24(int *ref)
{
int old = *ref;
int val = old & BLOCK_REFCOUNT_MASK;
// FIXME: We should gracefully handle refcount overflow, but for now we
// just give up
assert(val < BLOCK_REFCOUNT_MASK);
if (!__sync_bool_compare_and_swap(ref, old, old+1))
{
return increment24(ref);
}
return val + 1;
}
static int decrement24(int *ref)
{
int old = *ref;
int val = old & BLOCK_REFCOUNT_MASK;
// FIXME: We should gracefully handle refcount overflow, but for now we
// just give up
assert(val > 0);
if (!__sync_bool_compare_and_swap(ref, old, old-1))
{
return decrement24(ref);
}
return val - 1;
}
/* Certain field types require runtime assistance when being copied to the /* Certain field types require runtime assistance when being copied to the
* heap. The following function is used to copy fields of types: blocks, * heap. The following function is used to copy fields of types: blocks,
@ -143,48 +275,70 @@ const char *block_getType_np(void *b)
*/ */
void _Block_object_assign(void *destAddr, const void *object, const int flags) void _Block_object_assign(void *destAddr, const void *object, const int flags)
{ {
fprintf(stderr, "assign: %d\n", flags);
//printf("Copying %x to %x with flags %x\n", object, destAddr, flags); //printf("Copying %x to %x with flags %x\n", object, destAddr, flags);
// FIXME: Needs to be implemented // FIXME: Needs to be implemented
if(flags & BLOCK_FIELD_IS_WEAK) //if(flags & BLOCK_FIELD_IS_WEAK)
{ {
} }
else //else
{ {
if(flags & BLOCK_FIELD_IS_BYREF) if(flags & BLOCK_FIELD_IS_BYREF)
{ {
const struct psy_block_byref_obj *src = object; struct block_byref_obj *src = (struct block_byref_obj *)object;
struct psy_block_byref_obj **dst = destAddr; struct block_byref_obj **dst = destAddr;
/* I followed Apple's specs saying byref's "flags" field should if ((src->flags & BLOCK_REFCOUNT_MASK) == 0)
* represent the refcount but it still contains real flag, so this
* is a little hack...
*/
if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
{ {
*dst = malloc(src->size); *dst = malloc(src->size);
fprintf(stderr, "Copying %d bytes to %p\n", src->size, *dst);
memcpy(*dst, src, src->size); memcpy(*dst, src, src->size);
if (src->forwarding == src) (*dst)->isa = _HeapBlockByRef;
// Refcount must be two; one for the copy and one for the
// on-stack version that will point to it.
(*dst)->flags += 2;
if ((size_t)src->size >= sizeof(struct block_byref_obj))
{ {
(*dst)->forwarding = *dst; src->byref_keep(*dst, src);
} }
if((size_t)src->size >= sizeof(struct psy_block_byref_obj)) (*dst)->forwarding = *dst;
// Concurrency. If we try copying the same byref structure
// from two threads simultaneously, we could end up with two
// versions on the heap that are unaware of each other. That
// would be bad. So we first set up the copy, then try to do
// an atomic compare-and-exchange to point the old version at
// it. If the forwarding pointer in src has changed, then we
// recover - clean up and then return the structure that the
// other thread created.
/*
if (!__sync_bool_compare_and_swap(&src->forwarding, src, *dst))
{ {
src->byref_keep(*dst, src); if((size_t)src->size >= sizeof(struct block_byref_obj))
{
src->byref_dispose(*dst);
}
free(*dst);
*dst = src->forwarding;
} }
*/
} }
else *dst = (struct psy_block_byref_obj*)src; else
{
(*dst)->flags++; *dst = (struct block_byref_obj*)src;
}
increment24(&(*dst)->flags);
fprintf(stderr, "Flags for block: %p: %d\n", *dst, (*dst)->flags);
} }
else if((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) else if((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK)
{ {
struct psy_block_literal *src = (struct psy_block_literal*)object; struct block_literal *src = (struct block_literal*)object;
struct psy_block_literal **dst = destAddr; struct block_literal **dst = destAddr;
*dst = Block_copy(src); *dst = Block_copy(src);
} }
else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT)
{ {
fprintf(stderr, "-retain\n");
id src = (id)object; id src = (id)object;
id *dst = destAddr; id *dst = destAddr;
*dst = [src retain]; *dst = [src retain];
@ -200,32 +354,61 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags)
*/ */
void _Block_object_dispose(const void *object, const int flags) void _Block_object_dispose(const void *object, const int flags)
{ {
fprintf(stderr, "Dispose %p, Flags: %d\n", object, flags);
// FIXME: Needs to be implemented // FIXME: Needs to be implemented
if(flags & BLOCK_FIELD_IS_WEAK) //if(flags & BLOCK_FIELD_IS_WEAK)
{ {
} }
else //else
{ {
if(flags & BLOCK_FIELD_IS_BYREF) if(flags & BLOCK_FIELD_IS_BYREF)
{ {
struct psy_block_byref_obj *src = struct block_byref_obj *src =
(struct psy_block_byref_obj*)object; (struct block_byref_obj*)object;
if (src->isa == _HeapBlockByRef)
src->flags--;
if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0)
{ {
if((size_t)src->size >= sizeof(struct psy_block_byref_obj)) fprintf(stderr, "refcount %d\n", src->flags);
src->byref_dispose(src); int refcount = decrement24(&src->flags);
if (refcount == 0)
free(src); {
if (0 != src->byref_dispose)
{
src->byref_dispose(src);
}
free(src);
}
}
else
{
fprintf(stderr, "src: %p\n", src);
fprintf(stderr, "forwarding: %p\n", src->forwarding);
fprintf(stderr, "dispose: %p\n", src->byref_dispose);
void *var = src+1;
id obj = *(id*)var;
fprintf(stderr, "Cleaning up %p\n" ,obj);
// Call nontrivial destructors, but don't
if (0 != src->byref_dispose)
{
//fprintf(stderr, "Calling byref dispose\n");
//src->byref_dispose(src);
//src->byref_dispose(0);
//fprintf(stderr, "Called byref dispose\n");
}
// If this block has been promoted to the heap, decrement its
// reference count / destroy it if the heap version is already
// dead.
if (src->forwarding != src)
{
_Block_object_dispose(src->forwarding, flags | BLOCK_BYREF_CALLER);
}
} }
} }
else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK) else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK)
{ {
struct psy_block_literal *src = (struct psy_block_literal*)object; struct block_literal *src = (struct block_literal*)object;
Block_release(src); Block_release(src);
} }
else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT) else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT)
{ {
id src = (id)object; id src = (id)object;
[src release]; [src release];
@ -233,44 +416,31 @@ void _Block_object_dispose(const void *object, const int flags)
} }
} }
struct StackBlockClass {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags;
int reserved;
void (*invoke)(void *, ...);
struct {
unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions
void (*copy_helper)(void *dst, void *src);
void (*dispose_helper)(void *src);
} *descriptor;
};
// Copy a block to the heap if it's still on the stack or increments its retain count. // Copy a block to the heap if it's still on the stack or increments its retain count.
void *_Block_copy(void *src) void *_Block_copy(void *src)
{ {
struct StackBlockClass *self = src; fprintf(stderr, "_Block_copy()\n");
struct StackBlockClass *ret = self; struct block_literal *self = src;
struct block_literal *ret = self;
extern void _NSConcreteStackBlock __attribute__((weak)); extern void _NSConcreteStackBlock;
fprintf(stderr, "isa %p stack block %p\n", self->isa, &_NSConcreteStackBlock);
// If the block is Global, there's no need to copy it on the heap. // If the block is Global, there's no need to copy it on the heap.
if(self->isa == &_NSConcreteStackBlock) if(self->isa == &_NSConcreteStackBlock)
{ {
fprintf(stderr, "reserved: %d\n", self->reserved);
fprintf(stderr, "block flags: %d\n", self->flags);
if(self->reserved == 0) if(self->reserved == 0)
{ {
ret = malloc(self->descriptor->size); ret = malloc(self->descriptor->size);
memcpy(ret, self, self->descriptor->size);
if(self->flags & BLOCK_HAS_COPY_DISPOSE) if(self->flags & BLOCK_HAS_COPY_DISPOSE)
{ {
memcpy(self, ret, sizeof(struct StackBlockClass)); fprintf(stderr, "_Block_copy() calling copy helper\n");
self->descriptor->copy_helper(ret, self); self->descriptor->copy_helper(ret, self);
} }
else
{
memcpy(self, ret, self->descriptor->size);
}
} }
ret->reserved++; ret->reserved++;
} }
@ -280,9 +450,9 @@ void *_Block_copy(void *src)
// Release a block and frees the memory when the retain count hits zero. // Release a block and frees the memory when the retain count hits zero.
void _Block_release(void *src) void _Block_release(void *src)
{ {
struct StackBlockClass *self = src; struct block_literal *self = src;
extern void _NSConcreteStackBlock __attribute__((weak)); extern void _NSConcreteStackBlock;
if(self->isa == &_NSConcreteStackBlock && // A Global block doesn't need to be released if(self->isa == &_NSConcreteStackBlock && // A Global block doesn't need to be released
self->reserved > 0) // If false, then it's not allocated on the heap, we won't release auto memory ! self->reserved > 0) // If false, then it's not allocated on the heap, we won't release auto memory !

@ -0,0 +1,174 @@
.objc_sel_nameautorelease
.objc_sel_namecopy
.objc_sel_namedealloc
.objc_sel_namerelease
.objc_sel_nameretain
_Block_copy
_Block_object_assign
_Block_object_dispose
_Block_release
_NSConcreteGlobalBlock
_NSConcreteStackBlock
__gnu_objc_personality_v0
__objc_class_name_Object
__objc_class_name_Protocol
__objc_class_name_Protocol2
__objc_class_name___ObjC_Protocol_Holder_Ugly_Hack
__objc_exec_class
__objc_id_typeinfo
__objc_msg_forward2
__objc_msg_forward3
__objc_responds_to
__objc_runtime_mutex
__objc_runtime_threads_alive
__objc_sync_init
__objc_uninstalled_dtable
__objc_update_dispatch_table_for_class
_objc_class_for_boxing_foreign_exception
_objc_load_callback
_objc_lookup_class
_objc_selector_type_mismatch
_objc_unexpected_exception
block_getType_np
class_addIvar
class_addMethod
class_addProtocol
class_conformsToProtocol
class_copyIvarList
class_copyMethodList
class_copyPropertyList
class_copyProtocolList
class_createInstance
class_getClassMethod
class_getClassVariable
class_getInstanceMethod
class_getInstanceSize
class_getInstanceVariable
class_getIvarLayout
class_getMethodImplementation
class_getMethodImplementation_stret
class_getName
class_getProperty
class_getSuperclass
class_getVersion
class_getWeakIvarLayout
class_isMetaClass
class_pose_as
class_replaceMethod
class_respondsToSelector
class_setIvarLayout
class_setSuperclass
class_setVersion
class_setWeakIvarLayout
class_table_get_safe
class_table_insert
class_table_internal_create
get_imp
ivar_getName
ivar_getOffset
ivar_getTypeEncoding
method_copyArgumentType
method_copyReturnType
method_exchangeImplementations
method_getArgumentType
method_getImplementation
method_getName
method_getNumberOfArguments
method_getReturnType
method_getTypeEncoding
method_get_number_of_arguments
method_setImplementation
objc_aligned_size
objc_alignof_type
objc_allocateClassPair
objc_atomic_malloc
objc_calloc
objc_check_abi_version
objc_collect_garbage_data
objc_compute_ivar_offsets
objc_copy_dtable_for_class
objc_create_block_classes_as_subclasses_of
objc_disposeClassPair
objc_enumerationMutation
objc_exception_throw
objc_free
objc_getClass
objc_getClassList
objc_getMetaClass
objc_getProperty
objc_getProtocol
objc_getRequiredClass
objc_get_class
objc_get_meta_class
objc_get_slot
objc_get_type_qualifiers
objc_init_buffered_statics
objc_init_load_messages_table
objc_init_protocols
objc_init_statics
objc_layout_structure
objc_layout_structure_get_info
objc_layout_structure_next_member
objc_load_buffered_categories
objc_load_class
objc_lookUpClass
objc_lookup_class
objc_malloc
objc_msg_lookup
objc_msg_lookup_sender
objc_msg_lookup_super
objc_msg_profile
objc_msg_sender
objc_msg_sendv
objc_next_class
objc_plane_lookup
objc_promoted_size
objc_proxy_lookup
objc_realloc
objc_registerClassPair
objc_setProperty
objc_sizeof_type
objc_skip_argspec
objc_skip_type_qualifiers
objc_skip_typespec
objc_slot_lookup_super
objc_sync_enter
objc_sync_exit
objc_test_capability
objc_valloc
object_getClass
object_getClassName
object_getIndexedIvars
object_setClass
property_getName
protocol_conformsToProtocol
protocol_copyMethodDescriptionList
protocol_copyPropertyList
protocol_copyProtocolList
protocol_create
protocol_for_name
protocol_getMethodDescription
protocol_getName
protocol_getProperty
protocol_isEqual
sel_copyTypedSelectors_np
sel_copyTypes_np
sel_eq
sel_getName
sel_getType_np
sel_getUid
sel_get_any_typed_uid
sel_get_any_uid
sel_get_name
sel_get_type
sel_get_typed_uid
sel_get_uid
sel_isEqual
sel_is_mapped
sel_registerName
sel_registerTypedName_np
sel_register_name
sel_register_typed_name
selector_create
toy_dispatch_async_f
toy_dispatch_queue_create

@ -1,4 +1,4 @@
#include "toydispatch/toydispatch.h" #include "objc/toydispatch.h"
static dispatch_queue_t garbage_queue; static dispatch_queue_t garbage_queue;

@ -1,7 +1,7 @@
#include <pthread.h> #include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#define __TOY_DISPATCH__ #define __TOY_DISPATCH__
#include "toydispatch.h" #include "objc/toydispatch.h"
/** /**
* Amount of total space in the ring buffer. Must be a power of two. * Amount of total space in the ring buffer. Must be a power of two.

@ -1,47 +0,0 @@
/**
* toydispatch implements a (tiny) subset of the libdispatch interfaces. It
* can produce FIFO work queues, but not concurrent ones (although queues are
* concurrent with respect to each other, as with libdispatch). Unlike
* libdispatch, queues all run on the same system thread. This is less
* efficient, so the real libdispatch should be used on platforms where it is
* available.
*
* Toydispatch symbol names are prefixed with toy_ so programs can be linked to
* both libdispatch and toydispatch.
*/
/* If the real libdispatch exists, use that instead of the toy one. */
#if !defined(__has_include)
#define __has_include(x) 0
#endif
#if __has_include(<dispatch/dispatch.h>) && !defined(__TOY_DISPATCH__)
# include <dispatch/dispatch.h>
#else
/**
* Function type for functions that can be added to dispatch queues.
*/
typedef void (*dispatch_function_t)(void *);
typedef struct dispatch_queue * dispatch_queue_t;
#define dispatch_queue_create toy_dispatch_queue_create
/**
* Create a new queue. Both parameters are ignored by toydispatch.
*/
dispatch_queue_t dispatch_queue_create(const char *label,
void *attr);
#define dispatch_async_f toy_dispatch_async_f
/**
* Add a function to the queue.
*/
void dispatch_async_f(dispatch_queue_t queue, void *context,
dispatch_function_t work);
#define dispatch_release toy_dispatch_release
void dispatch_release(dispatch_queue_t queue);
#define dispatch_retain toy_dispatch_retain
void dispatch_retain(dispatch_queue_t queue);
#endif
Loading…
Cancel
Save