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() {}
39 Info.
name =
"next_elem";
41 Info.type = ArrayInfo::Sizet;
47 Info.type = ArrayInfo::Double;
55 :name(conf.get<
std::string>(
"name"))
57 ,length(conf.get<double>(
"L",0.0))
62 ElementVoid::~ElementVoid()
74 p_conf = other->p_conf;
76 *
const_cast<std::string*
>(&
name) = other->
name;
86 std::string type(c.
get<std::string>(
"sim_type"));
88 FLAME_LOG(INFO)<<
"Constructing Machine w/ sim_type='"<<type<<
'\'';
90 info_mutex_t::scoped_lock G(info_mutex);
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());
101 typedef Config::vector_t elements_t;
102 elements_t Es(c.
get<elements_t>(
"elements"));
105 p_lookup_t result_l, result_t;
106 result.reserve(Es.size());
109 for(elements_t::iterator it=Es.begin(),
end=Es.end(); it!=
end; ++it)
113 const std::string& etype(EC.
get<std::string>(
"type"));
115 state_info::elements_t::iterator eit = p_info.elements.find(etype);
116 if(eit==p_info.elements.end())
117 throw key_error(etype);
119 element_builder_t* builder = eit->second;
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());
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());
138 std::ostringstream strm;
139 strm<<
"Element type inconsistent "<<etype<<
" "<<E->
type_name();
140 throw std::logic_error(strm.str());
143 *
const_cast<size_t*
>(&E->
index) = idx++;
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));
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<<
'\'';
160 for(p_elements_t::iterator it=p_elements.begin(),
end=p_elements.end(); it!=
end; ++it)
169 const size_t nelem = p_elements.size();
172 for(
size_t i=0; S->
next_elem<nelem && i<max; i++)
179 E->p_observe->
view(E, S);
181 (*p_trace) <<
"After ["<< n<<
"] " << E->
name <<
" " << *S <<
"\n";
188 return (*p_info.builder)(c);
193 if(idx>=p_elements.size())
194 throw std::invalid_argument(
"element index out of range");
196 const std::string& etype(c.
get<std::string>(
"type"));
198 state_info::elements_t::iterator eit = p_info.elements.find(etype);
199 if(eit==p_info.elements.end())
200 throw key_error(etype);
202 element_builder_t *builder = eit->second;
204 builder->rebuild(p_elements[idx], c);
207 Machine::p_state_infos_t Machine::p_state_infos;
209 void Machine::p_registerState(
const char *name, state_builder_t b)
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());
220 p_state_infos[name] = I;
223 void Machine::p_registerElement(
const std::string& sname,
const char *ename, element_builder_t *b)
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());
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());
239 I.elements[ename] = b;
244 info_mutex_t::scoped_lock G(info_mutex);
246 for(p_state_infos_t::iterator it=p_state_infos.begin(),
end=p_state_infos.end();
249 state_info::elements_t::iterator it2, end2;
250 for(it2=it->second.elements.begin(), end2=it->second.elements.end(); it2!=end2; ++it2)
255 p_state_infos.clear();
258 std::ostream& operator<<(std::ostream& strm,
const Machine& m)
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)
264 (*it)->show(strm, 0);
270 struct Logcerr :
public Machine::Logger
272 virtual ~Logcerr() {}
273 virtual void log(
const Machine::LogRecord &r)
275 std::string msg(r.strm.str());
276 std::cerr<<r.fname<<
':'<<r.lnum<<
" : "<<msg;
277 if(msg.empty() || msg[msg.size()-1]!=
'\n')
280 static Logcerr singleton;
281 static void noopdtor(Logcerr*) {}
283 Logcerr Logcerr::singleton;
286 int Machine::log_detail = FLAME_WARN;
287 boost::shared_ptr<Machine::Logger> Machine::p_logger(&Logcerr::singleton, Logcerr::noopdtor);
289 void Machine::set_logger(
const boost::shared_ptr<Logger> &p)
291 boost::shared_ptr<Logger> temp(p);
293 temp.reset(&Logcerr::singleton, Logcerr::noopdtor);
295 info_mutex_t::scoped_lock G(info_mutex);
300 Machine::LogRecord::~LogRecord()
302 boost::shared_ptr<Logger> logger;
304 info_mutex_t::scoped_lock G(info_mutex);
StateBase(const Config &c)
ElementVoid(const Config &conf)
Construct this element using the provided Config.
void propagate(StateBase *S, size_t start=0, size_t max=-1) const
Pass the given bunch State through this Machine.
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
Associative configuration container.
Used with StateBase::getArray() to describe a single parameter.
virtual void assign(const StateBase &other)=0
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.
const size_t index
Index of this element (unique in its Machine)
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.