Cheetah - SKA - PSS - Prototype Time Domain Search Pipeline
PipelineHandlerFactory.cpp
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2016 The SKA organisation
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "cheetah/pipeline/PipelineHandlerFactory.h"
25 #include "cheetah/pipeline/CheetahConfig.h"
26 
27 // included pipelines
28 #include "cheetah/pipeline/Empty.h"
29 #include "cheetah/pipeline/AccelerationSearch.h"
30 #include "cheetah/pipeline/TdasAccelerationSearchTraits.h"
31 #include "cheetah/pipeline/SinglePulse.h"
32 #include "cheetah/pipeline/RfiDetectionPipeline.h"
33 
34 #include "panda/Error.h"
35 #include "panda/MixInTimer.h"
36 #include <chrono>
37 #include <utility>
38 #include <type_traits>
39 
40 namespace ska {
41 namespace cheetah {
42 namespace pipeline {
43 
44 template<typename T, typename NumericalT>
45 static
46 T* make_handler(CheetahConfig<NumericalT> const& config, BeamConfig<NumericalT> const& beam_config) {
47  return new T(config, beam_config);
48 }
49 
50 // wrapper to protect the pipeline from being destroyed before tasks in the pools finish
51 template<typename NumericalT, typename Base>
52 class PipelineWrapper : public Base
53 {
54  public:
55  template<typename... Args>
56  PipelineWrapper(CheetahConfig<NumericalT> const& config, Args&&... args)
57  : Base(config, std::forward<Args>(args)...)
58  , _config(config)
59  {
60  }
61 
62  PipelineWrapper()
63  {
64  _config.pool_manager().wait();
65  }
66 
67  private:
68  CheetahConfig<NumericalT> const& _config;
69 };
70 
71 // wrapper to implement required virtual function of PipelineHandler
72 template<typename NumericalT, typename Base>
73 class TimerWrapper : public PipelineWrapper<NumericalT, panda::MixInTimer<Base>>
74 {
76 
77  public:
78  template<typename... Args>
79  TimerWrapper(Args&&... args)
80  : BaseT(std::forward<Args>(args)...)
81  {
82  }
83 
84 };
85 
86 template<typename NumericalT>
87 class TimedPipeline : public PipelineHandler<NumericalT>
88 {
89  typedef std::chrono::high_resolution_clock ClockType;
91 
92  public:
94  : BaseT(config, beam_config)
95  , _handler(handler)
96  {
97  }
98 
99  ~TimedPipeline()
100  {
101  delete _handler;
102  }
103 
104  // costs us an extra indirection, but I can't see another way of doing it
105  void operator()(data::TimeFrequency<Cpu, NumericalT>& data) override
106  {
107  auto start=ClockType::now();
108  (*_handler)(data);
109  auto end=ClockType::now();
110  PANDA_LOG << "timing: " << std::chrono::duration_cast<std::chrono::microseconds>(start - end).count() << "microseconds";
111  }
112 
113  private:
114  PipelineHandler<NumericalT>* _handler;
115 };
116 
117 template<typename NumericalT>
118 class Tdas : public AccelerationSearch<NumericalT, TdasAccelerationSearchTraits<NumericalT>>
119 {
120  private:
122 
123  public:
125 };
126 
127 #define REGISTER_HANDLER(handler_name) \
128  add_type(#handler_name, make_handler<handler_name<NumericalT>, NumericalT>)
129 
130 PipelineHandlerFactory::PipelineHandlerFactory(CheetahConfig<NumericalT>& config)
131  : _config(config)
132 {
133  // add known handlers
134  REGISTER_HANDLER(Empty);
135  REGISTER_HANDLER(Tdas);
136  REGISTER_HANDLER(RfiDetectionPipeline);
137  REGISTER_HANDLER(SinglePulse);
138 
139  config.set_pipeline_handlers(available());
140 }
141 
142 PipelineHandlerFactory::~PipelineHandlerFactory()
143 {
144 }
145 
146 template<typename TypeFactory>
147 void PipelineHandlerFactory::add_factory(std::string const& handler_name, TypeFactory const& factory)
148 {
149  typedef typename std::remove_pointer<decltype(std::declval<TypeFactory>()(_config, std::declval<BeamConfig<NumericalT> const&>()))>::type Type;
150  _map.insert( std::make_pair( handler_name
151  , [factory](CheetahConfig<NumericalT> const& config, BeamConfig<NumericalT> const& beam_config)
152  {
153  return factory(config, beam_config);
154  }
155  )
156  );
157  _timed_map.insert( std::make_pair( handler_name
158  , [factory](CheetahConfig<NumericalT> const& config, BeamConfig<NumericalT> const& beam_config)
159  {
160  auto handler = factory(config, beam_config);
161  try {
162  return new TimedPipeline<NumericalT>(config, beam_config, handler);
163  } catch(...) {
164  delete handler;
165  throw;
166  }
167  }
168  ));
169 }
170 
171 template<typename TypeFactory>
172 void PipelineHandlerFactory::add_type(std::string const& handler_name, TypeFactory /*factory*/)
173 {
174  _types.push_back(handler_name);
175  //_map.insert(std::make_pair(handler_name, static_cast<PipelineHandlerFactory::FactoryType>(factory)));
176  // add a timer type
177  typedef typename std::remove_pointer<decltype(std::declval<TypeFactory>()(_config, std::declval<BeamConfig<NumericalT> const&>()))>::type Type;
178  _map.insert(std::make_pair(handler_name, &make_handler<PipelineWrapper<NumericalT, Type>, NumericalT>));
179  _timed_map.insert(std::make_pair(handler_name, &make_handler<TimerWrapper<NumericalT, Type>, NumericalT>));
180 }
181 
182 std::vector<std::string> PipelineHandlerFactory::available() const
183 {
184  return _types;
185 }
186 
187 PipelineHandlerFactory::HandlerType* PipelineHandlerFactory::create(std::string const& handler_name, BeamConfig<NumericalT> const& beam_config) const
188 {
189  auto it = _map.find(handler_name);
190  if(it == _map.end())
191  throw panda::Error("Pipeline handler '" + handler_name + "' unknown");
192 
193  return it->second(_config, beam_config);
194 }
195 
197 {
198  auto it = _timed_map.find(handler_name);
199  if(it == _timed_map.end())
200  throw panda::Error("Pipeline handler '" + handler_name + "' unknown");
201 
202  return it->second(_config, beam_config);
203 }
204 
205 } // namespace pipeline
206 } // namespace cheetah
207 } // namespace ska
A do nothing handler.
Definition: Empty.h:46
HandlerType * create_timed(std::string const &type, BeamConfig< NumericalT > const &) const
create a handler of the named type with a MixInTimer to record the time of each invocation ...
The acceleration search pipeline.
std::vector< std::string > available() const
return a vector of available pipeline
Some limits and constants for FLDO.
Definition: Brdz.h:35
PoolManagerType const & pool_manager() const
return the pool manager object
Parse configuration parameters for a single beam in the pipeline instance of cheetah.
Definition: BeamConfig.h:48
Base class for Cheetah Pipeline Handlers.
Definition: Pipeline.h:37
HandlerType * create(std::string const &type, BeamConfig< NumericalT > const &) const
create a handler of the named type
A Single Pulse Search Pipeline.
Definition: SinglePulse.h:46
void set_pipeline_handlers(std::vector< std::string > const &handler_names)
set the computational unit names available
Pipeline that performs only RFI detection.