Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. // OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22.  
  23. #ifndef CLOVER_CORE_EVENT_HPP
  24. #define CLOVER_CORE_EVENT_HPP
  25.  
  26. #include <condition_variable>
  27. #include <functional>
  28.  
  29. #include "core/object.hpp"
  30. #include "core/queue.hpp"
  31. #include "core/timestamp.hpp"
  32. #include "util/lazy.hpp"
  33.  
  34. namespace clover {
  35.    ///
  36.    /// Class that represents a task that might be executed
  37.    /// asynchronously at some point in the future.
  38.    ///
  39.    /// An event consists of a list of dependencies, a boolean
  40.    /// signalled() flag, and an associated task.  An event is
  41.    /// considered signalled as soon as all its dependencies (if any)
  42.    /// are signalled as well, and the trigger() method is called; at
  43.    /// that point the associated task will be started through the
  44.    /// specified \a action_ok.  If the abort() method is called
  45.    /// instead, the specified \a action_fail is executed and the
  46.    /// associated task will never be started.  Dependent events will
  47.    /// be aborted recursively.
  48.    ///
  49.    /// The execution status of the associated task can be queried
  50.    /// using the status() method, and it can be waited for completion
  51.    /// using the wait() method.
  52.    ///
  53.    class event : public ref_counter, public _cl_event {
  54.    public:
  55.       typedef std::function<void (event &)> action;
  56.  
  57.       event(clover::context &ctx, const ref_vector<event> &deps,
  58.             action action_ok, action action_fail);
  59.       virtual ~event();
  60.  
  61.       event(const event &ev) = delete;
  62.       event &
  63.       operator=(const event &ev) = delete;
  64.  
  65.       void trigger();
  66.       void abort(cl_int status);
  67.       bool signalled() const;
  68.  
  69.       virtual cl_int status() const;
  70.       virtual command_queue *queue() const = 0;
  71.       virtual cl_command_type command() const = 0;
  72.       virtual void wait() const;
  73.  
  74.       virtual struct pipe_fence_handle *fence() const {
  75.          return NULL;
  76.       }
  77.  
  78.       const intrusive_ref<clover::context> context;
  79.  
  80.    protected:
  81.       void chain(event &ev);
  82.  
  83.       std::vector<intrusive_ref<event>> deps;
  84.  
  85.    private:
  86.       std::vector<intrusive_ref<event>> trigger_self();
  87.       std::vector<intrusive_ref<event>> abort_self(cl_int status);
  88.  
  89.       unsigned wait_count;
  90.       cl_int _status;
  91.       action action_ok;
  92.       action action_fail;
  93.       std::vector<intrusive_ref<event>> _chain;
  94.       mutable std::condition_variable cv;
  95.       mutable std::mutex mutex;
  96.    };
  97.  
  98.    ///
  99.    /// Class that represents a task executed by a command queue.
  100.    ///
  101.    /// Similar to a normal clover::event.  In addition it's associated
  102.    /// with a given command queue \a q and a given OpenCL \a command.
  103.    /// hard_event instances created for the same queue are implicitly
  104.    /// ordered with respect to each other, and they are implicitly
  105.    /// triggered on construction.
  106.    ///
  107.    /// A hard_event is considered complete when the associated
  108.    /// hardware task finishes execution.
  109.    ///
  110.    class hard_event : public event {
  111.    public:
  112.       hard_event(command_queue &q, cl_command_type command,
  113.                  const ref_vector<event> &deps,
  114.                  action action = [](event &){});
  115.       ~hard_event();
  116.  
  117.       virtual cl_int status() const;
  118.       virtual command_queue *queue() const;
  119.       virtual cl_command_type command() const;
  120.       virtual void wait() const;
  121.  
  122.       const lazy<cl_ulong> &time_queued() const;
  123.       const lazy<cl_ulong> &time_submit() const;
  124.       const lazy<cl_ulong> &time_start() const;
  125.       const lazy<cl_ulong> &time_end() const;
  126.  
  127.       friend class command_queue;
  128.  
  129.       virtual struct pipe_fence_handle *fence() const {
  130.          return _fence;
  131.       }
  132.  
  133.    private:
  134.       virtual void fence(pipe_fence_handle *fence);
  135.       action profile(command_queue &q, const action &action) const;
  136.  
  137.       const intrusive_ref<command_queue> _queue;
  138.       cl_command_type _command;
  139.       pipe_fence_handle *_fence;
  140.       lazy<cl_ulong> _time_queued, _time_submit, _time_start, _time_end;
  141.    };
  142.  
  143.    ///
  144.    /// Class that represents a software event.
  145.    ///
  146.    /// A soft_event is not associated with any specific hardware task
  147.    /// or command queue.  It's considered complete as soon as all its
  148.    /// dependencies finish execution.
  149.    ///
  150.    class soft_event : public event {
  151.    public:
  152.       soft_event(clover::context &ctx, const ref_vector<event> &deps,
  153.                  bool trigger, action action = [](event &){});
  154.  
  155.       virtual cl_int status() const;
  156.       virtual command_queue *queue() const;
  157.       virtual cl_command_type command() const;
  158.       virtual void wait() const;
  159.    };
  160. }
  161.  
  162. #endif
  163.