Staging
v0.5.1
https://github.com/python/cpython
Revision 709b4c35cc6e6f5db58d9e440b5ca732b7fdb6a2 authored by R. David Murray on 11 February 2010, 00:25:17 UTC, committed by R. David Murray on 11 February 2010, 00:25:17 UTC
svn+ssh://pythondev@svn.python.org/python/branches/py3k

................
  r78139 | r.david.murray | 2010-02-10 19:15:05 -0500 (Wed, 10 Feb 2010) | 15 lines

  Merged revisions 78137 via svnmerge from
  svn+ssh://pythondev@svn.python.org/python/trunk

  ........
    r78137 | r.david.murray | 2010-02-10 17:42:04 -0500 (Wed, 10 Feb 2010) | 8 lines

    Issue 7835:  Shelve's __del__ method calls its close method, and its
    close method refers to an identifier in the global module namespace.
    This means that when __del__ is called during interpreter shutdown (if,
    for example, the calling program still has a pointer to the shelf),
    sometimes that global identifier would wind up being None, causing
    mysterious 'ignored' exceptions.  This patch checks for the possible None
    value first before using the global, thus avoiding the error messages.
  ........
................
1 parent 5431928
Raw File
Tip revision: 709b4c35cc6e6f5db58d9e440b5ca732b7fdb6a2 authored by R. David Murray on 11 February 2010, 00:25:17 UTC
Merged revisions 78139 via svnmerge from
Tip revision: 709b4c3
rotatingtree.c
#include "rotatingtree.h"

#define KEY_LOWER_THAN(key1, key2)  ((char*)(key1) < (char*)(key2))

/* The randombits() function below is a fast-and-dirty generator that
 * is probably irregular enough for our purposes.  Note that it's biased:
 * I think that ones are slightly more probable than zeroes.  It's not
 * important here, though.
 */

static unsigned int random_value = 1;
static unsigned int random_stream = 0;

static int
randombits(int bits)
{
	int result;
	if (random_stream < (1U << bits)) {
		random_value *= 1082527;
		random_stream = random_value;
	}
	result = random_stream & ((1<<bits)-1);
	random_stream >>= bits;
	return result;
}


/* Insert a new node into the tree.
   (*root) is modified to point to the new root. */
void
RotatingTree_Add(rotating_node_t **root, rotating_node_t *node)
{
	while (*root != NULL) {
		if (KEY_LOWER_THAN(node->key, (*root)->key))
			root = &((*root)->left);
		else
			root = &((*root)->right);
	}
	node->left = NULL;
	node->right = NULL;
	*root = node;
}

/* Locate the node with the given key.  This is the most complicated
   function because it occasionally rebalances the tree to move the
   resulting node closer to the root. */
rotating_node_t *
RotatingTree_Get(rotating_node_t **root, void *key)
{
	if (randombits(3) != 4) {
		/* Fast path, no rebalancing */
		rotating_node_t *node = *root;
		while (node != NULL) {
			if (node->key == key)
				return node;
			if (KEY_LOWER_THAN(key, node->key))
				node = node->left;
			else
				node = node->right;
		}
		return NULL;
	}
	else {
		rotating_node_t **pnode = root;
		rotating_node_t *node = *pnode;
		rotating_node_t *next;
		int rotate;
		if (node == NULL)
			return NULL;
		while (1) {
			if (node->key == key)
				return node;
			rotate = !randombits(1);
			if (KEY_LOWER_THAN(key, node->key)) {
				next = node->left;
				if (next == NULL)
					return NULL;
				if (rotate) {
					node->left = next->right;
					next->right = node;
					*pnode = next;
				}
				else
					pnode = &(node->left);
			}
			else {
				next = node->right;
				if (next == NULL)
					return NULL;
				if (rotate) {
					node->right = next->left;
					next->left = node;
					*pnode = next;
				}
				else
					pnode = &(node->right);
			}
			node = next;
		}
	}
}

/* Enumerate all nodes in the tree.  The callback enumfn() should return
   zero to continue the enumeration, or non-zero to interrupt it.
   A non-zero value is directly returned by RotatingTree_Enum(). */
int
RotatingTree_Enum(rotating_node_t *root, rotating_tree_enum_fn enumfn,
		  void *arg)
{
	int result;
	rotating_node_t *node;
	while (root != NULL) {
		result = RotatingTree_Enum(root->left, enumfn, arg);
		if (result != 0) return result;
		node = root->right;
		result = enumfn(root, arg);
		if (result != 0) return result;
		root = node;
	}
	return 0;
}
back to top