Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef __WORK_PROCESSOR_INL_H__
6 : #define __WORK_PROCESSOR_INL_H__
7 :
8 : #include <vector>
9 : #include <boost/function.hpp>
10 : #include <boost/bind/bind.hpp>
11 : #include <boost/shared_ptr.hpp>
12 : #include <boost/scoped_ptr.hpp>
13 : #include <boost/assign/list_of.hpp>
14 : #include <boost/type_traits.hpp>
15 : #include <boost/mpl/assert.hpp>
16 : #include <boost/tuple/tuple.hpp>
17 : #include <limits>
18 : #include <sstream>
19 : #include "base/task.h"
20 :
21 : using namespace boost::placeholders;
22 :
23 : struct PipelineWorker : public Task {
24 222826 : PipelineWorker(int tid, int tinst, boost::function<bool(void)> runner) :
25 222826 : Task(tid,tinst), runner_(runner) {}
26 :
27 222383 : bool Run() {
28 222383 : if (!(runner_)()) return false;
29 222452 : return true;
30 : }
31 0 : std::string Description() const { return "PipelineWorker"; }
32 : private:
33 : const boost::function<bool(void)> runner_;
34 : };
35 :
36 : template<typename InputT, typename SubResultT, typename ExternalT>
37 : class WorkProcessor : public ExternalProcIf<ExternalT> {
38 : public:
39 : typedef boost::function<ExternalBase::Efn(
40 : uint32_t inst,
41 : const std::vector<ExternalT*> & exts, // Info for previous steps of this stage
42 : const InputT & inp, // Info from previous stage
43 : SubResultT & subRes // Access to final result of this instance
44 : )> ExecuteFn;
45 :
46 110284 : WorkProcessor(uint32_t stage, ExecuteFn efn, FinFn finFn, const InputT & inp,
47 : uint32_t inst, int tid, int tinst) :
48 110272 : stage_(stage),
49 110272 : finFn_(finFn),
50 110199 : efn_(efn),
51 110210 : inp_(inp),
52 110189 : finished_(false),
53 110189 : running_(false),
54 110189 : inst_(inst),
55 110189 : tid_(tid),
56 110189 : tinst_(tinst),
57 110189 : w_(new PipelineWorker(tid_, tinst_,
58 : boost::bind(&WorkProcessor<InputT,SubResultT,ExternalT>::Runner,
59 220494 : this))) {
60 110168 : res_.reset(new SubResultT);
61 110138 : }
62 :
63 110416 : void Start() {
64 110416 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
65 110413 : scheduler->Enqueue(w_);
66 110397 : }
67 :
68 110003 : boost::shared_ptr<SubResultT> Result() const {
69 110003 : if (!finished_) return boost::shared_ptr<SubResultT>();
70 110003 : return res_;
71 : }
72 :
73 109541 : void Release() {
74 109541 : assert(finished_);
75 109541 : res_.reset();
76 110138 : }
77 :
78 254 : std::string Key() const {
79 254 : std::stringstream keystr;
80 254 : keystr << "PROC-STAGE:" << stage_ << "-INST:" << inst_ <<
81 254 : "-STEP:" << externals_.size();
82 508 : return keystr.str();
83 254 : }
84 :
85 : private:
86 : uint32_t stage_;
87 : FinFn finFn_;
88 : const ExecuteFn efn_;
89 : const InputT & inp_;
90 : boost::shared_ptr<SubResultT> res_;
91 : std::vector<ExternalT*> externals_;
92 : bool finished_;
93 : bool running_;
94 : const uint32_t inst_;
95 : const int tid_;
96 : const int tinst_;
97 : PipelineWorker * const w_;
98 :
99 110001 : void WorkDone(bool ret_code) {
100 110001 : for (typename std::vector<ExternalT*>::iterator it = externals_.begin();
101 219971 : it!=externals_.end(); it++) {
102 109684 : delete (*it);
103 : }
104 109549 : finished_ = true;
105 109549 : finFn_(ret_code);
106 110280 : }
107 :
108 220298 : bool Runner(void) {
109 220298 : running_ = true;
110 220298 : ExternalBase::Efn fn = (efn_)(inst_, externals_, inp_, *res_);
111 220179 : running_ = false;
112 220179 : if (fn.empty()) {
113 110036 : WorkDone(true);
114 : } else {
115 110681 : if (fn == &ExternalBase::Incomplete) return false;
116 :
117 110740 : if (!fn(this)) {
118 0 : WorkDone(false);
119 : }
120 : }
121 220907 : return true;
122 220907 : }
123 :
124 110789 : void Response(std::unique_ptr<ExternalT> resp) {
125 110789 : ExternalT * msg = resp.get();
126 110805 : resp.release();
127 110804 : externals_.push_back(msg);
128 110801 : assert(!running_);
129 110801 : PipelineWorker *w = new PipelineWorker(tid_, tinst_,
130 : boost::bind(&WorkProcessor<InputT,SubResultT,ExternalT>::Runner,
131 : this));
132 110790 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
133 110789 : scheduler->Enqueue(w);
134 110831 : }
135 : };
136 :
137 : template <typename InputT, typename ResultT>
138 : struct WorkStageIf {
139 : virtual void Start(uint32_t stage, FinFn finFn, const boost::shared_ptr<InputT> & inp) = 0;
140 : virtual boost::shared_ptr<ResultT> Result() const = 0;
141 : virtual void Release() = 0;
142 2064 : virtual ~WorkStageIf() {}
143 : };
144 : #endif
|