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 222013 : PipelineWorker(int tid, int tinst, boost::function<bool(void)> runner) :
25 222013 : Task(tid,tinst), runner_(runner) {}
26 :
27 221240 : bool Run() {
28 221240 : if (!(runner_)()) return false;
29 220994 : 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 109874 : WorkProcessor(uint32_t stage, ExecuteFn efn, FinFn finFn, const InputT & inp,
47 : uint32_t inst, int tid, int tinst) :
48 109862 : stage_(stage),
49 109862 : finFn_(finFn),
50 109829 : efn_(efn),
51 109815 : inp_(inp),
52 109740 : finished_(false),
53 109740 : running_(false),
54 109740 : inst_(inst),
55 109740 : tid_(tid),
56 109740 : tinst_(tinst),
57 109740 : w_(new PipelineWorker(tid_, tinst_,
58 : boost::bind(&WorkProcessor<InputT,SubResultT,ExternalT>::Runner,
59 219689 : this))) {
60 109737 : res_.reset(new SubResultT);
61 109707 : }
62 :
63 110003 : void Start() {
64 110003 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
65 110002 : scheduler->Enqueue(w_);
66 110011 : }
67 :
68 109535 : boost::shared_ptr<SubResultT> Result() const {
69 109535 : if (!finished_) return boost::shared_ptr<SubResultT>();
70 109535 : return res_;
71 : }
72 :
73 109342 : void Release() {
74 109342 : assert(finished_);
75 109342 : res_.reset();
76 109788 : }
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 109182 : void WorkDone(bool ret_code) {
100 109182 : for (typename std::vector<ExternalT*>::iterator it = externals_.begin();
101 218528 : it!=externals_.end(); it++) {
102 109469 : delete (*it);
103 : }
104 109031 : finished_ = true;
105 109031 : finFn_(ret_code);
106 109786 : }
107 :
108 218959 : bool Runner(void) {
109 218959 : running_ = true;
110 218959 : ExternalBase::Efn fn = (efn_)(inst_, externals_, inp_, *res_);
111 219096 : running_ = false;
112 219096 : if (fn.empty()) {
113 109266 : WorkDone(true);
114 : } else {
115 110218 : if (fn == &ExternalBase::Incomplete) return false;
116 :
117 110209 : if (!fn(this)) {
118 0 : WorkDone(false);
119 : }
120 : }
121 219934 : return true;
122 219934 : }
123 :
124 110375 : void Response(std::unique_ptr<ExternalT> resp) {
125 110375 : ExternalT * msg = resp.get();
126 110379 : resp.release();
127 110378 : externals_.push_back(msg);
128 110367 : assert(!running_);
129 110367 : PipelineWorker *w = new PipelineWorker(tid_, tinst_,
130 : boost::bind(&WorkProcessor<InputT,SubResultT,ExternalT>::Runner,
131 : this));
132 110371 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
133 110369 : scheduler->Enqueue(w);
134 110423 : }
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 2063 : virtual ~WorkStageIf() {}
143 : };
144 : #endif
|