[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.40,2.41

Guido van Rossum gvanrossum@users.sourceforge.net
Fri, 17 Aug 2001 13:32:38 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv21167

Modified Files:
	typeobject.c 
Log Message:
Weak reference support, closing SF bug #451773.

Classes that don't use __slots__ have a __weakref__ member added in
the same way as __dict__ is added (i.e. only if the base didn't
already have one).  Classes using __slots__ can enable weak
referenceability by adding '__weakref__' to the __slots__ list.

Renamed the __weaklistoffset__ class member to __weakrefoffset__ --
it's not always a list, it seems.  (Is tp_weaklistoffset a historical
misnomer, or do I misunderstand this?)


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.40
retrieving revision 2.41
diff -C2 -d -r2.40 -r2.41
*** typeobject.c	2001/08/17 16:47:50	2.40
--- typeobject.c	2001/08/17 20:32:36	2.41
***************
*** 10,14 ****
  	{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
  	{"__doc__", T_STRING, offsetof(PyTypeObject, tp_doc), READONLY},
! 	{"__weaklistoffset__", T_LONG,
  	 offsetof(PyTypeObject, tp_weaklistoffset), READONLY},
  	{"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY},
--- 10,14 ----
  	{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
  	{"__doc__", T_STRING, offsetof(PyTypeObject, tp_doc), READONLY},
! 	{"__weakrefoffset__", T_LONG,
  	 offsetof(PyTypeObject, tp_weaklistoffset), READONLY},
  	{"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY},
***************
*** 202,205 ****
--- 202,206 ----
  {
  	int dictoffset = self->ob_type->tp_dictoffset;
+ 	int weaklistoffset = self->ob_type->tp_weaklistoffset;
  	PyTypeObject *type, *base;
  	destructor f;
***************
*** 225,228 ****
--- 226,233 ----
  	}
  
+ 	/* If we added weaklist, we clear it */
+ 	if (weaklistoffset && !base->tp_weaklistoffset)
+ 		PyObject_ClearWeakRefs(self);
+ 
  	/* Finalize GC if the base doesn't do GC and we do */
  	if (PyType_IS_GC(type) && !PyType_IS_GC(base))
***************
*** 456,463 ****
  extra_ivars(PyTypeObject *type, PyTypeObject *base)
  {
! 	int t_size = PyType_BASICSIZE(type);
! 	int b_size = PyType_BASICSIZE(base);
  
! 	assert(t_size >= b_size); /* type smaller than base! */
  	if (type->tp_itemsize || base->tp_itemsize) {
  		/* If itemsize is involved, stricter rules */
--- 461,468 ----
  extra_ivars(PyTypeObject *type, PyTypeObject *base)
  {
! 	size_t t_size = PyType_BASICSIZE(type);
! 	size_t b_size = PyType_BASICSIZE(base);
  
! 	assert(t_size >= b_size); /* Else type smaller than base! */
  	if (type->tp_itemsize || base->tp_itemsize) {
  		/* If itemsize is involved, stricter rules */
***************
*** 465,475 ****
  			type->tp_itemsize != base->tp_itemsize;
  	}
! 	if (t_size == b_size)
! 		return 0;
! 	if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&
! 	    type->tp_dictoffset == b_size &&
! 	    (size_t)t_size == b_size + sizeof(PyObject *))
! 		return 0; /* "Forgive" adding a __dict__ only */
! 	return 1;
  }
  
--- 470,481 ----
  			type->tp_itemsize != base->tp_itemsize;
  	}
! 	if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 &&
! 	    type->tp_weaklistoffset + sizeof(PyObject *) == t_size)
! 		t_size -= sizeof(PyObject *);
! 	if (type->tp_dictoffset && base->tp_dictoffset == 0 &&
! 	    type->tp_dictoffset + sizeof(PyObject *) == t_size)
! 		t_size -= sizeof(PyObject *);
! 
! 	return t_size != b_size;
  }
  
***************
*** 501,505 ****
  	etype *et;
  	struct memberlist *mp;
! 	int i, nbases, nslots, slotoffset, dynamic;
  
  	/* Special case: type(x) should return x->ob_type */
--- 507,511 ----
  	etype *et;
  	struct memberlist *mp;
! 	int i, nbases, nslots, slotoffset, dynamic, add_dict, add_weak;
  
  	/* Special case: type(x) should return x->ob_type */
***************
*** 614,617 ****
--- 620,625 ----
  	slots = PyDict_GetItemString(dict, "__slots__");
  	nslots = 0;
+ 	add_dict = 0;
+ 	add_weak = 0;
  	if (slots != NULL) {
  		/* Make it into a tuple */
***************
*** 630,639 ****
  				return NULL;
  			}
  		}
  	}
  	if (slots == NULL && base->tp_dictoffset == 0 &&
  	    (base->tp_setattro == PyObject_GenericSetAttr ||
! 	     base->tp_setattro == NULL))
! 		nslots = 1;
  
  	/* XXX From here until type is safely allocated,
--- 638,654 ----
  				return NULL;
  			}
+ 			/* XXX Check against null bytes in name */
  		}
  	}
  	if (slots == NULL && base->tp_dictoffset == 0 &&
  	    (base->tp_setattro == PyObject_GenericSetAttr ||
! 	     base->tp_setattro == NULL)) {
! 		nslots++;
! 		add_dict++;
! 	}
! 	if (slots == NULL && base->tp_weaklistoffset == 0) {
! 		nslots++;
! 		add_weak++;
! 	}
  
  	/* XXX From here until type is safely allocated,
***************
*** 717,730 ****
  			mp->type = T_OBJECT;
  			mp->offset = slotoffset;
  			slotoffset += sizeof(PyObject *);
  		}
  	}
! 	else if (nslots) {
! 		type->tp_dictoffset = slotoffset;
! 		mp->name = "__dict__";
! 		mp->type = T_OBJECT;
! 		mp->offset = slotoffset;
! 		mp->readonly = 1;
! 		slotoffset += sizeof(PyObject *);
  	}
  	type->tp_basicsize = slotoffset;
--- 732,760 ----
  			mp->type = T_OBJECT;
  			mp->offset = slotoffset;
+ 			if (base->tp_weaklistoffset == 0 &&
+ 			    strcmp(mp->name, "__weakref__") == 0)
+ 				type->tp_weaklistoffset = slotoffset;
  			slotoffset += sizeof(PyObject *);
  		}
  	}
! 	else {
! 		if (add_dict) {
! 			type->tp_dictoffset = slotoffset;
! 			mp->name = "__dict__";
! 			mp->type = T_OBJECT;
! 			mp->offset = slotoffset;
! 			mp->readonly = 1;
! 			mp++;
! 			slotoffset += sizeof(PyObject *);
! 		}
! 		if (add_weak) {
! 			type->tp_weaklistoffset = slotoffset;
! 			mp->name = "__weakref__";
! 			mp->type = T_OBJECT;
! 			mp->offset = slotoffset;
! 			mp->readonly = 1;
! 			mp++;
! 			slotoffset += sizeof(PyObject *);
! 		}
  	}
  	type->tp_basicsize = slotoffset;