diff options
Diffstat (limited to 'python/sip/siplib/objmap.c')
-rw-r--r-- | python/sip/siplib/objmap.c | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/python/sip/siplib/objmap.c b/python/sip/siplib/objmap.c deleted file mode 100644 index efc7bc2a..00000000 --- a/python/sip/siplib/objmap.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * This module implements a hash table class for mapping C/C++ addresses to the - * corresponding wrapped Python object. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * This file is part of SIP. - * - * This copy of SIP is licensed for use under the terms of the SIP License - * Agreement. See the file LICENSE for more details. - * - * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - - -#include <string.h> - -#include "sip.h" -#include "sipint.h" - - -#define hash_1(k,s) (((unsigned long)(k)) % (s)) -#define hash_2(k,s) ((s) - 2 - (hash_1((k),(s)) % ((s) - 2))) - - -/* Prime numbers to use as hash table sizes. */ -static unsigned long hash_primes[] = { - 521, 1031, 2053, 4099, - 8209, 16411, 32771, 65537, 131101, 262147, - 524309, 1048583, 2097169, 4194319, 8388617, 16777259, - 33554467, 67108879, 134217757, 268435459, 536870923, 1073741827, - 2147483659U,0 -}; - - -static sipHashEntry *newHashTable(unsigned long); -static sipHashEntry *findHashEntry(sipObjectMap *,void *); -static void reorganiseMap(sipObjectMap *om); - - -/* - * Initialise an object map. - */ -void sipOMInit(sipObjectMap *om) -{ - om -> primeIdx = 0; - om -> unused = om -> size = hash_primes[om -> primeIdx]; - om -> stale = 0; - om -> hash_array = newHashTable(om -> size); -} - - -/* - * Finalise an object map. - */ -void sipOMFinalise(sipObjectMap *om) -{ - sip_api_free(om -> hash_array); -} - - -/* - * Allocate and initialise a new hash table. - */ -static sipHashEntry *newHashTable(unsigned long size) -{ - size_t nbytes; - sipHashEntry *hashtab; - - nbytes = sizeof (sipHashEntry) * size; - - if ((hashtab = (sipHashEntry *)sip_api_malloc(nbytes)) != NULL) - memset(hashtab,0,nbytes); - - return hashtab; -} - - -/* - * Return a pointer to the hash entry that is used, or should be used, for the - * given C/C++ address. - */ -static sipHashEntry *findHashEntry(sipObjectMap *om,void *key) -{ - unsigned long hash, inc; - void *hek; - - hash = hash_1(key,om -> size); - inc = hash_2(key,om -> size); - - while ((hek = om -> hash_array[hash].key) != NULL && hek != key) - hash = (hash + inc) % om -> size; - - return &om -> hash_array[hash]; -} - - -/* - * Return the wrapped Python object of a specific type for a C/C++ address or - * NULL if it wasn't found. - */ -sipWrapper *sipOMFindObject(sipObjectMap *om,void *key, sipWrapperType *type) -{ - sipHashEntry *he = findHashEntry(om, key); - sipWrapper *w; - - /* Go through each wrapped object at this address. */ - for (w = he->first; w != NULL; w = w->next) - { - /* - * If this wrapped object is of the given type, or a sub-type - * of it, or vice versa, then we assume it is the same C++ - * object. - */ - if (PyObject_TypeCheck(w, (PyTypeObject *)type) || - PyType_IsSubtype((PyTypeObject *)type, w->ob_type)) - return w; - } - - return NULL; -} - - -/* - * Add a C/C++ address and the corresponding wrapped Python object to the map. - */ -void sipOMAddObject(sipObjectMap *om,sipWrapper *val) -{ - sipHashEntry *he = findHashEntry(om,val -> u.cppPtr); - - /* - * If the bucket is in use then we appear to have several objects at - * the same address. - */ - if (he -> first != NULL) - { - /* - * This can happen for three reasons. A variable of one class - * can be declared at the start of another class. Therefore - * there are two objects, of different classes, with the same - * address. The second reason is that the old C/C++ object has - * been deleted by C/C++ but we didn't get to find out for some - * reason, and a new C/C++ instance has been created at the - * same address. The third reason is if we are in the process - * of deleting a Python object but the C++ object gets wrapped - * again because the C++ dtor called a method that has been - * re-implemented in Python. The absence of the SIP_SHARE_MAP - * flag tells us that a new C++ instance has just been created - * and so we know the second reason is the correct one so we - * mark the old pointers as invalid and reuse the entry. - * Otherwise we just add this one to the existing list of - * objects at this address. - */ - if (!(val -> flags & SIP_SHARE_MAP)) - { - sipWrapper *w; - - for (w = he -> first; w != NULL; w = w -> next) - w -> u.cppPtr = NULL; - - he -> first = NULL; - } - - val -> next = he -> first; - he -> first = val; - - return; - } - - /* See if the bucket was unused or stale. */ - if (he -> key == NULL) - { - he -> key = val -> u.cppPtr; - om -> unused--; - } - else - om -> stale--; - - /* Add the rest of the new value. */ - he -> first = val; - val -> next = NULL; - - reorganiseMap(om); -} - - -/* - * Reorganise a map if it is running short of space. - */ -static void reorganiseMap(sipObjectMap *om) -{ - unsigned long old_size, i; - sipHashEntry *ohe, *old_tab; - - /* Don't bother if it still has more than 12% available. */ - if (om -> unused > om -> size >> 3) - return; - - /* - * If reorganising (ie. making the stale buckets unused) using the same - * sized table would make 25% available then do that. Otherwise use a - * bigger table (if possible). - */ - if (om -> unused + om -> stale < om -> size >> 2 && hash_primes[om -> primeIdx + 1] != 0) - om -> primeIdx++; - - old_size = om -> size; - old_tab = om -> hash_array; - - om -> unused = om -> size = hash_primes[om -> primeIdx]; - om -> stale = 0; - om -> hash_array = newHashTable(om -> size); - - /* Transfer the entries from the old table to the new one. */ - ohe = old_tab; - - for (i = 0; i < old_size; ++i) - { - if (ohe -> key != NULL && ohe -> first != NULL) - { - *findHashEntry(om,ohe -> key) = *ohe; - om -> unused--; - } - - ++ohe; - } - - sip_api_free(old_tab); -} - - -/* - * Remove a C/C++ object from the table. Return 0 if it was removed - * successfully. - */ -int sipOMRemoveObject(sipObjectMap *om,sipWrapper *val) -{ - sipHashEntry *he = findHashEntry(om,val -> u.cppPtr); - sipWrapper **wp; - - for (wp = &he -> first; *wp != NULL; wp = &(*wp) -> next) - if (*wp == val) - { - *wp = val -> next; - - /* - * If the bucket is now empty then count it as stale. - * Note that we do not NULL the key and count it as - * unused because that might throw out the search for - * another entry that wanted to go here, found it - * already occupied, and was put somewhere else. In - * other words, searches must be repeatable until we - * reorganise the table. - */ - if (he -> first == NULL) - om -> stale++; - - return 0; - } - - return -1; -} |