home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / lang / cplus / 18641 < prev    next >
Encoding:
Text File  |  1993-01-02  |  14.1 KB  |  538 lines

  1. Xref: sparky comp.lang.c++:18641 alt.sources:2911
  2. Newsgroups: comp.lang.c++,alt.sources
  3. Path: sparky!uunet!think.com!enterpoop.mit.edu!micro-heart-of-gold.mit.edu!uw-beaver!cornell!moudgill
  4. From: moudgill@cs.cornell.edu ( Mayan Moudgill)
  5. Subject: Code for adding chunk based memory management to C++ classes
  6. Message-ID: <1993Jan3.021011.2968@cs.cornell.edu>
  7. Summary: Two mechanisms for adding free-list based memory management to a class
  8. Keywords: memory management, free list, blocks, c++, templates, cfront 3.0
  9. Organization: Cornell Univ. CS Dept, Ithaca NY 14853
  10. Date: Sun, 3 Jan 1993 02:10:11 GMT
  11. Lines: 525
  12.  
  13. I've written to easy to use "bolt-on" classes that use templates and
  14. inheritance. These classes provide overloaded new() and delete() operators
  15. for the class that implement free list based memory management.
  16.  
  17. The memory management routines keep a list of blocks of the right
  18. size around. Every time a block is "delete'd" it is added
  19. to that list. A request for a block is satisfied from the
  20. free list (if there is a block on the list), or malloc'd from
  21. the system.
  22.  
  23. The two implementations are PerClassFreeList and PerSizeFreeList.
  24. The first maintains a free list per class. The second
  25. maintains a free list per size (thus, if more than one class had the same
  26. size, they would all use the same free list).
  27.  
  28. To add PerClassFreeList memory management to a class:
  29.  
  30.    #include "PerClassFreeList.H"
  31.  
  32.    class Foo : public PerClassFreeList<Foo> {
  33.      ...
  34.      /* Foo has no new() or delete() operations defined */
  35.    };
  36.  
  37. The base class PerClassFreeList<Foo> provides new() and delete()
  38. operators. It also provides a free() operator that frees
  39. (in the sense of malloc) the entire free list, and free(n) that
  40. frees at most n blocks from the free list.
  41.  
  42. To add PerSizeFreeList memory management to a class:
  43.  
  44.    #include "PerSizeFreeList1.H"
  45.  
  46.    class Foo : public PerSizeFreeList<Foo> {
  47.      ...
  48.      /* Foo has no new() or delete() operations defined */
  49.    };
  50.  
  51.    #include "PerSizeFreeList2.H"
  52.  
  53. Notice the location of the two include files. They *MUST* be included
  54. as shown---PerSizeFreeList1.H before, and PerSizeFreeList2.H after
  55. the object being declared.
  56.  
  57. Any comments/suggestions will be extremely welcome.
  58. :)
  59. Mayan
  60.  
  61. #! /bin/sh
  62. # This is a shell archive, meaning:
  63. # 1. Remove everything above the #! /bin/sh line.
  64. # 2. Save the resulting text in a file.
  65. # 3. Execute the file with /bin/sh (not csh) to create the files:
  66. #    Size/PerSizeFreeList-Test.C
  67. #    Size/PerSizeFreeList1.H
  68. #    Size/PerSizeFreeList2.C
  69. #    Size/PerSizeFreeList2.H
  70. #    Class/PerClassFreeList-Test.C
  71. #    Class/PerClassFreeList.C
  72. #    Class/PerClassFreeList.H
  73. # This archive created: Sat Jan  2 20:49:40 1993
  74. export PATH; PATH=/bin:$PATH
  75. if test -f 'Size/PerSizeFreeList-Test.C'
  76. then
  77.     echo shar: will not over-write existing file "'Size/PerSizeFreeList-Test.C'"
  78. else
  79. sed 's/^X//' << \SHAR_EOF > 'Size/PerSizeFreeList-Test.C'
  80. X#include <iostream.h>
  81. X#include <string.h>
  82. X#include <iostream.h>
  83. X#include "PerSizeFreeList1.H"
  84. X
  85. Xclass Student : public PerSizeFreeList<Student> {
  86. Xprivate:
  87. X    char   _name[36];
  88. X    short  _age;
  89. Xpublic:
  90. X       Student(char * name,  int age)
  91. X      : _age(age)
  92. X      {
  93. X     strncpy(_name,name,35);
  94. X     _name[35] = 0;
  95. X      }
  96. X
  97. Xfriend ostream& operator<<(ostream& o, Student* s)
  98. X   {
  99. X   void * t = s;
  100. X      o << t;
  101. X      o << ':';
  102. X      o <<  s->_name;
  103. X      o << ' ';
  104. X      o << s->_age;
  105. X      return o;
  106. X   }
  107. X};
  108. X
  109. X#include "PerSizeFreeList2.H"
  110. Xtypedef PerSizeFreeList_Imp<24u> dummy;
  111. X
  112. X
  113. Xmain()
  114. X{
  115. XStudent * s1 = new Student("alpha", 10);
  116. XStudent * s2 = new Student("beta", 20);
  117. X   cout << s1 << '\n' << s2 << endl;
  118. X   delete s1;
  119. XStudent * s3 = new Student("nu", 13);
  120. XStudent * s4 = new Student("mu", 23);
  121. X   cout << s3 << '\n' << s4 << endl;
  122. X   cout << Student::free() << endl;
  123. X   delete s2;
  124. X   delete s3;
  125. X   delete s4;
  126. X   cout << Student::free(1) << endl;
  127. X   cout << Student::free() << endl;
  128. X}
  129. SHAR_EOF
  130. if test 979 -ne "`wc -c < 'Size/PerSizeFreeList-Test.C'`"
  131. then
  132.     echo shar: error transmitting "'Size/PerSizeFreeList-Test.C'" '(should have been 979 characters)'
  133. fi
  134. fi # end of overwriting check
  135. if test -f 'Size/PerSizeFreeList1.H'
  136. then
  137.     echo shar: will not over-write existing file "'Size/PerSizeFreeList1.H'"
  138. else
  139. sed 's/^X//' << \SHAR_EOF > 'Size/PerSizeFreeList1.H'
  140. X#ifndef mPERSIZEFREELIST1_H
  141. X#define mPERSIZEFREELIST1_H
  142. X
  143. X/* 26th December, 1992 Mayan Moudgill.
  144. X   I'm designing a class for "bolting-on" to an existing class,
  145. X   so as to give it free list based memory management.
  146. X   (I would use Mixin instead of Bolton except that the Mixin is
  147. X   used for _dynamic_ inheritance.)
  148. X
  149. X
  150. X   Purpose:
  151. X   Given a class Foo whose memory is to be managed in the
  152. X   following fashion:
  153. X      1. delete(f) takes f (of type Foo *), and adds it to a free list
  154. X      2. new() returns first member of free list (if any) else allocates
  155. X        from heap
  156. X
  157. X   Additionally, the memory management routines contain
  158. X      1. free() returns all free list members to heap
  159. X      2. free(n) return n free list members to heap
  160. X   They both return the number actually freed.
  161. X   
  162. X   Usage:
  163. X      #include "PerSizeFreeList1.H"
  164. X
  165. X      class Foo : PerSizeFreeList<Foo> {
  166. X     .
  167. X     .
  168. X     .
  169. X      };
  170. X
  171. X      #include "PerSizeFreeList2.H"
  172. X
  173. X   This class differs from PerClassFreeList in that there is one free_list
  174. X   per *size* of allocated, not one per class. Thus, if you have 2 classes,
  175. X   both of the same size, they will use the same free list if memory operations
  176. X   are bolted on using PerSizeFreeList.
  177. X*/
  178. X
  179. X/* There is an extremely nasty bug in cfront 3.0.1 which forces the
  180. X   use of the _dispatch() to actually call the right functions from
  181. X   PerSizeFreeList_Imp (see PerSizeFreeList2.H). The problem
  182. X   causes all but the first member function in ParSizeFreeList to use
  183. X   the wrong sized PerSizeFreeList_Imp. To check wether your complier
  184. X   has a similar bug define BUG_CONFIRM, compile and run, and see whether
  185. X   all the sizes are the same.
  186. X
  187. X   A workaround (sent by USL support) has been applied. It may or
  188. X   may not work with your compiler.
  189. X*/
  190. X
  191. X/* uncomment next line, compile and run to see if bug exists */
  192. X// #define BUG_CONFIRM
  193. X
  194. X#include <malloc.h>
  195. X
  196. Xtemplate<class T>
  197. Xclass PerSizeFreeList {
  198. Xprivate:
  199. Xpublic:
  200. X   inline
  201. X   void *            operator new(size_t);
  202. X   inline
  203. X   void              operator delete(void *);
  204. X   static inline
  205. X   int               free();
  206. X   static inline
  207. X   int               free(unsigned);
  208. X};
  209. X
  210. X#endif
  211. SHAR_EOF
  212. if test 2142 -ne "`wc -c < 'Size/PerSizeFreeList1.H'`"
  213. then
  214.     echo shar: error transmitting "'Size/PerSizeFreeList1.H'" '(should have been 2142 characters)'
  215. fi
  216. fi # end of overwriting check
  217. if test -f 'Size/PerSizeFreeList2.C'
  218. then
  219.     echo shar: will not over-write existing file "'Size/PerSizeFreeList2.C'"
  220. else
  221. sed 's/^X//' << \SHAR_EOF > 'Size/PerSizeFreeList2.C'
  222. X#ifndef mPERSIZEFREELIST2_H
  223. X#include "PerSizeFreeList2.H"
  224. X#endif
  225. X
  226. Xtemplate<size_t size>
  227. Xvoid *   PerSizeFreeList_Imp<size>::_free_list = 0;
  228. X
  229. Xtemplate<size_t size>
  230. Xint      PerSizeFreeList_Imp<size>::free()
  231. X{
  232. Xvoid *   p = _free_list;
  233. Xint      n = 0;
  234. X#ifdef BUG_CONFIRM
  235. X   cerr << "free():  " << size << endl;
  236. X#endif
  237. X   while( p != 0 ) {
  238. X   void *   q = p;
  239. X      p = *((void **) p);
  240. X      ::free(q);
  241. X      n++;
  242. X   }
  243. X   _free_list = 0;
  244. X   return n;
  245. X}
  246. X
  247. Xtemplate<size_t size>
  248. Xint      PerSizeFreeList_Imp<size>::free(unsigned num)
  249. X{
  250. Xvoid *   p = _free_list;
  251. Xint      n = 0;
  252. X#ifdef BUG_CONFIRM
  253. X   cerr << "free(n): " << size << endl;
  254. X#endif
  255. X   while( p != 0 && n < num) {
  256. X   void *   q = p;
  257. X      p = *((void **) p);
  258. X      ::free(q);
  259. X      n++;
  260. X   }
  261. X   _free_list = p;
  262. X   return n;
  263. X}
  264. SHAR_EOF
  265. if test 778 -ne "`wc -c < 'Size/PerSizeFreeList2.C'`"
  266. then
  267.     echo shar: error transmitting "'Size/PerSizeFreeList2.C'" '(should have been 778 characters)'
  268. fi
  269. fi # end of overwriting check
  270. if test -f 'Size/PerSizeFreeList2.H'
  271. then
  272.     echo shar: will not over-write existing file "'Size/PerSizeFreeList2.H'"
  273. else
  274. sed 's/^X//' << \SHAR_EOF > 'Size/PerSizeFreeList2.H'
  275. X#ifndef mPERSIZEFREELIST2_H
  276. X#define mPERSIZEFREELIST2_H
  277. X
  278. X#ifndef mPERSIZEFREELIST1_H
  279. X#include "PerSizeFreeList1.H"
  280. X#endif
  281. X
  282. X#include <iostream.h>
  283. X
  284. X/* 26th December, 1992 Mayan Moudgill.
  285. X   See PerClassFreeList1.H for details
  286. X*/
  287. X
  288. Xtemplate <size_t size>
  289. Xclass PerSizeFreeList_Imp {
  290. Xprivate:
  291. X   static void *     _free_list;
  292. Xpublic:
  293. X   static int        free();
  294. X   static int        free(unsigned);
  295. X
  296. X   static
  297. X   inline void *     alloc(size_t sz)
  298. X      {
  299. X      void *  obj;
  300. X#ifdef BUG_CONFIRM
  301. X     cerr << "alloc:   " << size << endl;
  302. X#endif
  303. X     (void) sz;
  304. X     if( _free_list == 0 ) {
  305. X        obj = malloc(size);              // is sz+sz%4 == size? it should.
  306. X     }
  307. X     else {
  308. X        obj = _free_list;
  309. X        _free_list = *((void **) obj); // Its not type safe--so what?
  310. X     }
  311. X     return obj;
  312. X      }
  313. X   static
  314. X   inline void       dealloc(void * obj)
  315. X      {
  316. X#ifdef BUG_CONFIRM
  317. X     cerr << "dealloc: " << size << endl;
  318. X#endif
  319. X     *((void **) obj) = _free_list;
  320. X     _free_list = obj;                 // Neither is this--so what?
  321. X      }
  322. X};
  323. X
  324. Xtemplate<class T>
  325. Xvoid *    PerSizeFreeList<T>::operator new(size_t sz)
  326. X{
  327. X   return PerSizeFreeList_Imp<unsigned(sizeof(T))>::alloc(sz);
  328. X}
  329. X
  330. Xtemplate<class T>
  331. Xvoid      PerSizeFreeList<T>::operator delete(void * obj)
  332. X{
  333. X   PerSizeFreeList_Imp<unsigned(sizeof(T))>::dealloc(obj);
  334. X}
  335. X
  336. Xtemplate<class T>
  337. Xint       PerSizeFreeList<T>::free()
  338. X{
  339. X   return PerSizeFreeList_Imp<unsigned(sizeof(T))>::free();
  340. X}
  341. X
  342. Xtemplate<class T>
  343. Xint       PerSizeFreeList<T>::free(unsigned n)
  344. X{
  345. X   return PerSizeFreeList_Imp<unsigned(sizeof(T))>::free(n);
  346. X}
  347. X
  348. X#endif
  349. SHAR_EOF
  350. if test 1548 -ne "`wc -c < 'Size/PerSizeFreeList2.H'`"
  351. then
  352.     echo shar: error transmitting "'Size/PerSizeFreeList2.H'" '(should have been 1548 characters)'
  353. fi
  354. fi # end of overwriting check
  355. if test -f 'Class/PerClassFreeList-Test.C'
  356. then
  357.     echo shar: will not over-write existing file "'Class/PerClassFreeList-Test.C'"
  358. else
  359. sed 's/^X//' << \SHAR_EOF > 'Class/PerClassFreeList-Test.C'
  360. X#include "PerClassFreeList.H"
  361. X#include <string.h>
  362. X#include <iostream.h>
  363. X
  364. Xclass Student : public PerClassFreeList<Student> {
  365. Xprivate:
  366. X    char   _name[36];
  367. X    short  _age;
  368. Xpublic:
  369. X       Student(char * name,  int age)
  370. X      : _age(age)
  371. X      {
  372. X     strncpy(_name,name,35);
  373. X     _name[35] = 0;
  374. X      }
  375. X
  376. Xfriend ostream& operator<<(ostream& o, Student& s)
  377. X   {
  378. X      /* broken up so that it gets inlined */
  379. X      o << s._name;
  380. X      o << ' ';
  381. X      o << s._age;
  382. X      return o;
  383. X   }
  384. Xfriend ostream& operator<<(ostream& o, Student* s)
  385. X   {
  386. X      o << (void *)s;
  387. X      o << ':';
  388. X      o <<  s->_name;
  389. X      o << ' ';
  390. X      o << s->_age;
  391. X      return o;
  392. X   }
  393. X};
  394. X
  395. Xmain()
  396. X{
  397. XStudent * s1 = new Student("alpha", 10);
  398. XStudent * s2 = new Student("beta", 20);
  399. X   cout << s1 << '\n' << s2 << endl;
  400. X   delete s1;
  401. XStudent * s3 = new Student("nu", 13);
  402. XStudent * s4 = new Student("mu", 23);
  403. X   cout << s3 << '\n' << s4 << endl;
  404. X   cout << Student::free() << endl;
  405. X   delete s2;
  406. X   delete s3;
  407. X   delete s4;
  408. X   cout << Student::free(1) << endl;
  409. X   cout << Student::free() << endl;
  410. X}
  411. SHAR_EOF
  412. if test 1055 -ne "`wc -c < 'Class/PerClassFreeList-Test.C'`"
  413. then
  414.     echo shar: error transmitting "'Class/PerClassFreeList-Test.C'" '(should have been 1055 characters)'
  415. fi
  416. fi # end of overwriting check
  417. if test -f 'Class/PerClassFreeList.C'
  418. then
  419.     echo shar: will not over-write existing file "'Class/PerClassFreeList.C'"
  420. else
  421. sed 's/^X//' << \SHAR_EOF > 'Class/PerClassFreeList.C'
  422. X#ifndef mPERCLASSFREELIST_H
  423. X#include "PerClassFreeList.H"
  424. X#endif
  425. X
  426. Xtemplate<class T>
  427. Xvoid *   PerClassFreeList<T>::_free_list = 0;
  428. X
  429. Xtemplate<class T>
  430. Xint      PerClassFreeList<T>::free()
  431. X{
  432. Xvoid *   p = _free_list;
  433. Xint      n = 0;
  434. X   while( p != 0 ) {
  435. X   void *   q = p;
  436. X      p = *((void **) p);
  437. X      ::free(q);
  438. X      n++;
  439. X   }
  440. X   _free_list = 0;
  441. X   return n;
  442. X}
  443. X
  444. Xtemplate<class T>
  445. Xint      PerClassFreeList<T>::free(unsigned num)
  446. X{
  447. Xvoid *   p = _free_list;
  448. Xint      n = 0;
  449. X   while( p != 0 && n < num) {
  450. X   void *   q = p;
  451. X      p = *((void **) p);
  452. X      ::free(q);
  453. X      n++;
  454. X   }
  455. X   _free_list = p;
  456. X   return n;
  457. X}
  458. SHAR_EOF
  459. if test 616 -ne "`wc -c < 'Class/PerClassFreeList.C'`"
  460. then
  461.     echo shar: error transmitting "'Class/PerClassFreeList.C'" '(should have been 616 characters)'
  462. fi
  463. fi # end of overwriting check
  464. if test -f 'Class/PerClassFreeList.H'
  465. then
  466.     echo shar: will not over-write existing file "'Class/PerClassFreeList.H'"
  467. else
  468. sed 's/^X//' << \SHAR_EOF > 'Class/PerClassFreeList.H'
  469. X#ifndef mPERCLASSFREELIST_H
  470. X#define mPERCLASSFREELIST_H
  471. X
  472. X/* 26th December, 1992 Mayan Moudgill.
  473. X   I'm designing a class for "bolting-on" to an existing class,
  474. X   so as to give it free list based memory management.
  475. X   (I would use Mixin instead of Bolton except that the Mixin is
  476. X   used for _dynamic_ inheritance.)
  477. X
  478. X   Purpose:
  479. X   Given a class Foo whose memory is to be managed in the
  480. X   following fashion:
  481. X      1. delete(f) takes f (of type Foo *), and adds it to a free list
  482. X      2. new() returns first member of free list (if any) else allocates
  483. X        from heap
  484. X
  485. X   Additionally, the memory management routines contain
  486. X      1. free() returns all free list members to heap
  487. X      2. free(n) return n free list members to heap
  488. X   They both return the number actually freed.
  489. X   
  490. X   Usage:
  491. X      #include "PerClassFreeList.H"
  492. X
  493. X      class Foo : PerClassFreeList<Foo> {
  494. X     .
  495. X     .
  496. X     .
  497. X      };
  498. X*/
  499. X
  500. X#include <malloc.h>
  501. X
  502. Xtemplate <class T>
  503. Xclass PerClassFreeList {
  504. Xprivate:
  505. X   static void *     _free_list;
  506. Xpublic:
  507. X   static int        free();
  508. X   static int        free(unsigned);
  509. X
  510. X   inline void *     operator new(size_t sz)
  511. X      {
  512. X      void *  obj;
  513. X     if( _free_list == 0 ) {
  514. X        obj = malloc(sz);
  515. X     }
  516. X     else {
  517. X        obj = _free_list;
  518. X        _free_list = *((void **) obj); // Its not type safe--so what?
  519. X     }
  520. X     return obj;
  521. X      }
  522. X   inline void       operator delete(void * obj)
  523. X      {
  524. X     *((void **) obj) = _free_list;
  525. X     _free_list = obj;                 // Neither is this--so what?
  526. X      }
  527. X};
  528. X
  529. X#endif
  530. SHAR_EOF
  531. if test 1502 -ne "`wc -c < 'Class/PerClassFreeList.H'`"
  532. then
  533.     echo shar: error transmitting "'Class/PerClassFreeList.H'" '(should have been 1502 characters)'
  534. fi
  535. fi # end of overwriting check
  536. #    End of shell archive
  537. exit 0
  538.