mrfioc2  2.3.0
object.cpp
Go to the documentation of this file.
1 #include <sstream>
2 #include <iostream>
3 #include <errlog.h>
4 #include <epicsMutex.h>
5 #include <epicsGuard.h>
6 
7 #include <epicsExport.h>
8 #include "mrf/object.h"
9 
10 using namespace mrf;
11 
12 typedef std::map<const std::string, Object*> objects_t;
13 static objects_t *objects;
14 typedef std::map<const std::string, Object::create_factory_t> factories_t;
15 static factories_t *factories;
16 
17 static epicsMutex *objectsLock=0;
18 
19 static
20 void initObjects(void* rmsg)
21 {
22  std::string *emsg=(std::string*)rmsg;
23  try{
24  objects = new objects_t;
25  factories = new factories_t;
26  objectsLock = new epicsMutex;
27  } catch(std::exception& e) {
28  objects=0;
29  *emsg = e.what();
30  }
31 }
32 
33 static
34 epicsThreadOnceId initOnce = EPICS_THREAD_ONCE_INIT;
35 
36 static
37 void initObjectsOnce()
38 {
39  std::string emsg;
40  epicsThreadOnce(&initOnce, &initObjects, (void*)&emsg);
41  if(!objects)
42  throw std::runtime_error(emsg);
43 }
44 
45 const char*
47 {
48  return "Alarm!";
49 }
50 
51 epicsShareFunc
53 
54 epicsShareFunc
55 void
56 propertyBase::show(std::ostream& strm) const
57 {
58  strm<<"<?>";
59 }
60 
61 Object::Object(const std::string& n, const Object *par)
62  :m_obj_name(n)
63  ,m_obj_parent(par)
64  ,m_obj_children()
65 {
66  initObjectsOnce();
67  epicsGuard<epicsMutex> g(*objectsLock);
68 
69  if(n.size()==0)
70  throw std::invalid_argument("Object name can not be empty string");
71 
72  objects_t::const_iterator it=objects->find(n);
73  if(it!=objects->end()) {
74  std::ostringstream strm;
75  strm<<"Object name '"<<n<<"' already exists.";
76  throw std::runtime_error(strm.str());
77  }
78  (*objects)[n]=this;
79 
80  if(m_obj_parent)
81  m_obj_parent->m_obj_children.insert(this);
82 }
83 
85 {
86  initObjectsOnce();
87  epicsGuard<epicsMutex> g(*objectsLock);
88 
89  if(m_obj_parent)
90  m_obj_parent->m_obj_children.erase(this);
91 
92  objects_t::iterator it=objects->find(name());
93  if(it==objects->end())
94  errlogPrintf("Can not remove object '%s' because it is not in global list.\n", name().c_str());
95  else
96  objects->erase(it);
97 }
98 
99 propertyBase* Object::getPropertyBase(const char*, const std::type_info&)
100 {
101  return 0;
102 }
103 
104 void Object::visitProperties(bool (*)(propertyBase*, void*), void*) {}
105 
106 Object*
107 Object::getObject(const std::string& n)
108 {
109  initObjectsOnce();
110  epicsGuard<epicsMutex> g(*objectsLock);
111  objects_t::const_iterator it=objects->find(n);
112  if(it!=objects->end())
113  return it->second;
114  return 0;
115 }
116 
117 Object*
118 Object::getCreateObject(const std::string& name, const std::string& klass, const create_args_t& args)
119 {
120  initObjectsOnce();
121  epicsGuard<epicsMutex> g(*objectsLock);
122  {
123  objects_t::const_iterator it=objects->find(name);
124  if(it!=objects->end())
125  return it->second;
126  }
127  if(klass.empty())
128  throw std::runtime_error(SB()<<"Object not found : "<<name);
129  {
130  factories_t::const_iterator it=factories->find(klass);
131  if(it==factories->end())
132  throw std::runtime_error(SB()<<"No such Object factory: "<<klass);
133  return (it->second)(name, klass, args);
134  }
135 }
136 
137 void
138 Object::addFactory(const std::string& klass, create_factory_t fn)
139 {
140  initObjectsOnce();
141  epicsGuard<epicsMutex> g(*objectsLock);
142 
143  factories_t::const_iterator it=factories->find(klass);
144  if(it!=factories->end())
145  throw std::runtime_error(SB()<<"Can't replace Object factory: "<<klass);
146  (*factories)[klass] = fn;
147 }
148 
149 void
150 Object::visitObjects(bool (*cb)(Object*, void*), void *arg)
151 {
152  initObjectsOnce();
153  epicsGuard<epicsMutex> g(*objectsLock);
154 
155  for(objects_t::const_iterator it=objects->begin();
156  it!=objects->end(); ++it)
157  {
158  if(!(*cb)(it->second, arg))
159  break;
160  }
161 }
162 
163 struct propArgs {
164  std::ostream& strm;
165  std::string indent;
166  propArgs(std::ostream& s, std::string i) :strm(s), indent(i) {}
167 };
168 
169 static
170 bool showProp(propertyBase* prop, void* raw)
171 {
172  propArgs *args=static_cast<propArgs*>(raw);
173  args->strm <<args->indent <<prop->type().name() << " " <<prop->name() << " = ";
174  try {
175  prop->show(args->strm);
176  } catch (std::exception& e) {
177  args->strm << "<Error: "<<e.what()<<">";
178  }
179 
180  args->strm<<"\n";
181  return true;
182 }
183 
184 static
185 void showObject(std::ostream& strm, Object& obj, std::string indent, int depth, int maxdepth, bool props)
186 {
187  if(depth>=maxdepth)
188  return;
189  propArgs args(strm, indent+" ");
190  strm <<indent <<"Object: " <<obj.name() <<"\n"
191  <<indent <<"Type: "<<typeid (obj).name()<<"\n";
192  if(props)
193  obj.visitProperties(&showProp, (void*)&args);
194  for(Object::child_iterator it=obj.beginChild(); it!=obj.endChild(); ++it)
195  showObject(strm, **it, args.indent, depth+1, maxdepth, props);
196 }
197 
198 extern "C"
199 void dol(int lvl, const char* obj)
200 {
201 try{
202  initObjectsOnce();
203  epicsGuard<epicsMutex> g(*objectsLock);
204 
205  std::cout <<objects->size() <<" Device Objects\n";
206 
207  if(!obj) {
208  for(objects_t::const_iterator it=objects->begin();
209  it!=objects->end(); ++it)
210  {
211  if(it->second->parent())
212  continue;
213  showObject(std::cout, *it->second, "", 0, lvl+1, false);
214  }
215 
216  } else {
217  objects_t::const_iterator it=objects->find(obj);
218  if(it==objects->end()) {
219  std::cout<<"Object '"<<obj<<"' does not exist\n";
220  return;
221  }
222  showObject(std::cout, *it->second, "", 0, lvl+1, false);
223  }
224 }catch(std::exception& e){
225  epicsPrintf("Error: %s\n", e.what());
226 }
227 }
228 
229 extern "C"
230 void dor(int lvl, const char* obj)
231 {
232 try{
233  initObjectsOnce();
234  epicsGuard<epicsMutex> g(*objectsLock);
235 
236  std::cout <<objects->size() <<" Device Objects\n";
237 
238  if(!obj) {
239  for(objects_t::const_iterator it=objects->begin();
240  it!=objects->end(); ++it)
241  {
242  if(it->second->parent())
243  continue;
244  showObject(std::cout, *it->second, "", 0, lvl+1, true);
245  }
246 
247  } else {
248  objects_t::const_iterator it=objects->find(obj);
249  if(it==objects->end()) {
250  std::cout<<"Object '"<<obj<<"' does not exist\n";
251  return;
252  }
253  showObject(std::cout, *it->second, "", 0, lvl+1, true);
254  }
255 }catch(std::exception& e){
256  epicsPrintf("Error: %s\n", e.what());
257 }
258 }
259 
260 #include <iocsh.h>
261 
262 static const iocshArg dolArg0 = { "level",iocshArgInt};
263 static const iocshArg dolArg1 = { "object name",iocshArgString};
264 static const iocshArg * const dolArgs[2] =
265 {&dolArg0,&dolArg1};
266 static const iocshFuncDef dolFuncDef =
267  {"dol",2,dolArgs};
268 static void dolCallFunc(const iocshArgBuf *args)
269 {
270  dol(args[0].ival, args[1].sval);
271 }
272 
273 static const iocshArg dorArg0 = { "level",iocshArgInt};
274 static const iocshArg dorArg1 = { "object name",iocshArgString};
275 static const iocshArg * const dorArgs[2] =
276 {&dorArg0,&dorArg1};
277 static const iocshFuncDef dorFuncDef =
278  {"dor",2,dorArgs};
279 static void dorCallFunc(const iocshArgBuf *args)
280 {
281  dor(args[0].ival, args[1].sval);
282 }
283 
284 static
285 void objectsreg()
286 {
287  iocshRegister(&dolFuncDef,dolCallFunc);
288  iocshRegister(&dorFuncDef,dorCallFunc);
289 }
290 
291 #include <epicsExport.h>
292 
293 extern "C" {
294 epicsExportRegistrar(objectsreg);
295 }
void dol(int lvl, const char *obj)
Definition: object.cpp:199
std::map< const std::string, Object::create_factory_t > factories_t
Definition: object.cpp:14
std::map< std::string, std::string > create_args_t
Definition: object.h:422
static Object * getCreateObject(const std::string &name, const std::string &klass, const create_args_t &args=create_args_t())
Definition: object.cpp:118
virtual ~propertyBase()=0
Definition: object.cpp:52
virtual const std::type_info & type() const =0
Object *(* create_factory_t)(const std::string &name, const std::string &klass, const create_args_t &args)
Definition: object.h:428
m_obj_children_t::const_iterator child_iterator
Definition: object.h:399
virtual const char * what()
Definition: object.cpp:46
Object(const std::string &n, const Object *par=0)
Definition: object.cpp:61
Definition: evrdump.c:37
std::map< const std::string, Object * > objects_t
Definition: object.cpp:12
virtual ~Object()=0
Definition: object.cpp:84
Base object inspection.
Definition: object.h:378
virtual void visitProperties(bool(*)(propertyBase *, void *), void *)=0
Definition: object.cpp:104
std::string indent
Definition: object.cpp:165
static Object * getObject(const std::string &name)
Definition: object.cpp:107
static void visitObjects(bool(*)(Object *, void *), void *)
Definition: object.cpp:150
virtual void show(std::ostream &) const
Print the value of the field w/o leading or trailing whitespace.
Definition: object.cpp:56
virtual const char * name() const =0
An un-typed property.
Definition: object.h:120
child_iterator beginChild() const
Definition: object.h:400
const std::string & name() const
Definition: object.h:393
static void addFactory(const std::string &klass, create_factory_t fn)
Definition: object.cpp:138
child_iterator endChild() const
Definition: object.h:401
std::ostream & strm
Definition: object.cpp:164
virtual propertyBase * getPropertyBase(const char *, const std::type_info &)=0
Definition: object.cpp:99
Definition: flash.cpp:23
void dor(int lvl, const char *obj)
Definition: object.cpp:230
epicsExportRegistrar(objectsreg)
propArgs(std::ostream &s, std::string i)
Definition: object.cpp:166