On 07/10/2011 09:13 PM Laura Creighton wrote:
What do we want to happen when somebody -- say in a C extension -- takes the id 
of an object
that is scheduled to be removed when the gc next runs?
IMO taking the id should increment the object ref counter
and prevent the garbage collection, until the id value itself is garbage 
collected.
The obvious way would be to make id an object that keeps a reference to the 
object
whose id it represents. See below[1] for an example (just for discussion 
illustration).

Of course in low level access, conventions of ownership can sometimes
safely optimize away actual ref incr/decr, but it sounds like your example
proposes "taking an id" after ref count has gone to zero.

That's like doing a reinterpret_cast to integer of a malloc pointer after
the area's been freed, and expecting it to mean something. It should be
an enforced nono, if you ask me.

The example id attempts to make all equivalent immutables of the same type
have the same id, by taking advantage of dict's key comparison properties
and the .setdefault method.

to get something like the current, with just the object reference to make
an id hold its object, use IdHolder in place of Id. But then you can get all 
kinds
of ids for the same immutable value, as with the old id.

_______________________________________________________________________________

# idstuff.py -- a concept-exploring toy re "id"
# 2011-07-10 22:58:46 bokr
#
class Id(object):
    refval = id     # old id function
    objcache = {}   # to store typed immutables for ref to first of 
equal-valued encountered
                    # and using old id of the first as id for all of same type 
and equal value.

    def __init__(self, obj):
        self.obj = obj

    def id(self):
        so=self.obj
        if type(so) in (int,float,bool,tuple,str,unicode): # etc?
            t = (type(so), so)
            return self.refval(self.objcache.setdefault(t, t)[1])
        else:
            return self.refval(so) # as now? XXX what is abstract meaning of 
id(some_mutable)?

    def __eq__(self, other):
        if type(self) != type(other):
            raise TypeError('Id instances can only be compared with each other,'
                    'not to "%s" instances.'% type(other).__name__)
        tobj=type(self.obj)
        tother=type(other.obj)
        if tobj != tother:
            return False
        return self.id() == other.id()

    def __repr__(self):
        return '<Id(%r)==%i vs old %i>'%(self.obj, self.id(), 
self.refval(self.obj))

    def __str__(self):
        return '<Id(%s)>'%(self.obj,)

class IdHolder(object):
    refval = id     # old id function

    def __init__(self, obj):
        self.obj = obj
        self.id = self.refval(obj)

    def __eq__(self, other):
        if type(self) != type(other):
            raise TypeError('IdHolder instances can only be compared with each 
other,'
                    ' not to "%s" instances.'% type(other).__name__)
        return self.id == other.id

    def __repr__(self):
        return '<IdHolder(%r)==%i>'%(self.obj, self.id)

    def __str__(self):
        return '<IdHolder(%s)>'%(self.obj,)
_______________________________________________________________________________

Python 2.7.2 (default, Jul  8 2011, 23:38:53)
[GCC 4.1.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> oldid=id
>>> from ut.idstuff import IdHolder as id
>>> from ut.idstuff import Id as idk      # with caching for equal (type,value) 
immutables
>>> oldid(2000),oldid(2000),oldid(20*100)
(136189164, 136189164, 136189176)
>>> id(2000),id(2000),id(20*100) # no k cacheing
(<IdHolder(2000)==136189164>, <IdHolder(2000)==136189164>, 
<IdHolder(2000)==136189212>)
>>> idk(2000),idk(2000),idk(20*100) # with k cacheing
(<Id(2000)==136189236 vs old 136189236>, <Id(2000)==136189236 vs old 136189236>, 
<Id(2000)==136189236 vs old 136189140>)
>>>
>>> oldid([]),oldid([])         # dangling pointer value returned
(3083895948L, 3083895948L)
>>> id([]),id([])               # pointer kept live
(<IdHolder([])==3083895948>, <IdHolder([])==3083896108>)
>>> idk([]),idk([])             # pointer kept live, constant caching n/a
(<Id([])==3083784300 vs old 3083784300>, <Id([])==3083896908 vs old 3083896908>)
>>>

Have fun ;-)

Regards
Bengt Richter


Laura
=

_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
http://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to