1 /******************************************************************************* 2 * thrill/api/action_node.hpp 3 * 4 * Part of Project Thrill - http://project-thrill.org 5 * 6 * Copyright (C) 2015 Sebastian Lamm <seba.lamm@gmail.com> 7 * Copyright (C) 2016 Timo Bingmann <tb@panthema.net> 8 * 9 * All rights reserved. Published under the BSD-2 license in the LICENSE file. 10 ******************************************************************************/ 11 12 #pragma once 13 #ifndef THRILL_API_ACTION_NODE_HEADER 14 #define THRILL_API_ACTION_NODE_HEADER 15 16 #include <thrill/api/dia_base.hpp> 17 18 #include <string> 19 #include <vector> 20 21 namespace thrill { 22 namespace api { 23 24 //! \ingroup api_layer 25 //! \{ 26 27 class ActionNode : public DIABase 28 { 29 public: ActionNode(Context & ctx,const char * label,const std::initializer_list<size_t> & parent_ids,const std::initializer_list<DIABasePtr> & parents)30 ActionNode(Context& ctx, const char* label, 31 const std::initializer_list<size_t>& parent_ids, 32 const std::initializer_list<DIABasePtr>& parents) 33 : DIABase(ctx, label, parent_ids, parents) { } 34 35 //! ActionNodes do not have children. RemoveChild(DIABase *)36 void RemoveChild(DIABase* /* node */) final { } 37 38 //! ActionNodes do not have children. RemoveAllChildren()39 void RemoveAllChildren() final { } 40 41 //! ActionNodes do not have children. children() const42 std::vector<DIABase*> children() const final 43 { return std::vector<DIABase*>(); } 44 45 //! ActionNodes do not push data, they only Execute. PushData(bool)46 void PushData(bool /* consume */) final { abort(); } 47 48 //! ActionNodes do not push data, they only Execute. RunPushData()49 void RunPushData() final { abort(); } 50 IncConsumeCounter(size_t)51 void IncConsumeCounter(size_t /* counter */) final { 52 die("Setting .Keep() on Actions does not make sense."); 53 } 54 DecConsumeCounter(size_t)55 void DecConsumeCounter(size_t /* counter */) final { 56 die("Setting .Keep() on Actions does not make sense."); 57 } 58 SetConsumeCounter(size_t)59 void SetConsumeCounter(size_t /* counter */) final { 60 die("Setting .Keep() on Actions does not make sense."); 61 } 62 }; 63 64 template <typename ResultType> 65 class ActionResultNode : public ActionNode 66 { 67 public: ActionResultNode(Context & ctx,const char * label,const std::initializer_list<size_t> & parent_ids,const std::initializer_list<DIABasePtr> & parents)68 ActionResultNode(Context& ctx, const char* label, 69 const std::initializer_list<size_t>& parent_ids, 70 const std::initializer_list<DIABasePtr>& parents) 71 : ActionNode(ctx, label, parent_ids, parents) { } 72 73 //! virtual method to return result via an ActionFuture 74 virtual const ResultType& result() const = 0; 75 }; 76 77 /*! 78 * The return type class for all ActionFutures. This is not a multi-threading 79 * Future, instead it is only a variable placeholder containing a pointer to the 80 * action node to retrieve the value once it is calculated. 81 */ 82 template <typename ValueType = void> 83 class Future 84 { 85 public: 86 using ActionResultNodePtr = 87 tlx::CountingPtr<ActionResultNode<ValueType> >; 88 Future(const ActionResultNodePtr & node)89 explicit Future(const ActionResultNodePtr& node) 90 : node_(node) { } 91 92 //! Evaluate the DIA data-flow graph for this ActionFuture. wait()93 void wait() { 94 if (node_->state() == DIAState::NEW) 95 node_->RunScope(); 96 } 97 98 //! true if already executed/valid valid() const99 bool valid() const { 100 return (node_->state() == DIAState::EXECUTED); 101 } 102 103 //! Return the value of the ActionFuture get()104 const ValueType& get() { 105 if (node_->state() == DIAState::NEW) 106 node_->RunScope(); 107 108 return node_->result(); 109 } 110 111 //! Return the value of the ActionFuture operator ()()112 const ValueType& operator () () { 113 return get(); 114 } 115 116 private: 117 //! shared pointer to the action node, which may not be executed yet. 118 ActionResultNodePtr node_; 119 }; 120 121 /*! 122 * Specialized template class for ActionFuture which return void. This class 123 * does not have a get() method. 124 */ 125 template <> 126 class Future<void> 127 { 128 public: 129 using ActionNodePtr = tlx::CountingPtr<ActionNode>; 130 Future(const ActionNodePtr & node)131 explicit Future(const ActionNodePtr& node) 132 : node_(node) { } 133 134 //! Evaluate the DIA data-flow graph for this ActionFuture. wait()135 void wait() { 136 if (node_->state() == DIAState::NEW) 137 node_->RunScope(); 138 } 139 140 //! true if already executed/valid valid() const141 bool valid() const { 142 return (node_->state() == DIAState::EXECUTED); 143 } 144 145 //! Return the value of the ActionFuture operator ()()146 void operator () () { 147 return wait(); 148 } 149 150 private: 151 //! shared pointer to the action node, which may not be executed yet. 152 ActionNodePtr node_; 153 }; 154 155 //! \} 156 157 } // namespace api 158 159 //! imported from api namespace 160 template <typename ValueType = void> 161 using Future = api::Future<ValueType>; 162 163 } // namespace thrill 164 165 #endif // !THRILL_API_ACTION_NODE_HEADER 166 167 /******************************************************************************/ 168