OBSEXTScope.h
3.63 KB
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//
// EXTScope.h
// extobjc
//
// Created by Justin Spahr-Summers on 2011-05-04.
// Copyright (C) 2012 Justin Spahr-Summers.
// Released under the MIT license.
//
#import "OBSmetamacros.h"
/**
*\@onExit defines some code to be executed when the current scope exits. The
*code must be enclosed in braces and terminated with a semicolon, and will be
*executed regardless of how the scope is exited, including from exceptions,
*\c goto, \c return, \c break, and \c continue.
*
*Provided code will go into a block to be executed later. Keep this in mind as
*it pertains to memory management, restrictions on assignment, etc. Because
*the code is used within a block, \c return is a legal (though perhaps
*confusing) way to exit the cleanup block early.
*
*Multiple \@onExit statements in the same scope are executed in reverse
*lexical order. This helps when pairing resource acquisition with \@onExit
*statements, as it guarantees teardown in the opposite order of acquisition.
*
*@note This statement cannot be used within scopes defined without braces
*(like a one line \c if). In practice, this is not an issue, since \@onExit is
*a useless construct in such a case anyways.
*/
#define obs_onExit \
try {} @finally {} \
__strong obs_mtl_cleanupBlock_t obs_metamacro_concat(obs_mtl_exitBlock_, __LINE__) __attribute__((cleanup(obs_mtl_executeCleanupBlock), unused)) = ^
/**
*Creates \c __weak shadow variables for each of the variables provided as
*arguments, which can later be made strong again with #strongify.
*
*This is typically used to weakly reference variables in a block, but then
*ensure that the variables stay alive during the actual execution of the block
*(if they were live upon entry).
*
*See #strongify for an example of usage.
*/
#define obs_weakify(...) \
try {} @finally {} \
obs_metamacro_foreach_cxt(obs_mtl_weakify_,, __weak, __VA_ARGS__)
/**
*Like #weakify, but uses \c __unsafe_unretained instead, for targets or
*classes that do not support weak references.
*/
#define obs_unsafeify(...) \
try {} @finally {} \
obs_metamacro_foreach_cxt(obs_mtl_weakify_,, __unsafe_unretained, __VA_ARGS__)
/**
*Strongly references each of the variables provided as arguments, which must
*have previously been passed to #weakify.
*
*The strong references created will shadow the original variable names, such
*that the original names can be used without issue (and a significantly
*reduced risk of retain cycles) in the current scope.
*
*@code
id foo = [[NSObject alloc] init];
id bar = [[NSObject alloc] init];
@weakify(foo, bar);
// this block will not keep 'foo' or 'bar' alive
BOOL (^matchesFooOrBar)(id) = ^ BOOL (id obj){
// but now, upon entry, 'foo' and 'bar' will stay alive until the block has
// finished executing
@strongify(foo, bar);
return [foo isEqual:obj] || [bar isEqual:obj];
};
*@endcode
*/
#define obs_strongify(...) \
try {} @finally {} \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
obs_metamacro_foreach(obs_mtl_strongify_,, __VA_ARGS__) \
_Pragma("clang diagnostic pop")
/** *implementation details follow ***/
typedef void (^obs_mtl_cleanupBlock_t)();
void obs_mtl_executeCleanupBlock (__strong obs_mtl_cleanupBlock_t *block);
#define obs_mtl_weakify_(INDEX, CONTEXT, VAR) \
CONTEXT __typeof__(VAR) obs_metamacro_concat(VAR, _weak_) = (VAR);
#define obs_mtl_strongify_(INDEX, VAR) \
__strong __typeof__(VAR) VAR = obs_metamacro_concat(VAR, _weak_);