| /* | 
 |  * Copyright (C) 2015-2017 Apple Inc. All rights reserved. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1. Redistributions of source code must retain the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 
 |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
 |  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR | 
 |  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
 |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
 |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
 |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 
 |  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
 |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
 |  */ | 
 |  | 
 | #ifndef SharedTask_h | 
 | #define SharedTask_h | 
 |  | 
 | #include <wtf/Ref.h> | 
 | #include <wtf/ThreadSafeRefCounted.h> | 
 |  | 
 | namespace WTF { | 
 |  | 
 | // SharedTask is a replacement for std::function for cases where: | 
 | // | 
 | // - You'd like to avoid the cost of copying, and would prefer to have reference semantics rather | 
 | //   than value semantics. | 
 | // - You want to use FastMalloc rather than system malloc. Note that std::function may avoid malloc | 
 | //   entirely in some cases, but that's hard to guarantee. | 
 | // - You intend to share the task with other threads and so want thread-safe reference counting. | 
 | // | 
 | // Here's an example of how SharedTask can be better than std::function. If you do: | 
 | // | 
 | // std::function<int(double)> a = b; | 
 | // | 
 | // Then "a" will get its own copy of all captured by-value variables. The act of copying may | 
 | // require calls to system malloc, and it may be linear time in the total size of captured | 
 | // variables. On the other hand, if you do: | 
 | // | 
 | // RefPtr<SharedTask<int(double)> a = b; | 
 | // | 
 | // Then "a" will point to the same task as b, and the only work involved is the CAS to increase the | 
 | // reference count. | 
 | // | 
 | // Also, SharedTask allows for more flexibility when sharing state between everyone who runs the | 
 | // task. With std::function, you can only share state using by-reference captured variables. | 
 | // SharedTask supports this since, like std::function, it can be built from a lambda (see | 
 | // createSharedTask(), below). But SharedTask also allows you to create your own subclass and put | 
 | // state in member fields. This can be more natural if you want fine-grained control over what | 
 | // state is shared between instances of the task. | 
 | template<typename FunctionType> class SharedTask; | 
 | template<typename PassedResultType, typename... ArgumentTypes> | 
 | class SharedTask<PassedResultType (ArgumentTypes...)> : public ThreadSafeRefCounted<SharedTask<PassedResultType (ArgumentTypes...)>> { | 
 | public: | 
 |     typedef PassedResultType ResultType; | 
 |      | 
 |     SharedTask() { } | 
 |     virtual ~SharedTask() { } | 
 |  | 
 |     virtual ResultType run(ArgumentTypes...) = 0; | 
 | }; | 
 |  | 
 | // This is a utility class that allows you to create a SharedTask subclass using a lambda. Usually, | 
 | // you don't want to use this class directly. Use createSharedTask() instead. | 
 | template<typename FunctionType, typename Functor> class SharedTaskFunctor; | 
 | template<typename ResultType, typename... ArgumentTypes, typename Functor> | 
 | class SharedTaskFunctor<ResultType (ArgumentTypes...), Functor> : public SharedTask<ResultType (ArgumentTypes...)> { | 
 | public: | 
 |     SharedTaskFunctor(const Functor& functor) | 
 |         : m_functor(functor) | 
 |     { | 
 |     } | 
 |  | 
 |     SharedTaskFunctor(Functor&& functor) | 
 |         : m_functor(WTFMove(functor)) | 
 |     { | 
 |     } | 
 |  | 
 | private: | 
 |     ResultType run(ArgumentTypes... arguments) override | 
 |     { | 
 |         return m_functor(std::forward<ArgumentTypes>(arguments)...); | 
 |     } | 
 |  | 
 |     Functor m_functor; | 
 | }; | 
 |  | 
 | // Create a SharedTask from a functor, such as a lambda. You can use this like so: | 
 | // | 
 | // RefPtr<SharedTask<void()>> task = createSharedTask<void()>( | 
 | //     [=] () { | 
 | //         do things; | 
 | //     }); | 
 | // | 
 | // Note that if you use the [&] capture list, then you're probably doing it wrong. That's because | 
 | // [&] will lead to pointers to the stack (the only exception is if you do something like &x where | 
 | // x is a reference to the heap - but in that case, it's better to use [=, &x] to be explicit). You | 
 | // probably don't want pointers to the stack if you will have tasks running on other threads. | 
 | // Probably the best way to be sure that you're not making a horrible mistake is to always use | 
 | // explicit capture lists. In many cases, [this] is sufficient. | 
 | // | 
 | // On the other hand, if you use something like ParallelHelperClient::runTaskInParallel() (or its | 
 | // helper, runFunctionInParallel(), which does createSharedTask() for you), then it can be OK to | 
 | // use [&], since the stack frame will remain live for the entire duration of the task's lifetime. | 
 | template<typename FunctionType, typename Functor> | 
 | Ref<SharedTask<FunctionType>> createSharedTask(const Functor& functor) | 
 | { | 
 |     return adoptRef(*new SharedTaskFunctor<FunctionType, Functor>(functor)); | 
 | } | 
 | template<typename FunctionType, typename Functor> | 
 | Ref<SharedTask<FunctionType>> createSharedTask(Functor&& functor) | 
 | { | 
 |     return adoptRef(*new SharedTaskFunctor<FunctionType, Functor>(WTFMove(functor))); | 
 | } | 
 |  | 
 | } // namespace WTF | 
 |  | 
 | using WTF::createSharedTask; | 
 | using WTF::SharedTask; | 
 | using WTF::SharedTaskFunctor; | 
 |  | 
 | #endif // SharedTask_h | 
 |  |