Home | History | Annotate | Download | only in core
      1 //
      2 // Copyright 2012 Francisco Jerez
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a
      5 // copy of this software and associated documentation files (the "Software"),
      6 // to deal in the Software without restriction, including without limitation
      7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 // and/or sell copies of the Software, and to permit persons to whom the
      9 // Software is furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 // THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20 // SOFTWARE.
     21 //
     22 
     23 #ifndef __CORE_EVENT_HPP__
     24 #define __CORE_EVENT_HPP__
     25 
     26 #include <functional>
     27 
     28 #include "core/base.hpp"
     29 #include "core/queue.hpp"
     30 
     31 namespace clover {
     32    typedef struct _cl_event event;
     33 }
     34 
     35 ///
     36 /// Class that represents a task that might be executed asynchronously
     37 /// at some point in the future.
     38 ///
     39 /// An event consists of a list of dependencies, a boolean signalled()
     40 /// flag, and an associated task.  An event is considered signalled as
     41 /// soon as all its dependencies (if any) are signalled as well, and
     42 /// the trigger() method is called; at that point the associated task
     43 /// will be started through the specified \a action_ok.  If the
     44 /// abort() method is called instead, the specified \a action_fail is
     45 /// executed and the associated task will never be started.  Dependent
     46 /// events will be aborted recursively.
     47 ///
     48 /// The execution status of the associated task can be queried using
     49 /// the status() method, and it can be waited for completion using the
     50 /// wait() method.
     51 ///
     52 struct _cl_event : public clover::ref_counter {
     53 public:
     54    typedef std::function<void (clover::event &)> action;
     55 
     56    _cl_event(clover::context &ctx, std::vector<clover::event *> deps,
     57              action action_ok, action action_fail);
     58    virtual ~_cl_event();
     59 
     60    void trigger();
     61    void abort(cl_int status);
     62    bool signalled() const;
     63 
     64    virtual cl_int status() const = 0;
     65    virtual cl_command_queue queue() const = 0;
     66    virtual cl_command_type command() const = 0;
     67    virtual void wait() const = 0;
     68 
     69    clover::context &ctx;
     70 
     71 protected:
     72    void chain(clover::event *ev);
     73 
     74    cl_int __status;
     75    std::vector<clover::ref_ptr<clover::event>> deps;
     76 
     77 private:
     78    unsigned wait_count;
     79    action action_ok;
     80    action action_fail;
     81    std::vector<clover::ref_ptr<clover::event>> __chain;
     82 };
     83 
     84 namespace clover {
     85    ///
     86    /// Class that represents a task executed by a command queue.
     87    ///
     88    /// Similar to a normal clover::event.  In addition it's associated
     89    /// with a given command queue \a q and a given OpenCL \a command.
     90    /// hard_event instances created for the same queue are implicitly
     91    /// ordered with respect to each other, and they are implicitly
     92    /// triggered on construction.
     93    ///
     94    /// A hard_event is considered complete when the associated
     95    /// hardware task finishes execution.
     96    ///
     97    class hard_event : public event {
     98    public:
     99       hard_event(clover::command_queue &q, cl_command_type command,
    100                  std::vector<clover::event *> deps,
    101                  action action = [](event &){});
    102       ~hard_event();
    103 
    104       virtual cl_int status() const;
    105       virtual cl_command_queue queue() const;
    106       virtual cl_command_type command() const;
    107       virtual void wait() const;
    108 
    109       friend class ::_cl_command_queue;
    110 
    111    private:
    112       virtual void fence(pipe_fence_handle *fence);
    113 
    114       clover::command_queue &__queue;
    115       cl_command_type __command;
    116       pipe_fence_handle *__fence;
    117    };
    118 
    119    ///
    120    /// Class that represents a software event.
    121    ///
    122    /// A soft_event is not associated with any specific hardware task
    123    /// or command queue.  It's considered complete as soon as all its
    124    /// dependencies finish execution.
    125    ///
    126    class soft_event : public event {
    127    public:
    128       soft_event(clover::context &ctx, std::vector<clover::event *> deps,
    129                  bool trigger, action action = [](event &){});
    130 
    131       virtual cl_int status() const;
    132       virtual cl_command_queue queue() const;
    133       virtual cl_command_type command() const;
    134       virtual void wait() const;
    135    };
    136 }
    137 
    138 #endif
    139