2 * $XConsortium: FolioObject.C /main/5 1996/10/04 11:23:44 drk $
4 * Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
5 * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
6 * States. Use of a copyright notice is precautionary only and does not
7 * imply publication or disclosure.
9 * This software contains confidential information and trade secrets of HaL
10 * Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
11 * without the prior express written permission of HaL Computer Systems, Inc.
13 * RESTRICTED RIGHTS LEGEND
14 * Use, duplication, or disclosure by the Government is subject to
15 * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
16 * Technical Data and Computer Software clause at DFARS 252.227-7013.
17 * HaL Computer Systems, Inc.
18 * 1315 Dell Avenue, Campbell, CA 95008
26 INIT_CLASS (FolioObject);
28 // private class to hold dependent data
29 // NOTE: To avoid overhead there should be a class below FolioObject
30 // to hold the dependency type stuff called "??"
31 // Need to fix this up later.
32 // BaseObject -> Object -> Hasbable -> etc.
33 // This may not be a problem once we have templates, because then we can
34 // stick anything in our list.
39 Dependent (Dependent **pre_next, Dependent *next,
40 FolioObject *dependent, FolioObject *folio_object,
41 notify_handler_t handler,
42 u_int notify_type, void *dependent_data)
43 : f_pre_next (pre_next), f_next (next),
44 f_dependent (dependent), f_folio_object (folio_object),
46 f_notify_type (notify_type), f_dependent_data (dependent_data)
47 { if (next) next->f_pre_next = &f_next; }
48 FolioObject *f_dependent;
49 FolioObject *f_folio_object;
50 notify_handler_t f_handler;
52 void *f_dependent_data;
53 Dependent **f_pre_next;
56 void call (FolioObject *obj, void *notify_data);
62 ON_DEBUG(printf ("@** assigning: f_dependent = %p\n", f_next));
64 if (f_next) f_next->f_pre_next = f_pre_next;
69 Dependent::call (FolioObject *obj, void *notify_data)
71 (f_dependent->*f_handler)(obj, f_notify_type, notify_data, f_dependent_data);
78 DependOnList (DependOnList *next, Dependent *d)
79 : f_next (next), f_dependent_obj (d)
81 void delete_dependent();
82 Dependent *f_dependent_obj;
87 DependOnList::delete_dependent()
89 f_dependent_obj->release();
93 // /////////////////////////////////////////////////////////////////
95 // /////////////////////////////////////////////////////////////////
97 FolioObject::FolioObject()
98 : f_dependents (NULL), f_depend_on_list (NULL)
100 // Initialize status to reasonable value.
101 // Subclasses only need to change on creation if an error occurs.
102 setStatus (eSuccess);
103 f_initialized = FALSE;
107 // /////////////////////////////////////////////////////////////////
109 // /////////////////////////////////////////////////////////////////
111 FolioObject::~FolioObject()
114 release_dependents();
115 release_depend_on_list();
119 // /////////////////////////////////////////////////////////////////
120 // notify - this object changed
121 // /////////////////////////////////////////////////////////////////
124 FolioObject::notify (u_int notify_type, void *notify_data)
128 // NOTE: This function is temporarily hacked up to get the next
129 // entry in the list before calling the function because it
130 // might be a destroy message which causes the object notified
131 // to destroy itself and delete the current Dependent object,
132 // leaving d pointing into freed memory. next could also point
133 // into freed memory, so for now we need to make sure that any
134 // notification that deletes the target object is at the end
135 // of the list of dependents. This is done by adding first, since
136 // Dependent records are added to the start of the list.
137 // The Right fix for this is probably to pull items from the "to check"
138 // list and move them to a "called" list as they are called. After
139 // each call, d should start at the beginning of the "to check" list
140 // since it will be the only memory guaranteed to be around.
142 for (d = f_dependents; d != NULL;)
145 if (d->f_notify_type == notify_type)
146 d->call (this, notify_data);
152 // /////////////////////////////////////////////////////////////////
153 // add_dependent - add a new dependent
154 // /////////////////////////////////////////////////////////////////
157 #if defined(SC3) || defined(__osf__) || defined(USL)
158 FolioObject::add_dependent (FolioObject *dependent, notify_handler_t handler,
160 FolioObject::add_dependent (void *dependent, notify_handler_t handler,
162 u_int notify_type, void *dependent_data)
164 // Adds to begining because that's easiest.
165 #if defined(SC3) || defined(__osf__) || defined(USL)
166 f_dependents = new Dependent (&f_dependents, f_dependents,
167 dependent, NULL, handler,
168 notify_type, dependent_data);
170 f_dependents = new Dependent (&f_dependents, f_dependents,
171 (FolioObject*)dependent, NULL, handler,
172 notify_type, dependent_data);
174 ON_DEBUG(printf ("@@@2 adding dependent %p to object %p\n",
175 f_dependents, this));
176 // Also remember it in the dependent for easy removal if it is deleted.
177 // The code below failed in a big way because the "dependent" variable
178 // was the real this pointer of the original object, not the offset
179 // this pointer for a FolioObject (in a multiply inherited object).
180 // The net result was the the code mucked up the object because dependent
181 // really wasn't a FolioObject.
182 // NOTE: need to change all code in which we're doing semi-bogus stuff
183 // with a FolioObject to be a void * so that functions can't be called
184 // by mistake like this. We'll just have to cast it to a FolioObject
185 // when the call through it is made and hope the compiler doesn't
186 // expect it to point to an actual FolioObject (or whatever, eg: WWL).
187 #if defined(SC3) || defined(__osf__) || defined(USL)
188 ON_DEBUG(printf ("@@@ adding to depend_on_list of %p\n", dependent));
189 dependent->f_depend_on_list =
190 new DependOnList (dependent->f_depend_on_list, f_dependents);
195 // /////////////////////////////////////////////////////////////////
197 // /////////////////////////////////////////////////////////////////
200 FolioObject::remove_depend_on (FolioObject *target, Dependent *d)
202 ON_DEBUG(printf ("Calling remove_depend_on for object %p, entry %p\n",
205 for (l = &(target->f_depend_on_list); *l != NULL; l = &((*l)->f_next))
207 ON_DEBUG(printf (" checking against entry %p\n", *l));
208 if ((*l)->f_dependent_obj == d)
210 ON_DEBUG(printf ("removing DependOnList %p\n", *l));
211 DependOnList *dead_meat = *l;
220 // /////////////////////////////////////////////////////////////////
221 // remove_dependent - remove first matching dependent
222 // /////////////////////////////////////////////////////////////////
225 #if defined(SC3) || defined(__osf__) || defined(USL)
226 FolioObject::remove_dependent (FolioObject *dependent,
228 FolioObject::remove_dependent (void *dependent,
230 notify_handler_t handler,
231 u_int notify_type, void *dependent_data)
235 // This only removes the first matching handler!
236 // That means that each handler added must be removed!
237 for (d = &f_dependents; *d != NULL; d = &((*d)->f_next))
239 #if defined(SC3) || defined(__osf__) || defined(USL)
240 if ((*d)->f_dependent == dependent &&
242 if ((*d)->f_dependent == (FolioObject*)dependent &&
244 (*d)->f_handler == handler &&
245 (*d)->f_notify_type == notify_type &&
246 (*d)->f_dependent_data == dependent_data)
248 // Following line is BOGUS because dependent is "real this"
249 // not necessarily a FolioObject!
250 // f_folio_object will be NULL if the Dependent object was
251 // created in add_dependent! DJB 11/10/92
252 assert ((*d)->f_folio_object != NULL);
253 #if defined(SC3) || defined(__osf__) || defined(USL)
254 remove_depend_on (dependent, *d);
256 remove_depend_on ((FolioObject*)dependent, *d);
258 Dependent *dead_meat = *d;
267 // /////////////////////////////////////////////////////////////////
268 // release_dependents - free all dependents
269 // /////////////////////////////////////////////////////////////////
272 FolioObject::release_dependents()
274 Dependent *d = f_dependents, *next;
278 // NOTE: Quick fix below. Improve with doubly-linked lists and
279 // cross pointers in Dependent and DependOnList objects.
280 // f_folio_object member is part of the quick fix. DJB 11/10/92
281 if (d->f_folio_object != NULL)
282 remove_depend_on (d->f_folio_object, d);
284 ON_DEBUG(printf ("WARNING: NULL f_folio_object member in release_dependents\n"));
293 // /////////////////////////////////////////////////////////////////
294 // release_depend_on_list
295 // /////////////////////////////////////////////////////////////////
298 FolioObject::release_depend_on_list()
300 DependOnList *l = f_depend_on_list, *next;
305 l->delete_dependent();
310 f_depend_on_list = NULL;
314 // /////////////////////////////////////////////////////////////////
315 // select_on - alternative add_dependent interface
316 // /////////////////////////////////////////////////////////////////
318 // NOTE: it would be useful to have this call return a handle to
319 // the thing we're observing so that we can stop observing just
320 // by deleting that handle!!!
323 #if defined(SC3) || defined(__osf__) || defined(USL)
324 FolioObject::observe (FolioObject *real_this, FolioObject *target,
326 FolioObject::observe (void *real_this, FolioObject *target,
328 notify_handler_t handler, u_int notify_type,
329 void *dependent_data)
331 // This routine will not work, because if target multiply inherits
332 // from FolioObject (like Agent) and FolioObject is not first inherited
333 // class, the this pointer in this routine will be offset from the
334 // real object this pointer, which will cause big problems when
335 // we try to call the callback which expects the real this pointer.
337 // OK, instead we will have to pass in the "real" this pointer which
338 // may be different from the this pointer visible in this routine.
339 #if defined(SC3) || defined(__osf__) || defined(USL)
340 target->f_dependents =
341 new Dependent (&target->f_dependents, target->f_dependents,
343 handler, notify_type, dependent_data);
344 assert( real_this == this );
346 target->f_dependents =
347 new Dependent (&target->f_dependents, target->f_dependents,
348 (FolioObject *) real_this, this,
349 handler, notify_type, dependent_data);
351 ON_DEBUG(printf ("@@@ adding dependent %p to object %p for object %p\n",
352 target->f_dependents, target, this));
354 new DependOnList (f_depend_on_list, target->f_dependents);
358 FolioObject::display_as()
360 return "Generic Folio Object";