Are blocks and libdispatch available on linux?

7.6k Views Asked by At

I would love to try out grand central dispatch, but all I have to develop on is an Ubuntu workstation. Is libdispatch, and the blocks extension to c/obj-c etc... available on linux? If so, how do I get them?

4

There are 4 best solutions below

3
On BEST ANSWER

You may need to use the LLVM Clang (available on Ubuntu) compiler to get blocks at this time (I don't think this is available in gcc yet, but I haven't been keeping up with gcc, so I could be wrong.)

There are efforts underway to port libdispatch (home for the open source libdispatch) to Linux. Most of the effort seems to be on Debian so far, but some on other distributions, too. See these discussion threads:

0
On

I've done some work to get the OS X Mountain Lion version of libdispatch working on Linux; the result is up at Github: http://nickhutchinson.me/libdispatch/.

0
On

Use clang-3.4.

  • sudo apt-get install libdispatch-dev
  • sudo apt-get install libblocks-runtime-dev
  • Compile with -fblocks
  • Link with -lBlocksRuntime -ldispatch
1
On

Rather than use blocks, use c++ lambdas. They play better with c++ and there is less hidden magic.

I do it like this:

/// 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);
}

And if you need to ensure that some shared resource exists before the call takes place (such as a callback on an object that is kept alive by a shared pointer):

/// 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);
}

call them like this

dispatch_function(queue, []() { something(); });

or...

dispatch_tied_function(_myQueue, shared_from_this(), [this]() { somethingOnThis(); });