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