-
Notifications
You must be signed in to change notification settings - Fork 118
/
NSBlocks.m
79 lines (67 loc) · 2.48 KB
/
NSBlocks.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include "objc/runtime.h"
#include "class.h"
#include "loader.h"
#include "lock.h"
#include "objc/blocks_runtime.h"
#include "dtable.h"
#include <assert.h>
#ifdef EMBEDDED_BLOCKS_RUNTIME
#define BLOCK_STORAGE OBJC_PUBLIC
#else
#define BLOCK_STORAGE extern
#endif
BLOCK_STORAGE struct objc_class _NSConcreteGlobalBlock;
BLOCK_STORAGE struct objc_class _NSConcreteStackBlock;
BLOCK_STORAGE struct objc_class _NSConcreteMallocBlock;
BLOCK_STORAGE struct objc_class _NSConcreteAutoBlock;
BLOCK_STORAGE struct objc_class _NSConcreteFinalizingBlock;
static struct objc_class _NSConcreteGlobalBlockMeta;
static struct objc_class _NSConcreteStackBlockMeta;
static struct objc_class _NSConcreteMallocBlockMeta;
static struct objc_class _NSConcreteAutoBlockMeta;
static struct objc_class _NSConcreteFinalizingBlockMeta;
static struct objc_class _NSBlock;
static struct objc_class _NSBlockMeta;
static void createNSBlockSubclass(Class superclass, Class newClass,
Class metaClass, char *name)
{
// Initialize the metaclass
//metaClass->class_pointer = superclass->class_pointer;
//metaClass->super_class = superclass->class_pointer;
metaClass->info = objc_class_flag_meta;
metaClass->dtable = uninstalled_dtable;
// Set up the new class
newClass->isa = metaClass;
newClass->super_class = superclass;
newClass->name = name;
newClass->dtable = uninstalled_dtable;
newClass->info = objc_class_flag_is_block;
LOCK_RUNTIME_FOR_SCOPE();
objc_load_class(newClass);
}
#define NEW_CLASS(super, sub) \
createNSBlockSubclass(super, &sub, &sub ## Meta, #sub)
OBJC_PUBLIC
BOOL objc_create_block_classes_as_subclasses_of(Class super)
{
if (_NSBlock.super_class != NULL) { return NO; }
NEW_CLASS(super, _NSBlock);
NEW_CLASS(&_NSBlock, _NSConcreteStackBlock);
NEW_CLASS(&_NSBlock, _NSConcreteGlobalBlock);
NEW_CLASS(&_NSBlock, _NSConcreteMallocBlock);
NEW_CLASS(&_NSBlock, _NSConcreteAutoBlock);
NEW_CLASS(&_NSBlock, _NSConcreteFinalizingBlock);
// Global blocks never need refcount manipulation.
objc_set_class_flag(&_NSConcreteGlobalBlock,
objc_class_flag_permanent_instances);
return YES;
}
PRIVATE void init_early_blocks(void)
{
if (_NSBlock.super_class != NULL) { return; }
_NSConcreteStackBlock.info = objc_class_flag_is_block;
_NSConcreteGlobalBlock.info = objc_class_flag_is_block | objc_class_flag_permanent_instances;
_NSConcreteMallocBlock.info = objc_class_flag_is_block;
_NSConcreteAutoBlock.info = objc_class_flag_is_block;
_NSConcreteFinalizingBlock.info = objc_class_flag_is_block;
}