如何重构任意块?
我有两个函数具有截然不同的签名,我希望将其作为块传递,以便我可以确保线程安全,因为setenv()和unsetenv()不能保证是线程安全的:
旧代码
-(X*)foo1
{
X* x;
@synchronized( self )
{
setenv( ... );
x = worker_1( ... );
unsetenv( ... );
}
return x;
}
-(Y*)foo2
{
Y* y;
@synchronized( self )
{
setenv( ... );
y = worker_2( ... );
unsetenv( ... );
}
return y;
}
请注意,两个代码块是相同,除了worker_1()和worker_2()的签名有很大不同。
换句话说,我需要重构相同的包装,但完全不同的guts返回任意对象。
新代码
- (void)aThreadSafeWrapper:my_block // broken: needs fixing
{
@synchronized( self )
{
setenv( ... );
my_block(); // broken: needs fixing
unsetenv( ... );
}
}
我有什么办法可以在Objective-C中完成这个重构吗?
答案 0 :(得分:1)
我不知道我是否理解你的问题,但看起来你所需要的只是......
- (void)performWithMySpecialEnvironment:(void(^)(void))block
{
@synchronized( self )
{
setenv( ... );
block();
unsetenv( ... );
}
}
然后,你可以在你的街区做任何你想做的事......
[foo performWithMySpecialEnvironment:^{
X x = worker_1( ... );
}];
[foo performWithMySpecialEnvironment:^{
Y y = worker_2( ... );
}];
请注意,我并不支持@ synchronized / setenv / unsetenv用法,但由于这就是你正在做的事情,并且它不是手头真正问题的一部分,我会不理睬它,因为它可能会混淆真正的“阻塞”问题。
修改强>
包装建议的+1。实际上,如果我将块签名更改为返回(void *)并执行一些非常难看的转换,我可以得到 这个工作。如果这最终混淆,我可能只需要 复制粘贴包装代码(yuck)。我喜欢ObjC,但这就是我的地方 像C ++模板这样的功能会派上用场。我会 如果没有更好的解决方案,请接受此答案。 tyvm! - kfmfe04
显然,您需要进行转换和返回,因为您想要访问块外的变量。这很容易解决。
__block X x;
[foo performWithMySpecialEnvironment:^{
x = worker_1( ... );
}];