Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

prefmem.c

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  file:  prefmem.c
00004  *
00005  * =======================================================================
00006  *  BUGBUG  need some comments here
00007  * =======================================================================
00008  *
00009  * Copyright 1995-2003 Carnegie Mellon University,
00010  *                                                                               University of Michigan,
00011  *                                                                               University of Southern California/Information
00012  *                                                                               Sciences Institute. All rights reserved.
00013  *                                                                              
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * 1.   Redistributions of source code must retain the above copyright notice,
00018  *              this list of conditions and the following disclaimer. 
00019  * 2.   Redistributions in binary form must reproduce the above copyright notice,
00020  *              this list of conditions and the following disclaimer in the documentation
00021  *              and/or other materials provided with the distribution. 
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE SOAR CONSORTIUM ``AS IS'' AND ANY EXPRESS OR
00024  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00025  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00026  * EVENT SHALL THE SOAR CONSORTIUM  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00027  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00030  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  * The views and conclusions contained in the software and documentation are
00034  * those of the authors and should not be interpreted as representing official
00035  * policies, either expressed or implied, of Carnegie Mellon University, the
00036  * University of Michigan, the University of Southern California/Information
00037  * Sciences Institute, or the Soar consortium.
00038  * =======================================================================
00039  */
00040 
00041 /* ======================================================================
00042         Preference Memory routines for Soar 6
00043    ====================================================================== */
00044 
00045 /* Debugging stuff:  #define DEBUG_PREFS to get preference printouts */
00046 
00047 /* #define DEBUG_PREFS */
00048 
00049 #include "soarkernel.h"
00050 
00051 /* ======================================================================
00052 
00053                      Preference Management Routines
00054 
00055 ====================================================================== */
00056 
00057 /* ----------------------------------------------------------------------
00058    Make_preference() creates a new preference structure of the given type
00059    with the given id/attribute/value/referent.  (Referent is only used
00060    for binary preferences.)  The preference is not yet added to preference
00061    memory, however.
00062 ---------------------------------------------------------------------- */
00063 
00064 preference *make_preference(byte type, Symbol * id, Symbol * attr, Symbol * value, Symbol * referent)
00065 {
00066     preference *p;
00067 
00068     allocate_with_pool(&current_agent(preference_pool), &p);
00069     p->type = type;
00070     p->in_tm = FALSE;
00071     p->o_supported = FALSE;
00072     p->on_goal_list = FALSE;
00073     p->reference_count = 0;
00074     p->id = id;
00075     p->attr = attr;
00076     p->value = value;
00077     p->referent = referent;
00078     p->slot = NIL;
00079     p->next_clone = NIL;
00080     p->prev_clone = NIL;
00081 
00082 #ifdef DEBUG_PREFS
00083     print("\nAllocating preference at 0x%8x: ", (unsigned long) p);
00084     print_preference(p);
00085 #endif
00086 
00087     return p;
00088 
00089     /* BUGBUG check to make sure the pref doesn't have
00090        value or referent .isa_goal or .isa_impasse; */
00091 }
00092 
00093 /* ----------------------------------------------------------------------
00094    Deallocate_preference() deallocates a given preference.
00095 ---------------------------------------------------------------------- */
00096 
00097 void deallocate_preference(preference * pref)
00098 {
00099 
00100 #ifdef DEBUG_PREFS
00101     print("\nDeallocating preference at 0x%8x: ", (unsigned long) pref);
00102     print_preference(pref);
00103     if (pref->reference_count != 0) {   /* --- sanity check --- */
00104         char msg[MESSAGE_SIZE];
00105         strncpy(msg, "prefmem.c: Internal Error: Deallocating preference with ref. count != 0\n", MESSAGE_SIZE);
00106         msg[MESSAGE_SIZE - 1] = 0;
00107         abort_with_fatal_error(msg);
00108     }
00109 #endif
00110 
00111 #ifdef NO_TOP_JUST
00112     /* --- remove it from the list of pref's for its match goal --- */
00113     if (pref->on_goal_list)
00114         remove_from_dll(pref->match_goal->id.preferences_from_goal, pref, all_of_goal_next, all_of_goal_prev);
00115 
00116     /* --- remove it from the list of pref's from that instantiation --- */
00117     if (pref->inst) {
00118         remove_from_dll(pref->inst->preferences_generated, pref, inst_next, inst_prev);
00119         possibly_deallocate_instantiation(pref->inst);
00120     }
00121 #else
00122 
00123     /* --- remove it from the list of pref's for its match goal --- */
00124     if (pref->on_goal_list)
00125         remove_from_dll(pref->inst->match_goal->id.preferences_from_goal, pref, all_of_goal_next, all_of_goal_prev);
00126 
00127     /* --- remove it from the list of pref's from that instantiation --- */
00128     remove_from_dll(pref->inst->preferences_generated, pref, inst_next, inst_prev);
00129     possibly_deallocate_instantiation(pref->inst);
00130 
00131 #endif
00132 
00133     /* --- dereference component symbols --- */
00134     symbol_remove_ref(pref->id);
00135     symbol_remove_ref(pref->attr);
00136     symbol_remove_ref(pref->value);
00137     if (preference_is_binary(pref->type))
00138         symbol_remove_ref(pref->referent);
00139 
00140     /* --- free the memory --- */
00141     free_with_pool(&current_agent(preference_pool), pref);
00142 }
00143 
00144 /* ----------------------------------------------------------------------
00145    Possibly_deallocate_preference_and_clones() checks whether a given
00146    preference and all its clones have reference_count 0, and deallocates
00147    them all if they do.  It returns TRUE if they were actually
00148    deallocated, FALSE otherwise.
00149 ---------------------------------------------------------------------- */
00150 
00151 bool possibly_deallocate_preference_and_clones(preference * pref)
00152 {
00153     preference *clone, *next;
00154 
00155     if (pref->reference_count)
00156         return FALSE;
00157     for (clone = pref->next_clone; clone != NIL; clone = clone->next_clone)
00158         if (clone->reference_count)
00159             return FALSE;
00160     for (clone = pref->prev_clone; clone != NIL; clone = clone->prev_clone)
00161         if (clone->reference_count)
00162             return FALSE;
00163 
00164     /* --- deallocate all the clones --- */
00165     clone = pref->next_clone;
00166     while (clone) {
00167         next = clone->next_clone;
00168         deallocate_preference(clone);
00169         clone = next;
00170     }
00171     clone = pref->prev_clone;
00172     while (clone) {
00173         next = clone->prev_clone;
00174         deallocate_preference(clone);
00175         clone = next;
00176     }
00177 
00178     /* --- deallocate pref --- */
00179     deallocate_preference(pref);
00180 
00181     return TRUE;
00182 }
00183 
00184 /* ----------------------------------------------------------------------
00185    Remove_preference_from_clones() splices a given preference out of the
00186    list of clones.  If the preference's reference_count is 0, it also
00187    deallocates it and returns TRUE.  Otherwise it returns FALSE.
00188 ---------------------------------------------------------------------- */
00189 
00190 bool remove_preference_from_clones(preference * pref)
00191 {
00192     preference *any_clone;
00193 
00194     any_clone = NIL;
00195     if (pref->next_clone) {
00196         any_clone = pref->next_clone;
00197         pref->next_clone->prev_clone = pref->prev_clone;
00198     }
00199     if (pref->prev_clone) {
00200         any_clone = pref->prev_clone;
00201         pref->prev_clone->next_clone = pref->next_clone;
00202     }
00203     pref->next_clone = pref->prev_clone = NIL;
00204     if (any_clone)
00205         possibly_deallocate_preference_and_clones(any_clone);
00206     if (!pref->reference_count) {
00207         deallocate_preference(pref);
00208         return TRUE;
00209     } else {
00210         return FALSE;
00211     }
00212 }
00213 
00214 /* ------------------------------------------------------------------------
00215    Add_preference_to_tm() adds a given preference to preference memory (and
00216    hence temporary memory).
00217 ------------------------------------------------------------------------ */
00218 
00219 void add_preference_to_tm(preference * pref)
00220 {
00221     slot *s;
00222     preference *p2;
00223 
00224 #ifdef DEBUG_PREFS
00225     print("\nAdd preference at 0x%8x:  ", (unsigned long) pref);
00226     print_preference(pref);
00227 #endif
00228 
00229     s = make_slot(pref->id, pref->attr);
00230     pref->slot = s;
00231 
00232     insert_at_head_of_dll(s->all_preferences, pref, all_of_slot_next, all_of_slot_prev);
00233 
00234     /* --- add preference to the list (in the right place, according to match
00235        goal level of the instantiations) for the slot --- */
00236 
00237 #ifdef NO_TOP_JUST
00238     /* DJP -- Each slot has an associated list of preferences, ordered by    */
00239     /* goal level.  In NO_TOP_JUST mode we need to look up the goal level of */
00240     /* the preference directly, rather than through pref->inst.              */
00241     if (!s->preferences[pref->type]) {
00242         /* --- this is the only pref. of its type, just put it at the head --- */
00243         insert_at_head_of_dll(s->preferences[pref->type], pref, next, prev);
00244     } else if (s->preferences[pref->type]->match_goal_level >= pref->match_goal_level) {
00245         /* --- it belongs at the head of the list, so put it there --- */
00246         insert_at_head_of_dll(s->preferences[pref->type], pref, next, prev);
00247     } else {
00248         /* --- scan through the pref. list, find the one to insert after --- */
00249         for (p2 = s->preferences[pref->type]; p2->next != NIL; p2 = p2->next)
00250             if (p2->next->match_goal_level >= pref->match_goal_level)
00251                 break;
00252         /* --- insert pref after p2 --- */
00253         pref->next = p2->next;
00254         pref->prev = p2;
00255         p2->next = pref;
00256         if (pref->next)
00257             pref->next->prev = pref;
00258     }
00259 
00260 #else
00261 
00262     if (!s->preferences[pref->type]) {
00263         /* --- this is the only pref. of its type, just put it at the head --- */
00264         insert_at_head_of_dll(s->preferences[pref->type], pref, next, prev);
00265     } else if (s->preferences[pref->type]->inst->match_goal_level >= pref->inst->match_goal_level) {
00266         /* --- it belongs at the head of the list, so put it there --- */
00267         insert_at_head_of_dll(s->preferences[pref->type], pref, next, prev);
00268     } else {
00269         /* --- scan through the pref. list, find the one to insert after --- */
00270         for (p2 = s->preferences[pref->type]; p2->next != NIL; p2 = p2->next)
00271             if (p2->next->inst->match_goal_level >= pref->inst->match_goal_level)
00272                 break;
00273         /* --- insert pref after p2 --- */
00274         pref->next = p2->next;
00275         pref->prev = p2;
00276         p2->next = pref;
00277         if (pref->next)
00278             pref->next->prev = pref;
00279     }
00280 
00281 #endif
00282 
00283     /* --- other miscellaneous stuff --- */
00284     pref->in_tm = TRUE;
00285     preference_add_ref(pref);
00286     mark_slot_as_changed(s);
00287 
00288     /* --- update identifier levels --- */
00289     if (pref->value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
00290         post_link_addition(pref->id, pref->value);
00291     if (preference_is_binary(pref->type))
00292         if (pref->referent->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
00293             post_link_addition(pref->id, pref->referent);
00294 
00295     /* --- if acceptable/require pref for context slot, we may need to add a
00296        wme later --- */
00297     if ((s->isa_context_slot) &&
00298         ((pref->type == ACCEPTABLE_PREFERENCE_TYPE) || (pref->type == REQUIRE_PREFERENCE_TYPE)))
00299         mark_context_slot_as_acceptable_preference_changed(s);
00300 }
00301 
00302 /* ------------------------------------------------------------------------
00303    Remove_preference_from_tm() removes a given preference from PM and TM.
00304 ------------------------------------------------------------------------ */
00305 
00306 void remove_preference_from_tm(preference * pref)
00307 {
00308     slot *s;
00309 
00310     s = pref->slot;
00311 
00312 #ifdef DEBUG_PREFS
00313     print("\nRemove preference at 0x%8x:  ", (unsigned long) pref);
00314     print_preference(pref);
00315 #endif
00316 
00317     /* --- remove preference from the list for the slot --- */
00318     remove_from_dll(s->all_preferences, pref, all_of_slot_next, all_of_slot_prev);
00319     remove_from_dll(s->preferences[pref->type], pref, next, prev);
00320 
00321     /* --- other miscellaneous stuff --- */
00322     pref->in_tm = FALSE;
00323     pref->slot = NIL;           /* BUGBUG use pref->slot in place of pref->in_tm? */
00324     mark_slot_as_changed(s);
00325 
00326     /* --- if acceptable/require pref for context slot, we may need to remove
00327        a wme later --- */
00328     if ((s->isa_context_slot) &&
00329         ((pref->type == ACCEPTABLE_PREFERENCE_TYPE) || (pref->type == REQUIRE_PREFERENCE_TYPE)))
00330         mark_context_slot_as_acceptable_preference_changed(s);
00331 
00332     /* --- update identifier levels --- */
00333     if (pref->value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
00334         post_link_removal(pref->id, pref->value);
00335     if (preference_is_binary(pref->type))
00336         if (pref->referent->common.symbol_type == IDENTIFIER_SYMBOL_TYPE)
00337             post_link_removal(pref->id, pref->referent);
00338 
00339     /* --- deallocate it and clones if possible --- */
00340     preference_remove_ref(pref);
00341 }
00342 
00343 /* ------------------------------------------------------------------------
00344    Process_o_rejects_and_deallocate_them() handles the processing of
00345    o-supported reject preferences.  This routine is called from the firer
00346    and passed a list of all the o-rejects generated in the current
00347    preference phase (the list is linked via the "next" fields on the
00348    preference structures).  This routine removes all preferences for
00349    matching values from TM, and deallocates the o-reject preferences when
00350    done.
00351 ------------------------------------------------------------------------ */
00352 
00353 void process_o_rejects_and_deallocate_them(preference * o_rejects)
00354 {
00355     preference *pref, *next_pref, *p, *next_p;
00356     slot *s;
00357 
00358     for (pref = o_rejects; pref != NIL; pref = pref->next) {
00359         preference_add_ref(pref);       /* prevents it from being deallocated if it's
00360                                            a clone of some other pref we're about to
00361                                            remove */
00362 #ifdef DEBUG_PREFS
00363         print("\nO-reject posted at 0x%8x:  ", (unsigned long) pref);
00364         print_preference(pref);
00365 #endif
00366     }
00367 
00368     pref = o_rejects;
00369     while (pref) {
00370         next_pref = pref->next;
00371         s = find_slot(pref->id, pref->attr);
00372         if (s) {
00373             /* --- remove all pref's in the slot that have the same value --- */
00374             p = s->all_preferences;
00375             while (p) {
00376                 next_p = p->all_of_slot_next;
00377                 if (p->value == pref->value)
00378                     remove_preference_from_tm(p);
00379                 p = next_p;
00380             }
00381         }
00382         preference_remove_ref(pref);
00383         pref = next_pref;
00384     }
00385 }

Generated on Thu Dec 11 13:00:17 2003 for Soar Kernel by doxygen 1.3.5