PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/ATF2/control-software/epics-3.14.8/base/src/gdd/gddAppTable.cc

http://atf2flightsim.googlecode.com/
C++ | 638 lines | 462 code | 95 blank | 81 comment | 94 complexity | 3753160179a41517d12c01bb8b19fac1 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  1. /*************************************************************************\
  2. * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
  3. * National Laboratory.
  4. * Copyright (c) 2002 The Regents of the University of California, as
  5. * Operator of Los Alamos National Laboratory.
  6. * EPICS BASE Versions 3.13.7
  7. * and higher are distributed subject to a Software License Agreement found
  8. * in file LICENSE that is included with this distribution.
  9. \*************************************************************************/
  10. // Author: Jim Kowalkowski
  11. // Date: 2/96
  12. //
  13. // gddAppTable.cc,v 1.16 2003/02/12 18:53:08 jhill Exp
  14. //
  15. #define epicsExportSharedSymbols
  16. #include "gddAppTable.h"
  17. // -----------------general destructor for managed gdds--------------------
  18. void gddApplicationTypeDestructor::run(void* v)
  19. {
  20. gdd* ec = (gdd*)v;
  21. // fprintf(stderr," destructing %8.8x\n",v);
  22. gddApplicationTypeTable* db = (gddApplicationTypeTable*)arg;
  23. db->freeDD(ec);
  24. }
  25. gddApplicationTypeElement::gddApplicationTypeElement(void) { }
  26. gddApplicationTypeElement::~gddApplicationTypeElement(void) { }
  27. // --------------------------app table stuff-----------------------------
  28. gddApplicationTypeTable gddApplicationTypeTable::app_table;
  29. gddApplicationTypeTable& gddApplicationTypeTable::AppTable(void)
  30. {
  31. return gddApplicationTypeTable::app_table;
  32. }
  33. gddApplicationTypeTable::gddApplicationTypeTable(aitUint32 tot)
  34. {
  35. aitUint32 i,total;
  36. // round tot up to nearest power of 2
  37. for(i=1u<<31;i && !(tot&i);i>>=1);
  38. if(i==0)
  39. total=1;
  40. else if(i==tot)
  41. total=tot;
  42. else
  43. total=i<<1;
  44. max_groups=total/APPLTABLE_GROUP_SIZE;
  45. if((max_groups*APPLTABLE_GROUP_SIZE) != total) ++max_groups;
  46. max_allowed=total;
  47. total_registered=1;
  48. attr_table=new gddApplicationTypeElement*[max_groups];
  49. for(i=0;i<max_groups;i++) attr_table[i]=NULL;
  50. GenerateTypes();
  51. }
  52. #if 0
  53. void* operator new(size_t x)
  54. {
  55. void* v = (void*)malloc(x);
  56. fprintf(stderr,"%8.8x In operator new %d\n",v,(int)x);
  57. return v;
  58. }
  59. void operator delete(void* x)
  60. {
  61. fprintf(stderr,"%8.8x In operator delete\n",x);
  62. free((char*)x);
  63. }
  64. #endif
  65. gddApplicationTypeTable::~gddApplicationTypeTable(void)
  66. {
  67. unsigned i,j;
  68. gdd* dd;
  69. aitUint8* blk;
  70. // fprintf(stderr,"in gddApplicationTypeTable dest\n");
  71. if(this!=&app_table) return;
  72. for(i=0u;i<max_groups;i++)
  73. {
  74. if(attr_table[i])
  75. {
  76. // fprintf(stderr,"Delete TypeTable: group %d exists\n",i);
  77. for(j=0u;j<APPLTABLE_GROUP_SIZE;j++)
  78. {
  79. switch(attr_table[i][j].type)
  80. {
  81. case gddApplicationTypeNormal:
  82. // fprintf(stderr,"Delete TypeTable: app %u normal\n",j);
  83. if(attr_table[i][j].app_name)
  84. delete [] attr_table[i][j].app_name;
  85. break;
  86. case gddApplicationTypeProto:
  87. // fprintf(stderr,"Delete TypeTable: app %u has proto\n",j);
  88. if(attr_table[i][j].app_name)
  89. delete [] attr_table[i][j].app_name;
  90. if(attr_table[i][j].proto)
  91. {
  92. // if(attr_table[i][j].free_list)
  93. // fprintf(stderr," app %u has free_list\n",j);
  94. // The proto is stored as flattened gdd
  95. blk=(aitUint8*)attr_table[i][j].proto;
  96. delete [] blk;
  97. for(dd=attr_table[i][j].free_list; dd;)
  98. {
  99. blk=(aitUint8*)dd;
  100. // fprintf(stderr," delete dd %8.8x\n",blk);
  101. dd=(gdd*)dd->next();
  102. delete [] blk;
  103. }
  104. }
  105. if(attr_table[i][j].map)
  106. delete [] attr_table[i][j].map;
  107. break;
  108. case gddApplicationTypeUndefined: break;
  109. default: break;
  110. }
  111. }
  112. delete [] attr_table[i];
  113. }
  114. }
  115. delete [] attr_table;
  116. }
  117. int gddApplicationTypeTable::describeDD(gddContainer* dd, FILE* fd,
  118. int level, char* tn)
  119. {
  120. gddCursor cur = dd->getCursor();
  121. gdd* pdd;
  122. char tmp[8];
  123. char* cp;
  124. char* str;
  125. strcpy(tmp,"unknown");
  126. for(pdd=cur.first();pdd;pdd=pdd->next())
  127. {
  128. if((cp=getName(pdd->applicationType()))==NULL) cp=tmp;
  129. fprintf(fd,"#define gddAppTypeIndex_%s_%s %d\n",tn,cp,level++);
  130. }
  131. for(pdd=cur.first();pdd;pdd=pdd->next())
  132. {
  133. if((cp=getName(pdd->applicationType()))==NULL) cp=tmp;
  134. if(pdd->isContainer())
  135. {
  136. str = new char[strlen(cp)+strlen(tn)+3];
  137. strcpy(str,tn);
  138. strcat(str,"_");
  139. strcat(str,cp);
  140. level=describeDD((gddContainer*)pdd,fd,level,str);
  141. delete [] str;
  142. }
  143. }
  144. return level;
  145. }
  146. void gddApplicationTypeTable::describe(FILE* fd)
  147. {
  148. unsigned i,j;
  149. gdd* dd;
  150. char* tn;
  151. fprintf(fd,"\n");
  152. for(i=0;i<max_groups;i++)
  153. {
  154. if(attr_table[i])
  155. {
  156. for(j=0;j<APPLTABLE_GROUP_SIZE;j++)
  157. {
  158. switch(attr_table[i][j].type)
  159. {
  160. case gddApplicationTypeNormal:
  161. case gddApplicationTypeProto:
  162. tn=attr_table[i][j].app_name;
  163. fprintf(fd,"#define gddAppType_%s\t%u\n",
  164. tn,i*APPLTABLE_GROUP_SIZE+j);
  165. if( (dd=attr_table[i][j].proto) )
  166. {
  167. fprintf(fd,"#define gddAppTypeIndex_%s 0\n",tn);
  168. if(dd->isContainer())
  169. describeDD((gddContainer*)dd,fd,1,tn);
  170. // fprintf(fd,"\n");
  171. }
  172. break;
  173. case gddApplicationTypeUndefined: break;
  174. default: break;
  175. }
  176. }
  177. }
  178. }
  179. fprintf(fd,"\n");
  180. }
  181. gddStatus gddApplicationTypeTable::registerApplicationType(
  182. const char* const name,aitUint32& new_app)
  183. {
  184. aitUint32 i,group,app,rapp;
  185. gddStatus rc;
  186. if( (new_app=getApplicationType(name)) )
  187. {
  188. // gddAutoPrint(gddErrorAlreadyDefined);
  189. return gddErrorAlreadyDefined;
  190. }
  191. if(total_registered>max_allowed)
  192. {
  193. gddAutoPrint("gddAppTable::registerApplicationType()",gddErrorAtLimit);
  194. return gddErrorAtLimit;
  195. }
  196. {
  197. epicsGuard < epicsMutex > guard ( sem );
  198. rapp=total_registered++;
  199. }
  200. if((rc=splitApplicationType(rapp,group,app))<0) return rc;
  201. if(attr_table[group])
  202. {
  203. // group already allocated - check is app already refined
  204. if(attr_table[group][app].type!=gddApplicationTypeUndefined)
  205. {
  206. // gddAutoPrint(gddErrorAlreadyDefined);
  207. return gddErrorAlreadyDefined;
  208. }
  209. }
  210. else
  211. {
  212. // group must be allocated
  213. attr_table[group]=new gddApplicationTypeElement[APPLTABLE_GROUP_SIZE];
  214. // initialize each element of the group as undefined
  215. for(i=0;i<APPLTABLE_GROUP_SIZE;i++)
  216. {
  217. attr_table[group][i].type=gddApplicationTypeUndefined;
  218. attr_table[group][i].map=NULL;
  219. }
  220. }
  221. attr_table[group][app].app_name=strDup(name);
  222. attr_table[group][app].type=gddApplicationTypeNormal;
  223. attr_table[group][app].proto=NULL;
  224. attr_table[group][app].free_list=NULL;
  225. new_app=rapp;
  226. // fprintf(stderr,"registered <%s> %d\n",name,(int)new_app);
  227. return 0;
  228. }
  229. // registering a prototype of an empty container causes problems.
  230. // The current implementation does not monitor this so the container
  231. // is not cleared when free. A user may, however, include an empty
  232. // container within a prototype container, and everything will work
  233. // correctly.
  234. gddStatus gddApplicationTypeTable::registerApplicationTypeWithProto(
  235. const char* const name, gdd* protoDD, aitUint32& new_app)
  236. {
  237. aitUint32 group,app,rapp;
  238. aitUint8* blk;
  239. size_t sz;
  240. aitIndex tot;
  241. aitUint16 x;
  242. aitUint16 i;
  243. gddStatus rc;
  244. if( (rc=registerApplicationType(name,new_app)) ) return rc;
  245. rapp=new_app;
  246. protoDD->setApplType(rapp);
  247. splitApplicationType(rapp,group,app);
  248. // user gives me the protoDD, so I should not need to reference it.
  249. // Warning, it the user does unreference() on it unknowningly, it will
  250. // go away and cause big problems
  251. // make sure that the currently registered destructor gets called
  252. // before setting the new one, this should occur in protoDD.
  253. // be sure to copy data from DD and create buffer that can be copied
  254. // easily when user asks for a DD with proto
  255. // important!! put destructor into each managed DD - what if atomic?
  256. // protoDD->registerDestructor(new gddApplicationTypeDestructor(protoDD));
  257. sz=protoDD->getTotalSizeBytes();
  258. blk=new aitUint8[sz];
  259. protoDD->flattenWithAddress(blk,sz,&tot);
  260. attr_table[group][app].proto_size=sz;
  261. attr_table[group][app].total_dds=tot;
  262. protoDD->unreference();
  263. attr_table[group][app].type=gddApplicationTypeProto;
  264. attr_table[group][app].proto=(gdd*)blk;
  265. attr_table[group][app].free_list=NULL;
  266. // create the stupid mapping table - bad implementation for now
  267. attr_table[group][app].map=new aitUint16[total_registered];
  268. attr_table[group][app].map_size=total_registered;
  269. for(i=0;i<total_registered;i++) attr_table[group][app].map[i]=0;
  270. for(i=0;i<tot;i++)
  271. {
  272. x=attr_table[group][app].proto[i].applicationType();
  273. if(x<total_registered) attr_table[group][app].map[x]=i;
  274. }
  275. return 0;
  276. }
  277. aitUint32 gddApplicationTypeTable::getApplicationType(const char* const name) const
  278. {
  279. unsigned i,j,rc;
  280. for(i=0,rc=0;i<max_groups && attr_table[i] && rc==0;i++)
  281. {
  282. for(j=0; j<APPLTABLE_GROUP_SIZE && rc==0; j++)
  283. {
  284. if(attr_table[i][j].type!=gddApplicationTypeUndefined &&
  285. strcmp(name,attr_table[i][j].app_name)==0)
  286. rc=APPLTABLE_GROUP_SIZE*i+j;
  287. }
  288. }
  289. return rc;
  290. }
  291. char* gddApplicationTypeTable::getName(aitUint32 rapp) const
  292. {
  293. aitUint32 group,app;
  294. if(splitApplicationType(rapp,group,app)<0) return NULL;
  295. if(!attr_table[group]) return NULL;
  296. if(attr_table[group][app].type==gddApplicationTypeUndefined) return NULL;
  297. return attr_table[group][app].app_name;
  298. }
  299. gddStatus gddApplicationTypeTable::mapAppToIndex(
  300. aitUint32 c_app, aitUint32 m_app, aitUint32& x)
  301. {
  302. aitUint32 group,app;
  303. gddStatus rc=0;
  304. if((rc=splitApplicationType(c_app,group,app))==0)
  305. {
  306. if(attr_table[group][app].map && m_app<attr_table[group][app].map_size)
  307. {
  308. x=attr_table[group][app].map[m_app];
  309. if(x==0 && c_app!=m_app)
  310. rc=gddErrorNotDefined;
  311. }
  312. else
  313. rc=gddErrorOutOfBounds;
  314. }
  315. // gddAutoPrint("gddAppTable::mapAppToIndex()",rc);
  316. return rc;
  317. }
  318. gdd* gddApplicationTypeTable::getDD(aitUint32 rapp)
  319. {
  320. gdd* dd=NULL;
  321. aitUint32 group,app;
  322. aitUint8* blk;
  323. if(splitApplicationType(rapp,group,app)<0) return NULL;
  324. switch(attr_table[group][app].type)
  325. {
  326. case gddApplicationTypeProto:
  327. attr_table[group][app].sem.lock ();
  328. if( (dd=attr_table[group][app].free_list) )
  329. {
  330. //fprintf(stderr,"Popping a proto DD from list! %d %8.8x\n",app,dd);
  331. attr_table[group][app].free_list=dd->next();
  332. attr_table[group][app].sem.unlock ();
  333. }
  334. else
  335. {
  336. attr_table[group][app].sem.unlock ();
  337. // copy the prototype
  338. blk=new aitUint8[attr_table[group][app].proto_size];
  339. // fprintf(stderr,"Creating a new proto DD! %d %8.8x\n",app,blk);
  340. attr_table[group][app].proto->flattenWithAddress(blk,
  341. attr_table[group][app].proto_size);
  342. dd=(gdd*)blk;
  343. }
  344. dd->registerDestructor(new gddApplicationTypeDestructor(this));
  345. dd->markManaged(); // must be sure to mark the thing as managed!
  346. break;
  347. case gddApplicationTypeNormal:
  348. dd=new gdd(app);
  349. // fprintf(stderr,"Creating a new normal DD! %d\n",app);
  350. break;
  351. case gddApplicationTypeUndefined: dd=NULL; break;
  352. default: break;
  353. }
  354. return dd;
  355. }
  356. gddStatus gddApplicationTypeTable::freeDD(gdd* dd)
  357. {
  358. aitUint32 group,app,i;
  359. gddStatus rc;
  360. if((rc=splitApplicationType(dd->applicationType(),group,app))<0) return rc;
  361. if(attr_table[group][app].type==gddApplicationTypeProto)
  362. {
  363. // this can be time consuming, clear out all user data from the DD
  364. // this is done because we are allowed to register atomic protos
  365. // that user can attach data to - which causes problems because
  366. // the actual structure of the DD is unknown
  367. for(i=1;i<attr_table[group][app].total_dds;i++)
  368. {
  369. dd[i].destroyData();
  370. dd[i].setPrimType(attr_table[group][app].proto[i].primitiveType());
  371. dd[i].setApplType(attr_table[group][app].proto[i].applicationType());
  372. }
  373. // fprintf(stderr,"Adding DD to free_list %d\n",app);
  374. dd->setNext(attr_table[group][app].free_list);
  375. attr_table[group][app].free_list=dd;
  376. }
  377. else if (attr_table[group][app].type==gddApplicationTypeNormal)
  378. {
  379. // fprintf(stderr,"freeDD a normal DD\n");
  380. dd->unreference();
  381. }
  382. else {
  383. fprintf ( stderr,"gddApplicationTypeTable::freeDD - unexpected DD type was %d\n",
  384. attr_table[group][app].type );
  385. }
  386. return 0;
  387. }
  388. gddStatus gddApplicationTypeTable::storeValue(aitUint32 ap, aitUint32 uv)
  389. {
  390. aitUint32 group,app;
  391. gddStatus rc=0;
  392. if((rc=splitApplicationType(ap,group,app))<0) return rc;
  393. if(attr_table[group]==NULL ||
  394. attr_table[group][app].type==gddApplicationTypeUndefined)
  395. rc=gddErrorNotDefined;
  396. else
  397. attr_table[group][app].user_value=uv;
  398. gddAutoPrint("gddAppTable::storeValue()",rc);
  399. return rc;
  400. }
  401. aitUint32 gddApplicationTypeTable::getValue(aitUint32 ap)
  402. {
  403. aitUint32 group,app;
  404. if(splitApplicationType(ap,group,app)<0) return 0;
  405. if(attr_table[group]==NULL ||
  406. attr_table[group][app].type==gddApplicationTypeUndefined)
  407. return 0;
  408. return attr_table[group][app].user_value;
  409. }
  410. // ----------------------smart copy functions------------------------
  411. // the source in the container we must walk through is this called
  412. gddStatus gddApplicationTypeTable::copyDD_src(gdd& dest, const gdd& src)
  413. {
  414. gddStatus rc=0,s;
  415. gddCursor cur;
  416. gdd* dd;
  417. aitIndex index;
  418. // this could be done better (faster) if we did not always recurse for
  419. // each GDD. I could have checked for type container before recursing.
  420. if(src.isContainer())
  421. {
  422. gddContainer& cdd = (gddContainer&) src;
  423. // go through src gdd and map app types to index into dest
  424. cur=cdd.getCursor();
  425. for(dd=cur.first();dd;dd=dd->next()) copyDD_src(dest,*dd);
  426. }
  427. else
  428. {
  429. // find src gdd in dest container and just do put()
  430. s=mapAppToIndex(dest.applicationType(),src.applicationType(),index);
  431. if(s==0)
  432. rc=dest[index].put(&src);
  433. }
  434. return rc;
  435. }
  436. // the destination in the container we must walk through is this called
  437. gddStatus gddApplicationTypeTable::copyDD_dest(gdd& dest, const gdd& src)
  438. {
  439. gddStatus rc=0,s;
  440. gddCursor cur;
  441. gdd* dd;
  442. aitIndex index;
  443. if(dest.isContainer())
  444. {
  445. gddContainer& cdd = (gddContainer&) dest;
  446. // go through dest gdd and map app types to index into src
  447. cur=cdd.getCursor();
  448. for(dd=cur.first();dd;dd=dd->next()) copyDD_dest(*dd,src);
  449. }
  450. else
  451. {
  452. // find dest gdd in src container and just do put()
  453. s=mapAppToIndex(src.applicationType(),dest.applicationType(),index);
  454. if(s==0)
  455. rc=dest.put(&src[index]);
  456. }
  457. return rc;
  458. }
  459. gddStatus gddApplicationTypeTable::smartCopy(gdd* dest, const gdd* src)
  460. {
  461. gddStatus rc = gddErrorNotAllowed;
  462. // only works with managed containers because app table mapping
  463. // feature is used.
  464. if(dest->isContainer() && dest->isManaged())
  465. rc=copyDD_src(*dest,*src);
  466. else if(src->isContainer() && src->isManaged())
  467. rc=copyDD_dest(*dest,*src);
  468. else if(!src->isContainer() && !dest->isContainer()) {
  469. if ( src->applicationType() == dest->applicationType() ) {
  470. rc=dest->put(src); // both are not containers, let gdd handle it
  471. }
  472. else {
  473. rc=gddErrorNotDefined;
  474. }
  475. }
  476. gddAutoPrint("gddAppTable::smartCopy()",rc);
  477. return rc;
  478. }
  479. // ----------------------smart reference functions------------------------
  480. // the source in the container we must walk through is this called
  481. gddStatus gddApplicationTypeTable::refDD_src(gdd& dest, const gdd& src)
  482. {
  483. gddStatus rc=0,s;
  484. gddCursor cur;
  485. gdd* dd;
  486. aitIndex index;
  487. // this could be done better (faster) if we did not always recurse for
  488. // each GDD. I could have checked for type container before recursing.
  489. if(src.isContainer())
  490. {
  491. gddContainer& cdd=(gddContainer&)src;
  492. // go through src gdd and map app types to index into dest
  493. cur=cdd.getCursor();
  494. for(dd=cur.first();dd;dd=dd->next()) refDD_src(dest,*dd);
  495. }
  496. else
  497. {
  498. // find src gdd in dest container and just do put()
  499. s=mapAppToIndex(dest.applicationType(),src.applicationType(),index);
  500. if(s==0)
  501. rc=dest[index].putRef(&src);
  502. }
  503. return rc;
  504. }
  505. // the destination in the container we must walk through is this called
  506. gddStatus gddApplicationTypeTable::refDD_dest(gdd& dest, const gdd& src)
  507. {
  508. gddStatus rc=0,s;
  509. gddCursor cur;
  510. gdd* dd;
  511. aitIndex index;
  512. if(dest.isContainer())
  513. {
  514. gddContainer& cdd=(gddContainer&)dest;
  515. // go through dest gdd and map app types to index into src
  516. cur=cdd.getCursor();
  517. for(dd=cur.first();dd;dd=dd->next()) refDD_dest(*dd,src);
  518. }
  519. else
  520. {
  521. // find dest gdd in src container and just do put()
  522. s=mapAppToIndex(src.applicationType(),dest.applicationType(),index);
  523. if(s==0)
  524. rc=dest.putRef(&src[index]);
  525. }
  526. return rc;
  527. }
  528. gddStatus gddApplicationTypeTable::smartRef(gdd* dest, const gdd* src)
  529. {
  530. gddStatus rc=0;
  531. // only works with managed containers because app table mapping
  532. // feature is used.
  533. if(dest->isContainer() && dest->isManaged())
  534. rc=refDD_src(*dest,*src);
  535. else if(src->isContainer() && src->isManaged())
  536. rc=refDD_dest(*dest,*src);
  537. else if(!src->isContainer() && !dest->isContainer())
  538. rc=dest->putRef(src); // both are not containers, let gdd handle it
  539. else
  540. rc=gddErrorNotAllowed;
  541. gddAutoPrint("gddAppTable::smartRef()",rc);
  542. return rc;
  543. }