| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | /*  Part of SWI-Prolog
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Author:        Jan Wielemaker | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     E-mail:        J.Wielemaker@vu.nl | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     WWW:           http://www.swi-prolog.org
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     Copyright (C): 1985-2012, University of Amsterdam | 
					
						
							|  |  |  | 			      VU University Amsterdam | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |     modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |     License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |     version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |     Lesser General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |     License along with this library; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*#define O_DEBUG 1*/ | 
					
						
							|  |  |  | #include "pl-incl.h"
 | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  | #define LOCK_TABLE(t)   if ( t->mutex ) simpleMutexLock(t->mutex)
 | 
					
						
							|  |  |  | #define UNLOCK_TABLE(t)	if ( t->mutex ) simpleMutexUnlock(t->mutex)
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define LOCK_TABLE(t) (void)0
 | 
					
						
							|  |  |  | #define UNLOCK_TABLE(t) (void)0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline Symbol rawAdvanceTableEnum(TableEnum e); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | This file provides generic hash-tables. Most   of  the implementation is | 
					
						
							|  |  |  | rather  straightforward.  Special  are  the  *TableEnum()  functions  to | 
					
						
							|  |  |  | create, advance over and destroy enumerator   objects. These objects are | 
					
						
							|  |  |  | used to enumerate the symbols of these   tables,  used primarily for the | 
					
						
							|  |  |  | pl_current_* predicates. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | The enumerators cause  two  things:  (1)   as  long  as  enumerators are | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | associated, the table will not  be  rehashed   and  (2)  if  symbols are | 
					
						
							|  |  |  | deleted  that  are  referenced  by  an  enumerator,  the  enumerator  is | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | automatically advanced to the next free  symbol. This, in general, makes | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | the enumeration of hash-tables safe. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | TBD: Resizing hash-tables causes major  headaches for concurrent access. | 
					
						
							|  |  |  | We can avoid this by using a dynamic array for the list of hash-entries. | 
					
						
							|  |  |  | Ongoing work in  the  RDF  store   shows  hash-tables  that  can  handle | 
					
						
							|  |  |  | concurrent lock-free access. | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | static Symbol * | 
					
						
							|  |  |  | allocHTableEntries(int buckets) | 
					
						
							|  |  |  | { size_t bytes = buckets * sizeof(Symbol); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Symbol *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   p = allocHeapOrHalt(bytes); | 
					
						
							|  |  |  |   memset(p, 0, bytes); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   return p; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Table | 
					
						
							|  |  |  | newHTable(int buckets) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { Table ht; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   ht		  = allocHeapOrHalt(sizeof(struct table)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   ht->buckets	  = (buckets & ~TABLE_MASK); | 
					
						
							|  |  |  |   ht->size	  = 0; | 
					
						
							|  |  |  |   ht->enumerators = NULL; | 
					
						
							|  |  |  |   ht->free_symbol = NULL; | 
					
						
							|  |  |  |   ht->copy_symbol = NULL; | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |   if ( (buckets & TABLE_UNLOCKED) ) | 
					
						
							|  |  |  |     ht->mutex = NULL; | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { ht->mutex     = allocHeapOrHalt(sizeof(simpleMutex)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     simpleMutexInit(ht->mutex); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   ht->entries = allocHTableEntries(ht->buckets); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   return ht; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | destroyHTable(Table ht) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |   if ( ht->mutex ) | 
					
						
							|  |  |  |   { simpleMutexDelete(ht->mutex); | 
					
						
							|  |  |  |     freeHeap(ht->mutex, sizeof(*ht->mutex)); | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     ht->mutex = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   clearHTable(ht); | 
					
						
							|  |  |  |   freeHeap(ht->entries, ht->buckets * sizeof(Symbol)); | 
					
						
							|  |  |  |   freeHeap(ht, sizeof(struct table)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #if O_DEBUG
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | static int lookups; | 
					
						
							|  |  |  | static int cmps; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | exitTables(int status, void *arg) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { (void)status; | 
					
						
							|  |  |  |   (void)arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Sdprintf("hashstat: Anonymous tables: %d lookups using %d compares\n", | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 	   lookups, cmps); | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2011-02-10 00:02:05 +00:00
										 |  |  | initTables(void) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | { static int done = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !done ) | 
					
						
							|  |  |  |   { done = TRUE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     DEBUG(MSG_HASH_STAT, PL_on_halt(exitTables, NULL)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbol | 
					
						
							|  |  |  | lookupHTable(Table ht, void *name) | 
					
						
							|  |  |  | { Symbol s = ht->entries[pointerHashValue(name, ht->buckets)]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   DEBUG(MSG_HASH_STAT, lookups++); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   for( ; s; s = s->next) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { DEBUG(MSG_HASH_STAT, cmps++); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     if ( s->name == name ) | 
					
						
							|  |  |  |       return s; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef O_DEBUG
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | checkHTable(Table ht) | 
					
						
							|  |  |  | { int i; | 
					
						
							|  |  |  |   int n = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(i=0; i<ht->buckets; i++) | 
					
						
							|  |  |  |   { Symbol s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(s=ht->entries[i]; s; s=s->next) | 
					
						
							|  |  |  |     { assert(lookupHTable(ht, s->name) == s); | 
					
						
							|  |  |  |       n++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert(n == ht->size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* MT: Locked by calling addHTable()
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | static Symbol | 
					
						
							|  |  |  | rehashHTable(Table ht, Symbol map) | 
					
						
							|  |  |  | { Symbol *newentries, *oldentries; | 
					
						
							|  |  |  |   int     newbuckets, oldbuckets; | 
					
						
							|  |  |  |   int     i; | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #if P_PLMT
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   int     safe_copy = (ht->mutex != NULL); | 
					
						
							| 
									
										
										
										
											2013-01-16 12:28:37 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   int     safe_copy = TRUE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   newbuckets = ht->buckets*2; | 
					
						
							|  |  |  |   newentries = allocHTableEntries(newbuckets); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   DEBUG(MSG_HASH_STAT, | 
					
						
							|  |  |  | 	Sdprintf("Rehashing table %p to %d entries\n", ht, ht->buckets)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   for(i=0; i<ht->buckets; i++) | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   { Symbol s, n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     if ( safe_copy ) | 
					
						
							|  |  |  |     { for(s=ht->entries[i]; s; s = n) | 
					
						
							|  |  |  |       { int v = (int)pointerHashValue(s->name, newbuckets); | 
					
						
							|  |  |  | 	Symbol s2 = allocHeapOrHalt(sizeof(*s2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = s->next; | 
					
						
							|  |  |  | 	if ( s == map ) | 
					
						
							|  |  |  | 	  map = s2; | 
					
						
							|  |  |  | 	*s2 = *s; | 
					
						
							|  |  |  | 	s2->next = newentries[v]; | 
					
						
							|  |  |  | 	newentries[v] = s2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { for(s=ht->entries[i]; s; s = n) | 
					
						
							|  |  |  |       { int v = (int)pointerHashValue(s->name, newbuckets); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = s->next; | 
					
						
							|  |  |  | 	s->next = newentries[v]; | 
					
						
							|  |  |  | 	newentries[v] = s; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   oldentries  = ht->entries; | 
					
						
							|  |  |  |   oldbuckets  = ht->buckets; | 
					
						
							|  |  |  |   ht->entries = newentries; | 
					
						
							|  |  |  |   ht->buckets = newbuckets; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( safe_copy ) | 
					
						
							|  |  |  |   {					/* Here we should be waiting until */ | 
					
						
							|  |  |  | 					/* active lookup are finished */ | 
					
						
							|  |  |  |     for(i=0; i<oldbuckets; i++) | 
					
						
							|  |  |  |     { Symbol s, n; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       for(s=oldentries[i]; s; s = n) | 
					
						
							|  |  |  |       { n = s->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s->next = NULL;			/* that causes old readers to stop */ | 
					
						
							|  |  |  | 	freeHeap(s, sizeof(*s)); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   freeHeap(oldentries, oldbuckets * sizeof(Symbol)); | 
					
						
							|  |  |  |   DEBUG(CHK_SECURE, checkHTable(ht)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return map; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbol | 
					
						
							|  |  |  | addHTable(Table ht, void *name, void *value) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { Symbol s; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK_TABLE(ht); | 
					
						
							|  |  |  |   v = (int)pointerHashValue(name, ht->buckets); | 
					
						
							|  |  |  |   if ( lookupHTable(ht, name) ) | 
					
						
							|  |  |  |   { UNLOCK_TABLE(ht); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   s = allocHeapOrHalt(sizeof(struct symbol)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   s->name  = name; | 
					
						
							|  |  |  |   s->value = value; | 
					
						
							|  |  |  |   s->next  = ht->entries[v]; | 
					
						
							|  |  |  |   ht->entries[v] = s; | 
					
						
							|  |  |  |   ht->size++; | 
					
						
							|  |  |  |   DEBUG(9, Sdprintf("addHTable(0x%x, 0x%x, 0x%x) --> size = %d\n", | 
					
						
							|  |  |  | 		    ht, name, value, ht->size)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( ht->buckets * 2 < ht->size && !ht->enumerators ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     s = rehashHTable(ht, s); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   UNLOCK_TABLE(ht); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DEBUG(1, checkHTable(ht)); | 
					
						
							|  |  |  |   return s; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Note: s must be in the table! | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | deleteSymbolHTable(Table ht, Symbol s) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { int v; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Symbol *h; | 
					
						
							|  |  |  |   TableEnum e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK_TABLE(ht); | 
					
						
							|  |  |  |   v = (int)pointerHashValue(s->name, ht->buckets); | 
					
						
							|  |  |  |   h = &ht->entries[v]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for( e=ht->enumerators; e; e = e->next ) | 
					
						
							|  |  |  |   { if ( e->current == s ) | 
					
						
							|  |  |  |       rawAdvanceTableEnum(e); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for( ; *h; h = &(*h)->next ) | 
					
						
							|  |  |  |   { if ( *h == s ) | 
					
						
							|  |  |  |     { *h = (*h)->next; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |       s->next = NULL;				/* force crash */ | 
					
						
							|  |  |  |       s->name = NULL; | 
					
						
							|  |  |  |       s->value = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |       freeHeap(s, sizeof(struct symbol)); | 
					
						
							|  |  |  |       ht->size--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   UNLOCK_TABLE(ht); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | clearHTable(Table ht) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { int n; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   TableEnum e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK_TABLE(ht); | 
					
						
							|  |  |  |   for( e=ht->enumerators; e; e = e->next ) | 
					
						
							|  |  |  |   { e->current = NULL; | 
					
						
							|  |  |  |     e->key     = ht->buckets; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(n=0; n < ht->buckets; n++) | 
					
						
							|  |  |  |   { Symbol s, q; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(s = ht->entries[n]; s; s = q) | 
					
						
							|  |  |  |     { q = s->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( ht->free_symbol ) | 
					
						
							|  |  |  | 	(*ht->free_symbol)(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       freeHeap(s, sizeof(struct symbol)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ht->entries[n] = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ht->size = 0; | 
					
						
							|  |  |  |   UNLOCK_TABLE(ht); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Table copyHTable(Table org) | 
					
						
							|  |  |  |     Make a copy of a hash-table.  This is used to realise the copy-on-write | 
					
						
							|  |  |  |     as defined by SharedTable.  The table is copied to have exactly the | 
					
						
							|  |  |  |     same dimensions as the original.  If the copy_symbol function is | 
					
						
							|  |  |  |     provided, it is called to allow duplicating the symbols name or value | 
					
						
							|  |  |  |     fields. | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Table | 
					
						
							|  |  |  | copyHTable(Table org) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { Table ht; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   int n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   ht = allocHeapOrHalt(sizeof(struct table)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   LOCK_TABLE(org); | 
					
						
							|  |  |  |   *ht = *org;				/* copy all attributes */ | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |   ht->mutex = NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   ht->entries = allocHTableEntries(ht->buckets); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for(n=0; n < ht->buckets; n++) | 
					
						
							|  |  |  |   { Symbol s, *q; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     q = &ht->entries[n]; | 
					
						
							|  |  |  |     for(s = org->entries[n]; s; s = s->next) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |     { Symbol s2 = allocHeapOrHalt(sizeof(*s2)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       *q = s2; | 
					
						
							|  |  |  |       q = &s2->next; | 
					
						
							|  |  |  |       s2->name = s->name; | 
					
						
							|  |  |  |       s2->value = s->value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ( ht->copy_symbol ) | 
					
						
							|  |  |  | 	(*ht->copy_symbol)(s2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *q = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | #ifdef O_PLMT
 | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   if ( org->mutex ) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  |   { ht->mutex = allocHeapOrHalt(sizeof(simpleMutex)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |     simpleMutexInit(ht->mutex); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   UNLOCK_TABLE(org); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ht; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		 /*******************************
 | 
					
						
							|  |  |  | 		 *	    ENUMERATING		* | 
					
						
							|  |  |  | 		 *******************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TableEnum | 
					
						
							|  |  |  | newTableEnum(Table ht) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { TableEnum e = allocHeapOrHalt(sizeof(struct table_enum)); | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Symbol n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK_TABLE(ht); | 
					
						
							|  |  |  |   e->table	  = ht; | 
					
						
							|  |  |  |   e->key	  = 0; | 
					
						
							|  |  |  |   e->next	  = ht->enumerators; | 
					
						
							|  |  |  |   ht->enumerators = e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   n = ht->entries[0]; | 
					
						
							|  |  |  |   while(!n && ++e->key < ht->buckets) | 
					
						
							|  |  |  |     n=ht->entries[e->key]; | 
					
						
							|  |  |  |   e->current = n; | 
					
						
							|  |  |  |   UNLOCK_TABLE(ht); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | freeTableEnum(TableEnum e) | 
					
						
							| 
									
										
										
										
											2013-01-16 11:28:58 +00:00
										 |  |  | { TableEnum *ep; | 
					
						
							| 
									
										
										
										
											2008-12-22 12:02:22 +00:00
										 |  |  |   Table ht; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !e ) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ht = e->table; | 
					
						
							|  |  |  |   LOCK_TABLE(ht); | 
					
						
							|  |  |  |   for( ep=&ht->enumerators; *ep ; ep = &(*ep)->next ) | 
					
						
							|  |  |  |   { if ( *ep == e ) | 
					
						
							|  |  |  |     { *ep = (*ep)->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       freeHeap(e, sizeof(*e)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   UNLOCK_TABLE(ht); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline Symbol | 
					
						
							|  |  |  | rawAdvanceTableEnum(TableEnum e) | 
					
						
							|  |  |  | { Symbol s, n; | 
					
						
							|  |  |  |   Table ht = e->table; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !(s = e->current) ) | 
					
						
							|  |  |  |     return s; | 
					
						
							|  |  |  |   n = s->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while(!n) | 
					
						
							|  |  |  |   { if ( ++e->key >= ht->buckets ) | 
					
						
							|  |  |  |     { e->current = NULL; | 
					
						
							|  |  |  |       return s; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     n=ht->entries[e->key]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   e->current = n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbol | 
					
						
							|  |  |  | advanceTableEnum(TableEnum e) | 
					
						
							|  |  |  | { Symbol s; | 
					
						
							|  |  |  | #ifdef O_PLMT
 | 
					
						
							|  |  |  |   Table ht = e->table; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LOCK_TABLE(ht); | 
					
						
							|  |  |  |   s = rawAdvanceTableEnum(e); | 
					
						
							|  |  |  |   UNLOCK_TABLE(ht); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s; | 
					
						
							|  |  |  | } |