FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
base.cpp
1 
2 #include <list>
3 #include <sstream>
4 
5 #include <boost/thread/mutex.hpp>
6 
7 #include "flame/base.h"
8 #include "flame/util.h"
9 
10 namespace {
11 // This mutex guards the global Machine::p_state_infos
12 typedef boost::mutex info_mutex_t;
13 info_mutex_t info_mutex;
14 }
15 
16 StateBase::~StateBase() {}
17 
19  :next_elem(0)
20  ,pos(0e0)
21  ,retreat(false)
22  ,pyptr(0)
23 {}
24 
26  :next_elem(0)
27  ,pos(o.pos)
28  ,retreat(false)
29  ,pyptr(0)
30 {}
31 
32 void StateBase::assign(const StateBase& other)
33 {
34  pos = other.pos;
35 }
36 
37 bool StateBase::getArray(unsigned idx, ArrayInfo& Info)
38 {
39  unsigned I=0;
40  if(idx==I++) {
41  Info.name = "next_elem";
42  Info.ndim = 0;
43  Info.type = ArrayInfo::Sizet;
44  Info.ptr = &next_elem;
45  return true;
46  } else if(idx==I++) {
47  Info.name = "pos";
48  Info.ptr = &pos;
49  Info.type = ArrayInfo::Double;
50  Info.ndim = 0;
51  return true;
52  }
53  return false;
54 }
55 
57  :name(conf.get<std::string>("name"))
58  ,index(0)
59  ,length(conf.get<double>("L",0.0))
60  ,p_observe(NULL)
61  ,p_conf(conf)
62 {}
63 
64 ElementVoid::~ElementVoid()
65 {
66  delete p_observe;
67 }
68 
69 void ElementVoid::show(std::ostream& strm, int level) const
70 {
71  strm<<"Element "<<index<<": "<<name<<" ("<<type_name()<<")\n";
72 }
73 
74 void ElementVoid::assign(const ElementVoid *other)
75 {
76  p_conf = other->p_conf;
77  length = other->length;
78  *const_cast<std::string*>(&name) = other->name;
79  *const_cast<size_t*>(&index) = other->index;
80 }
81 
83  :p_elements()
84  ,p_trace(NULL)
85  ,p_conf(c)
86  ,p_info()
87 {
88  std::string type(c.get<std::string>("sim_type"));
89  p_simtype = type;
90  FLAME_LOG(INFO)<<"Constructing Machine w/ sim_type='"<<type<<'\'';
91 
92  info_mutex_t::scoped_lock G(info_mutex);
93 
94  p_state_infos_t::iterator it = p_state_infos.find(type);
95  if(it==p_state_infos.end()) {
96  std::ostringstream msg;
97  msg<<"Unsupport sim_type '"<<type<<"'";
98  throw key_error(msg.str());
99  }
100 
101  p_info = it->second;
102 
103  typedef Config::vector_t elements_t;
104  elements_t Es(c.get<elements_t>("elements"));
105 
106  p_elements_t result;
107  p_lookup_t result_l, result_t;
108  result.reserve(Es.size());
109 
110  size_t idx=0;
111  for(elements_t::iterator it=Es.begin(), end=Es.end(); it!=end; ++it)
112  {
113  const Config& EC = *it;
114 
115  const std::string& etype(EC.get<std::string>("type"));
116 
117  state_info::elements_t::iterator eit = p_info.elements.find(etype);
118  if(eit==p_info.elements.end())
119  throw key_error(etype);
120 
121  element_builder_t* builder = eit->second;
122 
123  ElementVoid *E;
124  try{
125  E = builder->build(EC);
126  }catch(key_error& e){
127  std::ostringstream strm;
128  strm<<"Error while initializing element "<<idx<<" '"<<EC.get<std::string>("name", "<invalid>")
129  <<"' : missing required parameter '"<<e.what()<<"'";
130  throw key_error(strm.str());
131 
132  }catch(std::exception& e){
133  std::ostringstream strm;
134  strm<<"Error while constructing element "<<idx<<" '"<<EC.get<std::string>("name", "<invalid>")
135  <<"' : "<<typeid(e).name()<<" : "<<e.what();
136  throw std::runtime_error(strm.str());
137  }
138 
139  if(E->type_name()!=etype) {
140  std::ostringstream strm;
141  strm<<"Element type inconsistent "<<etype<<" "<<E->type_name();
142  throw std::logic_error(strm.str());
143  }
144 
145  *const_cast<size_t*>(&E->index) = idx++; // ugly
146 
147  result.push_back(E);
148  result_l.insert(std::make_pair(LookupKey(E->name, E->index), E));
149  result_t.insert(std::make_pair(LookupKey(etype, E->index), E));
150  }
151 
152  G.unlock();
153 
154  p_elements.swap(result);
155  p_lookup.swap(result_l);
156  p_lookup_type.swap(result_t);
157  FLAME_LOG(DEBUG)<<"Complete constructing Machine w/ sim_type='"<<type<<'\'';
158 }
159 
160 Machine::~Machine()
161 {
162  for(p_elements_t::iterator it=p_elements.begin(), end=p_elements.end(); it!=end; ++it)
163  {
164  delete *it;
165  }
166 }
167 
168 void
169 Machine::propagate(StateBase* S, size_t start, int max) const
170 {
171  const size_t nelem = p_elements.size();
172 
173  S->next_elem = start;
174  S->retreat = std::signbit(max);
175 
176  for(int i=0; S->next_elem<nelem && i<abs(max); i++)
177  {
178  size_t n = S->next_elem;
179  ElementVoid* E = p_elements[n];
180  if(S->retreat) {
181  S->next_elem--;
182  } else {
183  S->next_elem++;
184  }
185  E->advance(*S);
186 
187  if(E->p_observe)
188  E->p_observe->view(E, S);
189  if(p_trace)
190  (*p_trace) << "After ["<< n<< "] " << E->name << " " << *S << "\n";
191  }
192 }
193 
194 StateBase*
196 {
197  return (*p_info.builder)(c);
198 }
199 
200 void Machine::reconfigure(size_t idx, const Config& c)
201 {
202  if(idx>=p_elements.size())
203  throw std::invalid_argument("element index out of range");
204 
205  const std::string& etype(c.get<std::string>("type"));
206 
207  state_info::elements_t::iterator eit = p_info.elements.find(etype);
208  if(eit==p_info.elements.end())
209  throw key_error(etype);
210 
211  element_builder_t *builder = eit->second;
212 
213  builder->rebuild(p_elements[idx], c, idx);
214 }
215 
216 Machine::p_state_infos_t Machine::p_state_infos;
217 
218 void Machine::p_registerState(const char *name, state_builder_t b)
219 {
220  info_mutex_t::scoped_lock G(info_mutex);
221  if(p_state_infos.find(name)!=p_state_infos.end()) {
222  std::ostringstream strm;
223  strm<<"attempt to register already registered sim_type=\""<<name<<"\"";
224  throw std::logic_error(strm.str());
225  }
226  state_info I;
227  I.name = name;
228  I.builder = b;
229  p_state_infos[name] = I;
230 }
231 
232 void Machine::p_registerElement(const std::string& sname, const char *ename, element_builder_t *b)
233 {
234  info_mutex_t::scoped_lock G(info_mutex);
235  p_state_infos_t::iterator it = p_state_infos.find(sname);
236  if(it==p_state_infos.end()) {
237  std::ostringstream strm;
238  strm<<"can't add element \""<<ename<<"\" for unknown sim_type=\""<<sname<<"\"";
239  throw std::logic_error(strm.str());
240  }
241  state_info& I = it->second;
242  if(I.elements.find(ename)!=I.elements.end()) {
243  std::ostringstream strm;
244  strm<<"element type \""<<ename<<"\" has already been registered for "
245  "sim_type=\""<<sname<<"\"";
246  throw std::logic_error(strm.str());
247  }
248  I.elements[ename] = b;
249 }
250 
252 {
253  info_mutex_t::scoped_lock G(info_mutex);
254 
255  for(p_state_infos_t::iterator it=p_state_infos.begin(), end=p_state_infos.end();
256  it!=end; ++it)
257  {
258  state_info::elements_t::iterator it2, end2;
259  for(it2=it->second.elements.begin(), end2=it->second.elements.end(); it2!=end2; ++it2)
260  {
261  delete it2->second;
262  }
263  }
264  p_state_infos.clear();
265 }
266 
267 std::ostream& operator<<(std::ostream& strm, const Machine& m)
268 {
269  strm<<"sim_type: "<<m.p_info.name<<"\n#Elements: "<<m.p_elements.size()<<"\n";
270  for(Machine::p_elements_t::const_iterator it=m.p_elements.begin(),
271  end=m.p_elements.end(); it!=end; ++it)
272  {
273  (*it)->show(strm, 0);
274  }
275  return strm;
276 }
277 
278 namespace {
279 struct Logcerr : public Machine::Logger
280 {
281  virtual ~Logcerr() {}
282  virtual void log(const Machine::LogRecord &r)
283  {
284  std::string msg(r.strm.str());
285  std::cerr<<r.fname<<':'<<r.lnum<<" : "<<msg;
286  if(msg.empty() || msg[msg.size()-1]!='\n')
287  std::cerr.put('\n');
288  }
289  static Logcerr singleton;
290  static void noopdtor(Logcerr*) {}
291 };
292 Logcerr Logcerr::singleton;
293 }
294 
295 int Machine::log_detail = FLAME_WARN;
296 boost::shared_ptr<Machine::Logger> Machine::p_logger(&Logcerr::singleton, Logcerr::noopdtor);
297 
298 void Machine::set_logger(const boost::shared_ptr<Logger> &p)
299 {
300  boost::shared_ptr<Logger> temp(p);
301  if(!temp)
302  temp.reset(&Logcerr::singleton, Logcerr::noopdtor);
303  {
304  info_mutex_t::scoped_lock G(info_mutex);
305  p_logger.swap(temp);
306  }
307 }
308 
309 Machine::LogRecord::~LogRecord()
310 {
311  boost::shared_ptr<Logger> logger;
312  {
313  info_mutex_t::scoped_lock G(info_mutex);
314  logger = p_logger;
315  }
316  logger->log(*this);
317 }
StateBase(const Config &c)
Definition: base.cpp:18
ElementVoid(const Config &conf)
Construct this element using the provided Config.
Definition: base.cpp:56
bool retreat
retreat (backward) simulation flag
Definition: base.h:39
Base class for all simulated elements.
Definition: base.h:165
double length
Longitudual length of this element (added to StateBase::pos)
Definition: base.h:195
virtual void view(const ElementVoid *elem, const StateBase *state)=0
Called from within Machine::propagate()
Machine(const Config &c)
Construct a new Machine.
Definition: base.cpp:82
The core simulate Machine engine.
Definition: base.h:229
virtual const char * type_name() const =0
size_t next_elem
Definition: base.h:35
virtual void advance(StateBase &s)=0
Propogate the given State through this Element.
The abstract base class for all simulation state objects.
Definition: base.h:29
virtual void assign(const ElementVoid *other)=0
Definition: base.cpp:74
void propagate(StateBase *S, size_t start=0, int max=INT_MAX) const
Pass the given bunch State through this Machine.
Definition: base.cpp:169
Associative configuration container.
Definition: config.h:66
Used with StateBase::getArray() to describe a single parameter.
Definition: base.h:51
virtual void assign(const StateBase &other)=0
Definition: base.cpp:32
size_t index
Index of this element (unique in its Machine)
Definition: base.h:193
static void registeryCleanup()
Discard all registered State and Element type information.
Definition: base.cpp:251
double pos
absolute longitudinal position at end of Element
Definition: base.h:37
const std::string name
Name of this element (unique in its Machine)
Definition: base.h:192
iterator end()
Points just after the last element.
Definition: base.h:341
void reconfigure(size_t idx, const Config &c)
Change the configuration of a single element.
Definition: base.cpp:200
virtual bool getArray(unsigned index, ArrayInfo &Info)
Introspect named parameter of the derived class.
Definition: base.cpp:37
detail::RT< T >::type get(const std::string &name) const
Definition: config.h:123
virtual void show(std::ostream &, int level) const
Definition: base.cpp:69
Used with clone ctor.
Definition: base.h:133
StateBase * allocState() const
Definition: base.h:260
const char * name
The parameter name.
Definition: base.h:55
unsigned ndim
Definition: base.h:67