home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / IDIOMS.ZIP / ESHAPE.C < prev    next >
C/C++ Source or Header  |  1991-12-04  |  7KB  |  230 lines

  1. /* Copyright (c) 1992 by AT&T Bell Laboratories. */
  2. /* Advanced C++ Programming Styles and Idioms */
  3. /* James O. Coplien */
  4. /* All rights reserved. */
  5.  
  6. //************************************************************//
  7. //                                                            //
  8. //     F I L E :    E S H A P E . C                           //
  9. //                                                            //
  10. //         Code for class Shape                               //
  11. //                                                            //
  12. //************************************************************//
  13.  
  14. #include "eshape.h"
  15. #ifndef _SHAPEREP_H
  16. #include "eshaprp.h"
  17. #endif
  18. #ifndef _TRIANGLE_H
  19. #include "etringl.h"
  20. #endif
  21. #ifndef _RECTANGLE_H
  22. #include "erect.h"
  23. #endif
  24. #include "List.h"
  25.  
  26. // Class Shape does much of the memory management work for
  27. // all Shapes.
  28.  
  29. // Handles to all extant Shape instances everywhere
  30. List<Topp> *Shape::allShapes = 0;
  31.  
  32. // List of all Exemplars that are made for subclasses
  33. // of class ShapeRep
  34. List<Thingp> *Shape::allShapeExemplars = 0;
  35.  
  36. // Shape exemplar
  37. extern Shape *shape = 0;
  38.  
  39. void
  40. Shape::init() {
  41.     // initializes all global data structures for
  42.     // Shapes, so main can orchestrate order of
  43.     // initialization
  44.     allShapes = new List<Topp>;
  45.     allShapeExemplars = new List<Thingp>;
  46.     shape = new Shape;
  47.  
  48.     // orchestrate initialization of ShapeRep types
  49.     ShapeRep::init();
  50.     Triangle::init();
  51.     Rectangle::init();
  52. }
  53.  
  54. Top *
  55. Shape::doit() {
  56.     // handy function that can be reloaded by users
  57.     // and used as a utility
  58.     return 0;
  59. }
  60.  
  61. Shape::Shape() {
  62.     // default shape constructor
  63.     Topp tp = this;
  64.  
  65.     // log self in allShapes list
  66.     allShapes->put(tp);
  67.  
  68.     // we don't know what kind of Shape:
  69.     // just make it a dummy for now
  70.     rep = new ShapeRep;
  71. }
  72.  
  73. Shape::~Shape() {
  74.     Listiter<Topp> tp = *allShapes;
  75.     Topp t;
  76.     for ( tp.reset(); tp.next(t); ) {
  77.         if (t == (Thingp)this) {
  78.             tp.remove_prev(t);
  79.             break;
  80.         }
  81.     }
  82.     if (allShapes->length() == 0) {
  83.         // last gasp garbage collection
  84.         gc();
  85.     }
  86. }
  87.  
  88. Shape::Shape(Shape &x) {
  89.     // copy constructor
  90.     Thingp tp = (Thingp) this;
  91.  
  92.     // log self with allShapes list
  93.     allShapes->put(tp);
  94.  
  95.     // just point to parameter's rep
  96.     rep = x.rep;
  97. }
  98.  
  99. Shape::Shape(ShapeRep &x) {
  100.     // build a Shape from a ShapeRep:  used
  101.     // mainly to convert the ShapeReps built
  102.     // by Triangle, Rectangle, etc., into
  103.     // Shapes that are returned to the users
  104.     // (users never see the inner classes)
  105.     Topp tp = this;
  106.  
  107.     // log self with allShapes
  108.     allShapes->put(tp);
  109.  
  110.     // note:  no ->ref();  caller must yield copy!
  111.     rep = &x;
  112. }
  113.  
  114. Shape&
  115. Shape::operator=(Shape &x) {
  116.     // assignment of shapes.  Don't worry about what
  117.     // rep used to point to:  garbage collection
  118.     // will get it.
  119.     rep = x.rep;
  120.     return *this;
  121. }
  122.  
  123. Top *
  124. Shape::type() {
  125.     // A Shape's type is its own exemplar
  126.     return shape;
  127. }
  128.  
  129. void
  130. Shape::dataUpdate(Thingp &oldExemplar,
  131.                                const Thingp newExemplar) {
  132.     // This function allows class replacement of a subclass
  133.     // of ShapeRep.  It assumes that all virtual functions
  134.     // have been recompiled and incrementally loaded
  135.     // against the new class definition.  It also assumes
  136.     // the programmer has provided a cutover function
  137.     // which, when invoked on an old instance of the
  138.     // shape, will return a pointer to a semantically
  139.     // equivalent copy.
  140.  
  141.     ShapeRep* savedExemplar = (ShapeRep*) oldExemplar;
  142.     Topp tp = 0;
  143.  
  144.     // get a static copy to iterate over;  we don't
  145.     // want to catch new things as they are added!
  146.     // The copy will be reclaimed on return from this
  147.     // member function
  148.     List<Topp> staticCopy = *allShapes;
  149.  
  150.     // change exemplars
  151.     oldExemplar = newExemplar;
  152.  
  153.     // cut over all subobjects for this exemplar
  154.     Listiter<Topp> shapeIter = staticCopy;
  155.     for ( shapeIter.reset(); shapeIter.next(tp);  ) {
  156.         Shapepointer sp = (Shapepointer)tp;
  157.         if (sp->rep->type() == (Thingp)savedExemplar) {
  158.             if (sp->rep->docutover()) {
  159.                 ShapeRep *oldrep = sp->rep;
  160.                 printf("\tchanging shape 0x%x to new format\n",
  161.                     oldrep);
  162.                 sp->rep = (ShapeRep*)sp->rep->cutover();
  163.  
  164.                 // must manually clean up old rep here:
  165.                 // garbage collector won't get it, as it's
  166.                 // about to go out of the arena
  167.                 oldrep->ShapeRep::~ShapeRep();
  168.             }
  169.         }
  170.     }
  171.  
  172.     // Remove this exemplar from Shape's list of all exemplars
  173.     // in the world--it is no longer participating as part
  174.     // of this abstract base exemplar
  175.     UnRegister(savedExemplar);
  176. }
  177.  
  178. void
  179. Shape::gc() {
  180.     // Shape garbage collector: orchestrates collection
  181.     // of unreachable objects for all subclasses of
  182.     // ShapeRep.  Uses Baker's algorithm
  183.  
  184.     // First half of Baker:  mark all reachable shapes
  185.     Listiter<Topp> shapeIter = *allShapes;
  186.     shapeIter.reset();
  187.     for ( Topp tp = 0; shapeIter.next(tp);  ) {
  188.         Shapepointer sp = (Shapepointer)tp;
  189.         if (sp->rep) {
  190.             sp->rep->mark();
  191.         }
  192.     }        
  193.  
  194.     // Second half of Baker:  sweep.  Let individual
  195.     // subtypes each do their own sweep of their own
  196.     // pools, using their own gc member function.
  197.     Listiter<Thingp> shapeExemplarIter = *allShapeExemplars;
  198.     shapeExemplarIter.reset();
  199.     for ( Thingp anExemplar = 0;
  200.                 shapeExemplarIter.next(anExemplar);  ) {
  201.         ShapeRep *thisExemplar = (ShapeRep*)anExemplar;
  202.         thisExemplar->gc(0);
  203.     }
  204.  
  205.     // Baker swap of To and From spaces
  206.     ShapeRep::FromSpace ^= 1;
  207.     ShapeRep::ToSpace ^= 1;
  208. }
  209.  
  210. void
  211. Shape::Register(ShapeRep *s) {
  212.     // routine by which ShapeRep exemplars
  213.     // register themselves with Shape
  214.     Thingp tp = s;
  215.     allShapeExemplars->put(tp);
  216. }
  217.  
  218. void
  219. Shape::UnRegister(ShapeRep *s) {
  220.     // Allows an exemplar to unregister itself
  221.     // (as when it is replaced by a new version)
  222.     Thingp tp = 0;
  223.     Listiter<Thingp> shapeIter = *allShapeExemplars;
  224.     for ( shapeIter.reset(); shapeIter.next(tp); ) {
  225.         if (tp == (Thingp)s) {
  226.             shapeIter.remove_prev(tp);
  227.         }
  228.     }
  229. }
  230.