黑魔法__attribute__((cleanup))有講如何使用cleanup
來簡化使用lock代碼。__attribute__
這個修飾符頗有用,前段時間集中寫了一些東西收集這些有意思__attribute__
。戳這裏git
今天展現一種另外的方法達到這個目的。最終代碼放在了個人githubgithub
#define CONCAT(x, y) x##y #define MACRO_CONCAT(x,y) CONCAT(x,y) @interface AutoUnlockObject : NSObject { id<NSLocking> _lock; } - (id) initWithLock:(id<NSLocking>)theLock; @end @implementation AutoUnlockObject - (id) initWithLock:(id<NSLocking>)theLock{ self = [super init]; _lock = theLock; [_lock lock]; return self; } - (void) dealloc{ [_lock unlock]; } @end #define AUTOLOCK(lock) \ __unused AutoUnlockObject* MACRO_CONCAT(tmpObject,__COUNTER__) = [[AutoUnlockObject alloc] initWithLock:lock];
利用ARC的特性,在離開代碼塊時,tmpObject
會自動釋放。這樣-dealloc
中的unlock回觸發,從而實現自動unlock。segmentfault
- (void) dosth{ AUTOLOCK(self.lock); //do actual work you want below }
__Counter__
是一個gcc提供的宏,在此用於產生一個文件內惟一的數字,這樣就能夠在同一個函數裏屢次使用AUTOLOCK
lock不一樣的鎖。CONCAT
和MACRO_CONCAT
是一種慣用的鏈接Macro的手法,很少說了。函數
這種方法依賴於代碼塊的長度,若是要分段使用屢次lock同一把鎖。那就方法以下:atom
- (void) dosth{ { AUTOLOCK(self.lock); //do actual work you want below } { AUTOLOCK(self.lock); //do actual work you want below } }
若是還嫌麻煩,那就只能用這個函數:spa
void lockAndDo(id<NSLocking>lock,dispatch_block_t block) { if (lock) { AUTOLOCK(lock); if (block) { block(); } }else{ if (block) { block(); } } }
使用時:code
lockAndDo(lock, ^{ //do actual work you want here });
這樣以來就跟@synchronized
很像了。blog
@interface AutoUnlockObject2 : AutoUnlockObject @property (nonatomic,copy) dispatch_block_t block; @end @implementation AutoUnlockObject2 - (void) dealloc{ if (self.block) self.block(); [_lock unlock]; } @end #define AUTOLOCK2(lock) \ __unused AutoUnlockObject2* tmpObject = [[AutoUnlockObject2 alloc] initWithLock:lock];\ tmpObject.block = ^
加強一下,使用起來跟@synchronized
和cleanup
的方案基本差不太多了:作用域
AUTOLOCK2(lock){ NSLog(@"hi"); };
美中不足:沒有使用__COUNTER__,若是不分代碼塊的話,一個做用域裏只能用一個。get
更新一下,改爲這種就行了,
#define AUTOLOCK3(lock) \ [[AutoUnlockObject2 alloc] initWithLock:lock].block = ^ //usage AUTOLOCK3(lock){ NSLog(@"hi1"); }; AUTOLOCK3(lock){ NSLog(@"hi2"); };
恩.
All is well that ends well
不過話說回來,如今用lock的時候,已經不太多了。C++的代碼基本也能夠用相似實現。
原做寫於segmentfault 連接