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

wmem.c

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  file:  wmem.c
00004  *
00005  * =======================================================================
00006  *  These are the working memory management routines and utility functions
00007  *  for Soar working memory elements.
00008  * =======================================================================
00009  *
00010  * Copyright 1995-2003 Carnegie Mellon University,
00011  *                                                                               University of Michigan,
00012  *                                                                               University of Southern California/Information
00013  *                                                                               Sciences Institute. All rights reserved.
00014  *                                                                              
00015  * Redistribution and use in source and binary forms, with or without
00016  * modification, are permitted provided that the following conditions are met:
00017  *
00018  * 1.   Redistributions of source code must retain the above copyright notice,
00019  *              this list of conditions and the following disclaimer. 
00020  * 2.   Redistributions in binary form must reproduce the above copyright notice,
00021  *              this list of conditions and the following disclaimer in the documentation
00022  *              and/or other materials provided with the distribution. 
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE SOAR CONSORTIUM ``AS IS'' AND ANY EXPRESS OR
00025  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00026  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00027  * EVENT SHALL THE SOAR CONSORTIUM  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00028  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  * The views and conclusions contained in the software and documentation are
00035  * those of the authors and should not be interpreted as representing official
00036  * policies, either expressed or implied, of Carnegie Mellon University, the
00037  * University of Michigan, the University of Southern California/Information
00038  * Sciences Institute, or the Soar consortium.
00039  * =======================================================================
00040  */
00041 
00042 /* ======================================================================
00043          Working memory routines for Soar 6
00044    ====================================================================== */
00045 
00046 /* Debugging stuff:  #define DEBUG_WMES to get slot printouts */
00047 
00048 /* #define DEBUG_WMES */
00049 
00050 #include "soarkernel.h"
00051 
00052 extern void filtered_print_wme_add(wme * w);
00053 extern void filtered_print_wme_remove(wme * w);
00054 
00055 /* ======================================================================
00056 
00057              Working Memory Management and Utility Routines
00058 
00059    Reset_wme_timetags() resets the wme timetag generator back to 1.
00060    This should be called during an init-soar.
00061 
00062    Make_wme() creates and returns a new wme.  The caller should add the
00063    wme onto the appropriate dll (e.g., my_slot->wmes) and should call
00064    add_wme_to_wm() on it.
00065 
00066    Add_wme_to_wm() and remove_wme_from_wm() make changes to WM.  Again,
00067    the caller is responsible for manipulating the appropriate dll.  WM
00068    changes don't actually get stuffed down the rete until the end of the
00069    phase, when do_buffered_wm_changes() gets be called.
00070 
00071    Remove_wme_list_from_wm() is a utility routine that scans through a
00072    list of wmes, linked by their "next" fields, and calls remove_wme_from_wm()
00073    on each one.
00074 
00075    Deallocate_wme() deallocates a wme.  This should only be invoked via
00076    the wme_remove_ref() macro.
00077 
00078    Find_name_of_object() is a utility function for finding the value of
00079    the ^name attribute on a given object (Symbol).  It returns the name,
00080    or NIL if the object has no name.
00081 ====================================================================== */
00082 
00083 void reset_wme_timetags(void)
00084 {
00085     if (current_agent(num_existing_wmes) != 0) {
00086         print("Internal warning:  wanted to reset wme timetag generator, but\n");
00087         print("there are still some wmes allocated. (Probably a memory leak.)\n");
00088         print("(Leaving timetag numbers alone.)\n");
00089         return;
00090     }
00091     current_agent(current_wme_timetag) = 1;
00092 }
00093 
00094 wme *make_wme(Symbol * id, Symbol * attr, Symbol * value, bool acceptable)
00095 {
00096     wme *w;
00097 
00098     current_agent(num_existing_wmes)++;
00099     allocate_with_pool(&current_agent(wme_pool), &w);
00100     w->id = id;
00101     w->attr = attr;
00102     w->value = value;
00103     symbol_add_ref(id);
00104     symbol_add_ref(attr);
00105     symbol_add_ref(value);
00106     w->acceptable = acceptable;
00107     w->timetag = current_agent(current_wme_timetag)++;
00108     w->reference_count = 0;
00109     w->preference = NIL;
00110     w->output_link = NIL;
00111     w->grounds_tc = 0;
00112     w->potentials_tc = 0;
00113     w->locals_tc = 0;
00114 
00115 /* REW: begin 09.15.96 */
00116     /* When we first create a WME, it had no gds value.  
00117        Do this for ALL wmes, regardless of the operand mode, so that no undefined pointers
00118        are floating around. */
00119     w->gds = NIL;
00120 /* REW: end 09.15.96 */
00121 
00122     return w;
00123 }
00124 
00125 /* --- lists of buffered WM changes --- */
00126 
00127 void add_wme_to_wm(wme * w)
00128 {
00129     push(w, current_agent(wmes_to_add));
00130     if (w->value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
00131         post_link_addition(w->id, w->value);
00132         if (w->attr == current_agent(operator_symbol))
00133             w->value->id.isa_operator++;
00134     }
00135 }
00136 
00137 void remove_wme_from_wm(wme * w)
00138 {
00139     push(w, current_agent(wmes_to_remove));
00140     if (w->value->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
00141         post_link_removal(w->id, w->value);
00142         if (w->attr == current_agent(operator_symbol))
00143             w->value->id.isa_operator--;
00144     }
00145     /* REW: begin 09.15.96 */
00146     /* When we remove a WME, we always have to determine if it's on a GDS, and, if
00147        so, after removing the WME, if there are no longer any WMEs on the GDS,
00148        then we can free the GDS memory */
00149     if (w->gds) {
00150         fast_remove_from_dll(w->gds->wmes_in_gds, w, wme, gds_next, gds_prev);
00151         /* print("\nRemoving WME on some GDS"); */
00152         if (!w->gds->wmes_in_gds) {
00153             free_memory(w->gds, MISCELLANEOUS_MEM_USAGE);
00154             /* print("REMOVING GDS FROM MEMORY. \n"); */
00155         }
00156     }
00157     /* REW: end   09.15.96 */
00158 }
00159 
00160 void remove_wme_list_from_wm(wme * w)
00161 {
00162     wme *next_w;
00163 
00164     while (w) {
00165         next_w = w->next;
00166         remove_wme_from_wm(w);
00167         w = next_w;
00168     }
00169 }
00170 
00171 void do_buffered_wm_changes(void)
00172 {
00173     cons *c, *next_c;
00174     wme *w;
00175 #ifndef NO_TIMING_STUFF
00176 #ifdef DETAILED_TIMING_STATS
00177     struct timeval start_tv;
00178 #endif
00179 #endif
00180 
00181     /* --- if no wme changes are buffered, do nothing --- */
00182     if (!current_agent(wmes_to_add) && !current_agent(wmes_to_remove))
00183         return;
00184 
00185     /* --- call output module in case any changes are output link changes --- */
00186     inform_output_module_of_wm_changes(current_agent(wmes_to_add), current_agent(wmes_to_remove));
00187 
00188     /* --- invoke callback routine.  wmes_to_add and wmes_to_remove can   --- */
00189     /* --- be fetched from the agent structure.                           --- */
00190     soar_invoke_callbacks(soar_agent, WM_CHANGES_CALLBACK, (soar_call_data) NULL);
00191 
00192     /* --- stuff wme changes through the rete net --- */
00193 #ifndef NO_TIMING_STUFF
00194 #ifdef DETAILED_TIMING_STATS
00195     start_timer(&start_tv);
00196 #endif
00197 #endif
00198     for (c = current_agent(wmes_to_add); c != NIL; c = c->rest)
00199         add_wme_to_rete(c->first);
00200     for (c = current_agent(wmes_to_remove); c != NIL; c = c->rest)
00201         remove_wme_from_rete(c->first);
00202 #ifndef NO_TIMING_STUFF
00203 #ifdef DETAILED_TIMING_STATS
00204     stop_timer(&start_tv, &current_agent(match_cpu_time[current_agent(current_phase)]));
00205 #endif
00206 #endif
00207 
00208     /* --- do tracing and cleanup stuff --- */
00209     for (c = current_agent(wmes_to_add); c != NIL; c = next_c) {
00210         next_c = c->rest;
00211         w = c->first;
00212 
00213 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00214 
00215         if (current_agent(sysparams)[TRACE_WM_CHANGES_SYSPARAM]) {
00216             /* print ("=>WM: ");
00217              * print_wme (w);
00218              */
00219             filtered_print_wme_add(w);  /* kjh(CUSP-B2) begin */
00220         }
00221 #endif
00222 
00223         wme_add_ref(w);
00224         free_cons(c);
00225         current_agent(wme_addition_count)++;
00226     }
00227     for (c = current_agent(wmes_to_remove); c != NIL; c = next_c) {
00228         next_c = c->rest;
00229         w = c->first;
00230 
00231 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
00232 
00233         if (current_agent(sysparams)[TRACE_WM_CHANGES_SYSPARAM]) {
00234             /* print ("<=WM: "); 
00235              * print_wme (w);
00236              */
00237             filtered_print_wme_remove(w);       /* kjh(CUSP-B2) begin */
00238         }
00239 #endif
00240 
00241         wme_remove_ref(w);
00242         free_cons(c);
00243         current_agent(wme_removal_count)++;
00244     }
00245     current_agent(wmes_to_add) = NIL;
00246     current_agent(wmes_to_remove) = NIL;
00247 }
00248 
00249 void deallocate_wme(wme * w)
00250 {
00251 #ifdef DEBUG_WMES
00252     print_with_symbols("\nDeallocate wme: ");
00253     print_wme(w);
00254 #endif
00255     symbol_remove_ref(w->id);
00256     symbol_remove_ref(w->attr);
00257     symbol_remove_ref(w->value);
00258     free_with_pool(&current_agent(wme_pool), w);
00259     current_agent(num_existing_wmes)--;
00260 }
00261 
00262 Symbol *find_name_of_object(Symbol * object)
00263 {
00264     slot *s;
00265 
00266     if (object->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)
00267         return NIL;
00268     s = find_slot(object, current_agent(name_symbol));
00269     if (!s)
00270         return NIL;
00271     if (!s->wmes)
00272         return NIL;
00273     return s->wmes->value;
00274 }

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