Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
tempmem.cpp
Go to the documentation of this file.
1 #include <portability.h>
2 
3 /*************************************************************************
4  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
5  * FOR LICENSE AND COPYRIGHT INFORMATION.
6  *************************************************************************/
7 
8 /*************************************************************************
9  *
10  * file: tempmem.cpp
11  *
12  * =======================================================================
13  *
14  * Temporary Memory and Slot routines for Soar 6
15  *
16  * see comments below and in soarkernel.h
17  *
18  * =======================================================================
19  */
20 
21 /* Debugging stuff: #define DEBUG_SLOTS to get slot printouts */
22 
23 /* #define DEBUG_SLOTS */
24 
25 #include <stdlib.h>
26 
27 #include "tempmem.h"
28 #include "kernel.h"
29 #include "symtab.h"
30 #include "gdatastructs.h"
31 #include "mem.h"
32 #include "agent.h"
33 
34 /* **********************************************************************
35 
36  Temporary Memory
37 
38 ********************************************************************** */
39 
40 /* ======================================================================
41 
42  Slot Management Routines
43 
44  Find_slot() looks for an existing slot for a given id/attr pair, and
45  returns it if found. If no such slot exists, it returns NIL.
46  Make_slot() looks for an existing slot for a given id/attr pair,
47  returns it if found, and otherwise creates a new slot and returns it.
48 
49  Mark_slot_as_changed() is called by the preference manager whenever
50  the preferences for a slot change. This updates the list of
51  changed_slots and highest_goal_whose_context_changed for use by the
52  decider.
53 ====================================================================== */
54 
55 slot *find_slot (Symbol *id, Symbol *attr) {
56  slot *s;
57 
58  if (!id) return NIL; /* fixes bug #135 kjh */
59  for (s=id->id.slots; s!=NIL; s=s->next)
60  if (s->attr==attr) return s;
61  return NIL;
62 }
63 
64 slot *make_slot (agent* thisAgent, Symbol *id, Symbol *attr)
65 {
66  slot *s;
67  int i;
68 
69  /* JC: Search for a slot first. If it exists
70  * for the given symbol, then just return it
71  */
72  for (s=id->id.slots; s!=NIL; s=s->next)
73  {
74  if (s->attr==attr)
75  return s;
76  }
77 
78  /* JC: need to create a new slot */
79  allocate_with_pool (thisAgent, &thisAgent->slot_pool, &s);
80  insert_at_head_of_dll (id->id.slots, s, next, prev);
81 
82  /* Context slots are goals and operators; operator slots get
83  * created with a goal (see create_new_context).
84  */
85  if ((id->id.isa_goal) && (attr == thisAgent->operator_symbol))
86  {
88  }
89  else
90  {
92  }
93 
94  s->changed = NIL;
96  s->id = id;
97  s->attr = attr;
98  symbol_add_ref (id);
99  symbol_add_ref (attr);
100  s->wmes = NIL;
101  s->all_preferences = NIL;
102 
103  /* JC: This is the same as all_preferences
104  * except they are indexed by type.
105  */
106  for (i=0; i<NUM_PREFERENCE_TYPES; i++)
107  s->preferences[i] = NIL;
108 
110  s->impasse_id = NIL;
113 
114  s->wma_val_references = NIL;
115 
116  return s;
117 }
118 
119 void mark_slot_as_changed (agent* thisAgent, slot *s) {
120  dl_cons *dc;
121 
122  if (s->isa_context_slot) {
123  if (thisAgent->highest_goal_whose_context_changed) {
124  if (s->id->id.level <
126  thisAgent->highest_goal_whose_context_changed = s->id;
127  } else {
128  thisAgent->highest_goal_whose_context_changed = s->id;
129  }
130  s->changed = reinterpret_cast<dl_cons *>(s); /* just make it nonzero */
131  } else {
132  if (! s->changed) {
133  allocate_with_pool (thisAgent, &thisAgent->dl_cons_pool, &dc);
134  dc->item = s;
135  s->changed = dc;
136 
137  insert_at_head_of_dll (thisAgent->changed_slots, dc, next, prev);
138  }
139  }
140 }
141 
142 /* -----------------------------------------------------------------
143  Slot Garbage Collection
144 
145  Old slots are garbage collected as follows: whenever we notice that
146  the last preference has been removed from a slot, we call
147  mark_slot_for_possible_removal(). We don't deallocate the slot
148  right away, because there might still be wmes in it, or we might
149  be about to add a new preference to it (through some later action
150  of the same production firing, for example).
151 
152  At the end of the phase, we call remove_garbage_slots(), which
153  scans through each marked slot and garbage collects it if it has
154  no wmes or preferences.
155 ----------------------------------------------------------------- */
156 
158  if (s->marked_for_possible_removal) return;
160  push (thisAgent, s, thisAgent->slots_for_possible_removal);
161 }
162 
163 void remove_garbage_slots (agent* thisAgent) {
164  cons *c;
165  slot *s;
166 
167  while (thisAgent->slots_for_possible_removal) {
168  c = thisAgent->slots_for_possible_removal;
170  s = static_cast<slot_struct *>(c->first);
171  free_cons(thisAgent, c);
172 
173  if (s->wmes || s->all_preferences) {
174  /* --- don't deallocate it if it still has any wmes or preferences --- */
176  continue;
177  }
178 
179  /* --- deallocate the slot --- */
180 #ifdef DEBUG_SLOTS
181  print_with_symbols (thisAgent, "\nDeallocate slot %y ^%y", s->id, s->attr);
182 #endif
183 
184  if (s->changed && (! s->isa_context_slot)) {
185  remove_from_dll (thisAgent->changed_slots, s->changed, next, prev);
186  free_with_pool (&thisAgent->dl_cons_pool, s->changed);
187  }
188  remove_from_dll (s->id->id.slots, s, next, prev);
189  symbol_remove_ref (thisAgent, s->id);
190  symbol_remove_ref (thisAgent, s->attr);
191  if ( s->wma_val_references != NIL )
192  {
193  s->wma_val_references->~wma_sym_reference_map();
194  free_with_pool( &( thisAgent->wma_slot_refs_pool ), s->wma_val_references );
195  s->wma_val_references = NIL;
196  }
197  free_with_pool (&thisAgent->slot_pool, s);
198  }
199 }
200