5 #include <boost/thread/mutex.hpp>
7 #include "flame/base.h"
8 #include "flame/util.h"
12 typedef boost::mutex info_mutex_t;
13 info_mutex_t info_mutex;
16 StateBase::~StateBase() {}
41 Info.
name =
"next_elem";
43 Info.type = ArrayInfo::Sizet;
49 Info.type = ArrayInfo::Double;
57 :name(conf.get<std::string>(
"name"))
59 ,length(conf.get<double>(
"L",0.0))
64 ElementVoid::~ElementVoid()
76 p_conf = other->p_conf;
78 *
const_cast<std::string*
>(&
name) = other->
name;
88 std::string type(c.
get<std::string>(
"sim_type"));
90 FLAME_LOG(INFO)<<
"Constructing Machine w/ sim_type='"<<type<<
'\'';
92 info_mutex_t::scoped_lock G(info_mutex);
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());
103 typedef Config::vector_t elements_t;
104 elements_t Es(c.
get<elements_t>(
"elements"));
107 p_lookup_t result_l, result_t;
108 result.reserve(Es.size());
111 for(elements_t::iterator it=Es.begin(),
end=Es.end(); it!=
end; ++it)
115 const std::string& etype(EC.
get<std::string>(
"type"));
117 state_info::elements_t::iterator eit = p_info.elements.find(etype);
118 if(eit==p_info.elements.end())
119 throw key_error(etype);
121 element_builder_t* builder = eit->second;
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());
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());
140 std::ostringstream strm;
141 strm<<
"Element type inconsistent "<<etype<<
" "<<E->
type_name();
142 throw std::logic_error(strm.str());
145 *
const_cast<size_t*
>(&E->
index) = idx++;
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));
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<<
'\'';
162 for(p_elements_t::iterator it=p_elements.begin(),
end=p_elements.end(); it!=
end; ++it)
171 const size_t nelem = p_elements.size();
174 S->
retreat = std::signbit(max);
176 for(
int i=0; S->
next_elem<nelem && i<abs(max); i++)
188 E->p_observe->
view(E, S);
190 (*p_trace) <<
"After ["<< n<<
"] " << E->
name <<
" " << *S <<
"\n";
197 return (*p_info.builder)(c);
202 if(idx>=p_elements.size())
203 throw std::invalid_argument(
"element index out of range");
205 const std::string& etype(c.
get<std::string>(
"type"));
207 state_info::elements_t::iterator eit = p_info.elements.find(etype);
208 if(eit==p_info.elements.end())
209 throw key_error(etype);
211 element_builder_t *builder = eit->second;
213 builder->rebuild(p_elements[idx], c, idx);
216 Machine::p_state_infos_t Machine::p_state_infos;
218 void Machine::p_registerState(
const char *name, state_builder_t b)
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());
229 p_state_infos[name] = I;
232 void Machine::p_registerElement(
const std::string& sname,
const char *ename, element_builder_t *b)
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());
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());
248 I.elements[ename] = b;
253 info_mutex_t::scoped_lock G(info_mutex);
255 for(p_state_infos_t::iterator it=p_state_infos.begin(),
end=p_state_infos.end();
258 state_info::elements_t::iterator it2, end2;
259 for(it2=it->second.elements.begin(), end2=it->second.elements.end(); it2!=end2; ++it2)
264 p_state_infos.clear();
267 std::ostream& operator<<(std::ostream& strm,
const Machine& m)
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)
273 (*it)->show(strm, 0);
279 struct Logcerr :
public Machine::Logger
281 virtual ~Logcerr() {}
282 virtual void log(
const Machine::LogRecord &r)
284 std::string msg(r.strm.str());
285 std::cerr<<r.fname<<
':'<<r.lnum<<
" : "<<msg;
286 if(msg.empty() || msg[msg.size()-1]!=
'\n')
289 static Logcerr singleton;
290 static void noopdtor(Logcerr*) {}
292 Logcerr Logcerr::singleton;
295 int Machine::log_detail = FLAME_WARN;
296 boost::shared_ptr<Machine::Logger> Machine::p_logger(&Logcerr::singleton, Logcerr::noopdtor);
298 void Machine::set_logger(
const boost::shared_ptr<Logger> &p)
300 boost::shared_ptr<Logger> temp(p);
302 temp.reset(&Logcerr::singleton, Logcerr::noopdtor);
304 info_mutex_t::scoped_lock G(info_mutex);
309 Machine::LogRecord::~LogRecord()
311 boost::shared_ptr<Logger> logger;
313 info_mutex_t::scoped_lock G(info_mutex);
StateBase(const Config &c)
ElementVoid(const Config &conf)
Construct this element using the provided Config.
bool retreat
retreat (backward) simulation flag
Base class for all simulated elements.
double length
Longitudual length of this element (added to StateBase::pos)
virtual void view(const ElementVoid *elem, const StateBase *state)=0
Called from within Machine::propagate()
Machine(const Config &c)
Construct a new Machine.
The core simulate Machine engine.
virtual const char * type_name() const =0
virtual void advance(StateBase &s)=0
Propogate the given State through this Element.
The abstract base class for all simulation state objects.
virtual void assign(const ElementVoid *other)=0
void propagate(StateBase *S, size_t start=0, int max=INT_MAX) const
Pass the given bunch State through this Machine.
Associative configuration container.
Used with StateBase::getArray() to describe a single parameter.
virtual void assign(const StateBase &other)=0
size_t index
Index of this element (unique in its Machine)
static void registeryCleanup()
Discard all registered State and Element type information.
double pos
absolute longitudinal position at end of Element
const std::string name
Name of this element (unique in its Machine)
iterator end()
Points just after the last element.
void reconfigure(size_t idx, const Config &c)
Change the configuration of a single element.
virtual bool getArray(unsigned index, ArrayInfo &Info)
Introspect named parameter of the derived class.
detail::RT< T >::type get(const std::string &name) const
virtual void show(std::ostream &, int level) const
StateBase * allocState() const
const char * name
The parameter name.