我很想尝试一下grand central dispatch,但是我所需要的只是一个Ubuntu工作站。是libdispatch, block扩展到c/obj-c等…linux上可用吗?如果有,我怎么得到它们?
此时您可能需要使用LLVM Clang (Ubuntu上可用)编译器来获取块(我不认为这在gcc中可用,但我一直没有跟上gcc,所以我可能错了)
正在努力将libdispatch(开放源码libdispatch的主页)移植到Linux上。到目前为止,大部分的工作似乎都在Debian上,但也有一些在其他发行版上。查看这些讨论线程:
- linux + libdispatch + clang + blocks
- libdispatch移植状态更新
- Grand Central Dispatch for Debian(存档链接)
我做了一些工作,使OS X Mountain Lion版本的libdispatch在Linux上工作;结果在Github: http://nickhutchinson.me/libdispatch/.
使用clang-3.4.
- 安装libdispatchdev sudo apt-get install libblocks-runtime-dev
- 编译-fblocks
- 链接-lBlocksRuntime -ldispatch
不要使用块,而是使用c++ lambdas。他们用c++玩得更好,而且没有那么多隐藏的魔法。
我是这样做的:
/// Dispatch a function object to a queue.
template<class F>
static void dispatch_async_function(dispatch_queue_t queue, F f) {
struct context_t {
using function_type = F;
context_t(function_type&& f) noexcept
: _f(std::move(f))
{}
static void execute(void* p) noexcept {
auto context = reinterpret_cast<context_t*>(p);
if (context) {
try {
context->_f();
}
catch(...) {
// error processing here
}
delete context;
}
}
private:
function_type _f;
};
dispatch_async_f(queue, new context_t<F>(std::move(f)), &context_t<F>::execute);
}
如果您需要确保在调用发生之前存在某些共享资源(例如对由共享指针保持活动的对象进行回调):
/// Dispatch a function object to a queue. Only execute the function if the tie
/// locks successfully.
template<class F>
static void dispatch_async_tied_function(dispatch_queue_t queue, std::weak_ptr<void> tie, F f) {
struct context_t {
using function_type = F;
context_t(function_type&& f) noexcept
: _f(std::move(f))
{}
static void execute(void* p) noexcept {
auto context = reinterpret_cast<context_t*>(p);
auto lock = _tie.lock();
if (context && tie) {
try {
context->_f();
}
catch(...) {
// error processing here
}
delete context;
}
}
private:
function_type _f;
std::weak_ptr<void> _tie;
};
dispatch_async_f(queue, new context_t<F>(std::move(f)), &context_t<F>::execute);
}
这样称呼它们
dispatch_function(queue, []() { something(); });
还是……
dispatch_tied_function(_myQueue, shared_from_this(), [this]() { somethingOnThis(); });