3 //============================================================================
7 // Implementation of the CdlReference and CdlReferrer classes.
9 //============================================================================
10 //####COPYRIGHTBEGIN####
12 // ----------------------------------------------------------------------------
13 // Copyright (C) 1999, 2000 Red Hat, Inc.
15 // This file is part of the eCos host tools.
17 // This program is free software; you can redistribute it and/or modify it
18 // under the terms of the GNU General Public License as published by the Free
19 // Software Foundation; either version 2 of the License, or (at your option)
22 // This program is distributed in the hope that it will be useful, but WITHOUT
23 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
27 // You should have received a copy of the GNU General Public License along with
28 // this program; if not, write to the Free Software Foundation, Inc.,
29 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 // ----------------------------------------------------------------------------
33 //####COPYRIGHTEND####
34 //============================================================================
35 //#####DESCRIPTIONBEGIN####
42 //####DESCRIPTIONEND####
43 //============================================================================
48 // ----------------------------------------------------------------------------
49 #include "cdlconfig.h"
51 // Get the infrastructure types, assertions, tracing and similar
53 #include <cyg/infra/cyg_ass.h>
54 #include <cyg/infra/cyg_trac.h>
56 // <cdlcore.hxx> defines everything implemented in this module.
57 // It implicitly supplies <string>, <vector> and <map> because
58 // the class definitions rely on these headers.
59 #include <cdlcore.hxx>
65 // ----------------------------------------------------------------------------
66 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlReference);
67 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlReferrer);
70 //{{{ CdlReference class
72 // ----------------------------------------------------------------------------
73 // The default constructor. This should not normally get invoked, instead
74 // a string argument should be supplied. However it is occasionally useful
75 // to construct a reference and then set the name later.
77 CdlReference::CdlReference()
79 CYG_REPORT_FUNCNAME("CdlReference:: default constructor");
80 CYG_REPORT_FUNCARG1XV(this);
84 cdlreference_cookie = CdlReference_Magic;
85 CYGDBG_MEMLEAK_CONSTRUCTOR();
87 CYG_POSTCONDITION_THISC();
91 // This constructor typically gets used when parsing a property.
92 // The object may be created either on the stack or in the heap,
93 // depending on the requirements of the property. During a later
94 // phase in the parsing process the object may get bound.
95 CdlReference::CdlReference(const std::string dest_arg)
97 CYG_REPORT_FUNCNAME("CdlReference:: constructor");
98 CYG_REPORT_FUNCARG1("this %p", this);
100 dest_name = dest_arg;
102 cdlreference_cookie = CdlReference_Magic;
103 CYGDBG_MEMLEAK_CONSTRUCTOR();
105 CYG_POSTCONDITION_THISC();
109 // For some properties, notably LocalReference ones, it is convenient
110 // to create a temporary reference object on the stack and then
111 // derive the property from the temporary. This requires the
112 // copy constructor. When this operation is used the object
113 // should still be unbound.
114 CdlReference::CdlReference(const CdlReference& orig)
116 CYG_REPORT_FUNCNAME("CdlReference:: copy constructor");
117 CYG_REPORT_FUNCARG2("this %p, orig %p", this, &orig);
118 CYG_INVARIANT_CLASSC(CdlReference, orig);
119 CYG_PRECONDITIONC(0 == orig.dest);
121 dest_name = orig.dest_name;
123 cdlreference_cookie = CdlReference_Magic;
124 CYGDBG_MEMLEAK_CONSTRUCTOR();
126 CYG_POSTCONDITION_THISC();
130 // The assignment operator may be needed for similar reasons.
132 CdlReference::operator=(const CdlReference& orig)
134 CYG_REPORT_FUNCNAME("CdlReference:: assignment operator");
135 CYG_REPORT_FUNCARG2("this %p, orig %p", this, &orig);
136 CYG_INVARIANT_CLASSC(CdlReference, orig);
137 CYG_PRECONDITIONC(0 == orig.dest);
140 dest_name = orig.dest_name;
142 cdlreference_cookie = CdlReference_Magic;
145 CYG_POSTCONDITION_THISC();
150 // The destructor should only get invoked when a package is unloaded.
151 // All appropriate clean-ups should have happened already, in particular
152 // the reference should not currently be bound.
153 CdlReference::~CdlReference()
155 CYG_REPORT_FUNCNAME("CdlReference:: destructor");
156 CYG_REPORT_FUNCARG1("this %p", this);
157 CYG_PRECONDITION_THISC();
158 CYG_PRECONDITIONC(0 == dest);
160 cdlreference_cookie = CdlReference_Invalid;
162 CYGDBG_MEMLEAK_DESTRUCTOR();
167 // ----------------------------------------------------------------------------
168 // Accessing the fields.
171 CdlReference::set_destination_name(const std::string name)
173 CYG_REPORT_FUNCNAME("CdlReference::set_destination_name");
174 CYG_REPORT_FUNCARG1XV(this);
175 CYG_PRECONDITION_THISC();
176 CYG_PRECONDITIONC((0 == dest) && ("" == dest_name));
184 CdlReference::get_destination_name(void) const
186 CYG_REPORT_FUNCNAME("CdlReference::get_destination_name");
187 CYG_REPORT_FUNCARG1("this %p", this);
188 CYG_PRECONDITION_THISC();
195 CdlReference::get_destination() const
197 CYG_REPORT_FUNCNAMETYPE("CdlReference::get_destination", "result %p");
198 CYG_REPORT_FUNCARG1XV(this);
199 CYG_PRECONDITION_THISC();
201 CdlNode result = dest;
202 CYG_REPORT_RETVAL(result);
207 CdlReference::check_this(cyg_assert_class_zeal zeal) const
209 if (CdlReference_Magic != cdlreference_cookie) {
212 CYGDBG_MEMLEAK_CHECKTHIS();
214 case cyg_system_test:
216 // There is not enough information in the reference
217 // object itself to allow for a check for a corresponding
218 // referrer object. If more debugability is needed
219 // then extra data will have to be stored.
221 // However, it is possible to do a basic check of dest itself.
223 if (!dest->check_this(cyg_quick)) {
229 if (dest_name != dest->get_name()) {
242 // ----------------------------------------------------------------------------
243 // Binding. This is simply a case of filling in some fields in the reference
244 // object and pushing a new referrer object. Binding generally happens as
245 // a result of calling reference update handlers when a package gets loaded.
248 CdlReference::bind(CdlNode src_arg, CdlProperty src_prop_arg, CdlNode dest_arg)
250 CYG_REPORT_FUNCNAME("CdlReference::bind");
251 CYG_REPORT_FUNCARG4XV(this, src_arg, src_prop_arg, dest_arg);
252 CYG_INVARIANT_THISC(CdlReference);
253 CYG_PRECONDITION_CLASSC(src_arg);
254 CYG_PRECONDITION_CLASSC(src_prop_arg);
255 CYG_PRECONDITION_CLASSC(dest_arg);
257 CYG_ASSERTC(dest_name == dest_arg->get_name());
259 CdlReferrer local_copy;
260 local_copy.source = src_arg;
261 local_copy.source_property = src_prop_arg;
263 dest_arg->referrers.push_back(local_copy);
269 // Unbinding involves finding and removing the appropriate referrer object (there
270 // may be several, but each will result in a separate unbind() call.)
272 CdlReference::unbind(CdlNode src_arg, CdlProperty src_prop_arg)
274 CYG_REPORT_FUNCNAME("CdlReference::unbind");
275 CYG_REPORT_FUNCARG3XV(this, src_arg, src_prop_arg);
276 CYG_PRECONDITION_THISC();
277 CYG_PRECONDITION_CLASSC(src_arg);
278 CYG_PRECONDITION_CLASSC(src_prop_arg);
281 std::vector<CdlReferrer>::iterator ref_i;
282 for (ref_i = dest->referrers.begin(); ref_i != dest->referrers.end(); ref_i++) {
283 if ((ref_i->source == src_arg) && (ref_i->source_property == src_prop_arg)) {
284 dest->referrers.erase(ref_i);
296 //{{{ CdlReferrer class
298 // ----------------------------------------------------------------------------
299 // The constructors etc. should only get invoked from
300 // CdlReference::bind() and unbind(). However because Referrer objects
301 // get held in STL vectors/lists/whatever it is hard to know exactly
302 // what will happen when, so assertions are a bit thin on the ground.
304 CdlReferrer::CdlReferrer()
306 CYG_REPORT_FUNCNAME("CdlReferrer:: default constructor");
307 CYG_REPORT_FUNCARG1XV(this);
311 cdlreferrer_cookie = CdlReferrer_Magic;
312 CYGDBG_MEMLEAK_CONSTRUCTOR();
314 CYG_POSTCONDITION_THISC();
318 CdlReferrer::CdlReferrer(const CdlReferrer& original)
320 CYG_REPORT_FUNCNAME("CdlReferrer:: copy constructor");
321 CYG_REPORT_FUNCARG2XV(this, &original);
322 CYG_PRECONDITION_CLASSOC(original);
324 source = original.source;
325 source_property = original.source_property;
326 cdlreferrer_cookie = CdlReferrer_Magic;
327 CYGDBG_MEMLEAK_CONSTRUCTOR();
329 CYG_POSTCONDITION_THISC();
334 CdlReferrer::operator=(const CdlReferrer& original)
336 CYG_REPORT_FUNCNAME("CdlReferrer:: assignment operator");
337 CYG_REPORT_FUNCARG2XV(this, &original);
338 CYG_PRECONDITION_CLASSOC(original);
340 if (this != &original) {
341 source = original.source;
342 source_property = original.source_property;
343 cdlreferrer_cookie = CdlReferrer_Magic;
346 CYG_POSTCONDITION_THISC();
351 CdlReferrer::~CdlReferrer()
353 CYG_REPORT_FUNCNAME("CdlReferrer:: destructor");
354 CYG_REPORT_FUNCARG1XV(this);
355 CYG_PRECONDITION_THISC();
357 cdlreferrer_cookie = CdlReferrer_Magic;
360 CYGDBG_MEMLEAK_DESTRUCTOR();
365 // ----------------------------------------------------------------------------
366 // This routine is the main reason for having reference and referrer
367 // objects around in the first place. It allows changes to an entity
368 // to be propagated back to anything else interested in the entity.
371 CdlReferrer::update(CdlTransaction transact, CdlNode dest_arg, CdlUpdate change)
373 CYG_REPORT_FUNCNAME("CdlReferrer::update");
374 CYG_REPORT_FUNCARG4XV(this, transact, dest_arg, change);
375 CYG_PRECONDITION_THISC();
377 source_property->update(transact, source, dest_arg, change);
383 CdlReferrer::get_source() const
385 CYG_REPORT_FUNCNAMETYPE("CdlReferrer::get_source", "result %p");
386 CYG_REPORT_FUNCARG1XV(this);
387 CYG_PRECONDITION_THISC();
389 CdlNode result = source;
390 CYG_REPORT_RETVAL(result);
395 CdlReferrer::get_source_property() const
397 CYG_REPORT_FUNCNAMETYPE("CdlReferrer::get_source_property", "result %p");
398 CYG_REPORT_FUNCARG1XV(this);
399 CYG_PRECONDITION_THISC();
401 CdlProperty result = source_property;
402 CYG_REPORT_RETVAL(result);
407 CdlReferrer::check_this(cyg_assert_class_zeal zeal) const
409 if (CdlReferrer_Magic != cdlreferrer_cookie) {
412 CYGDBG_MEMLEAK_CHECKTHIS();
414 case cyg_system_test :
418 if (!source->check_this(cyg_quick)) {
422 if (0 != source_property) {
423 if (!source_property->check_this(cyg_quick)) {