Reverse finalizer

This commit is contained in:
Siu Kwan Lam 2013-01-07 14:25:58 -06:00
commit 371e940c83
7 changed files with 41 additions and 111 deletions

View file

@ -6,9 +6,7 @@ __version__ = '0.9.1'
from weakref import WeakValueDictionary
from llvm._utils.finalizer import track as track_resource
from llvm._utils.finalizer import OwnerMixin as _OwnerMixin
from llvm import _core
import _core
#===----------------------------------------------------------------------===
# LLVM Version
@ -33,26 +31,11 @@ class LLVMException(Exception):
Exception.__init__(self, msg)
#===----------------------------------------------------------------------===
# Resource Handle
#===----------------------------------------------------------------------===
class Handle(_OwnerMixin):
_finalizer = NotImplemented
def __init__(self, ptr):
self.ptr = ptr
self._finalizer_track(self.ptr)
@classmethod
def _finalize(cls, ptr):
cls._finalizer(ptr)
#===----------------------------------------------------------------------===
# Ownables
#===----------------------------------------------------------------------===
class Ownable(Handle):
class Ownable(object):
"""Objects that can be owned.
Modules and Module Providers can be owned, i.e., the responsibility of
@ -61,21 +44,25 @@ class Ownable(Handle):
is NOT intended for public use.
"""
def __init__(self, ptr):
Handle.__init__(self, ptr)
def __init__(self, ptr, del_fn):
self.ptr = ptr
self.owner = None
self.del_fn = del_fn
def _own(self, owner):
if self.owner:
raise LLVMException("object already owned")
self.owner = owner
self._finalizer_untrack(self.ptr)
def _disown(self):
if not self.owner:
raise LLVMException("not owned")
self.owner = None
self._finalizer_track(self.ptr)
def __del__(self):
if not self.owner:
self.del_fn(self.ptr)
#===----------------------------------------------------------------------===
# Dummy owner, will not delete ownee. Be careful.

View file

@ -1,58 +0,0 @@
'''
Modified C-level finalizer by Benjamin Peterson <benjamin@python.org>
Available at http://code.activestate.com/recipes/577242-calling-c-level-finalizers-without-__del__/
'''
import sys
import traceback
import weakref
class OwnerRef(weakref.ref):
"""A simple weakref.ref subclass, so attributes can be added."""
pass
def _run_finalizer(ref):
"""Internal weakref callback to run finalizers"""
del _finalize_refs[ref.owner]
for item, finalizer in ref.items:
try:
finalizer(item)
except Exception:
print>>sys.stderr, "Exception running {}:".format(finalizer)
traceback.print_exc()
_finalize_refs = {}
def track(owner, item, finalizer):
"""Register an object for finalization.
``owner`` is the the object which is responsible for ``item``.
``finalizer`` will be called with ``item`` as its only argument when
``owner`` is destroyed by the garbage collector.
"""
if id(owner) in _finalize_refs:
ref = _finalize_refs[id(owner)]
else:
ref = OwnerRef(owner, _run_finalizer)
ref.owner = id(owner)
ref.items = []
ref.items.append((item, finalizer))
_finalize_refs[id(owner)] = ref
def untrack(owner, item):
ref = _finalize_refs[id(owner)]
# search and remove the item from the ref
for i, (item_i, _) in enumerate(ref.items):
if item_i is item:
del ref.items[i]
# remove the ref if it is empty
if not ref.items:
del _finalize_refs[id(owner)]
class OwnerMixin(object):
def _finalizer_track(self, item):
if not hasattr(self, '_finalize'):
raise AttributeError("%s must define a _finalize method" % self)
track(self, item, type(self)._finalize)
def _finalizer_untrack(self, item):
untrack(self, item)

View file

@ -397,9 +397,7 @@ class Module(llvm.Ownable, llvm.Cacheable):
Use the static method `Module.new' instead.
"""
llvm.Ownable.__init__(self, ptr)
_finalizer = _core.LLVMDisposeModule
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule)
def __str__(self):
"""Text representation of a module.
@ -1801,7 +1799,7 @@ def _make_value(ptr):
# Builder
#===----------------------------------------------------------------------===
class Builder(llvm.Handle):
class Builder(object):
@staticmethod
def new(basic_block):
@ -1811,9 +1809,10 @@ class Builder(llvm.Handle):
return b
def __init__(self, ptr):
llvm.Handle.__init__(self, ptr)
self.ptr = ptr
_finalizer = _core.LLVMDisposeBuilder
def __del__(self):
_core.LLVMDisposeBuilder(self.ptr)
def position_at_beginning(self, bblk):
"""Position the builder at the beginning of the given block.
@ -2302,7 +2301,7 @@ class Builder(llvm.Handle):
# Memory buffer
#===----------------------------------------------------------------------===
class MemoryBuffer(llvm.Handle):
class MemoryBuffer(object):
@staticmethod
def from_file(fname):
@ -2323,9 +2322,10 @@ class MemoryBuffer(llvm.Handle):
return (obj, "")
def __init__(self, ptr):
llvm.Handle.__init__(self, ptr)
self.ptr = ptr
_finalizer = _core.LLVMDisposeMemoryBuffer
def __del__(self):
_core.LLVMDisposeMemoryBuffer(self.ptr)
#===----------------------------------------------------------------------===

View file

@ -63,7 +63,7 @@ CM_LARGE = 5
# Generic value
#===----------------------------------------------------------------------===
class GenericValue(llvm.Handle):
class GenericValue(object):
@staticmethod
def int(ty, intval):
@ -106,9 +106,10 @@ class GenericValue(llvm.Handle):
return GenericValue(ptr)
def __init__(self, ptr):
llvm.Handle.__init__(self, ptr)
self.ptr = ptr
_finalizer = _core.LLVMDisposeGenericValue
def __del__(self):
_core.LLVMDisposeGenericValue(self.ptr)
def as_int(self):
return _core.LLVMGenericValueToInt(self.ptr, 0)
@ -134,7 +135,7 @@ def _unpack_generic_values(objlist):
# Engine builder
#===----------------------------------------------------------------------===
class EngineBuilder(llvm.Handle):
class EngineBuilder(object):
@staticmethod
def new(module):
core.check_is_module(module)
@ -143,10 +144,11 @@ class EngineBuilder(llvm.Handle):
return EngineBuilder(obj, module)
def __init__(self, ptr, module):
llvm.Handle.__init__(self, ptr)
self.ptr = ptr
self._module = module
_finalizer = _core.LLVMDisposeEngineBuilder
def __del__(self):
_core.LLVMDisposeEngineBuilder(self.ptr)
def force_jit(self):
_core.LLVMEngineBuilderForceJIT(self.ptr)
@ -199,7 +201,7 @@ class EngineBuilder(llvm.Handle):
# Execution engine
#===----------------------------------------------------------------------===
class ExecutionEngine(llvm.Handle):
class ExecutionEngine(object):
@staticmethod
def new(module, force_interpreter=False):
@ -211,10 +213,11 @@ class ExecutionEngine(llvm.Handle):
return ExecutionEngine(ret, module)
def __init__(self, ptr, module):
llvm.Handle.__init__(self, ptr)
self.ptr = ptr
module._own(self)
_finalizer = _core.LLVMDisposeExecutionEngine
def __del__(self):
_core.LLVMDisposeExecutionEngine(self.ptr)
def run_function(self, fn, args):
core.check_is_function(fn)
@ -313,9 +316,7 @@ class TargetMachine(llvm.Ownable):
return TargetMachine(ptr)
def __init__(self, ptr):
llvm.Ownable.__init__(self, ptr)
_finalizer = _core.LLVMDisposeTargetMachine
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetMachine)
def emit_assembly(self, module):
'''returns byte string of the module as assembly code of the target machine

View file

@ -45,15 +45,16 @@ import warnings
# Pass manager builder
#===----------------------------------------------------------------------===
class PassManagerBuilder(llvm.Handle):
class PassManagerBuilder(object):
@staticmethod
def new():
return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate())
def __init__(self, ptr):
llvm.Handle.__init__(self, ptr)
self.ptr = ptr
_finalizer = _core.LLVMPassManagerBuilderDispose
def __del__(self):
_core.LLVMPassManagerBuilderDispose(self.ptr)
def populate(self, pm):
if isinstance(pm, FunctionPassManager):
@ -141,7 +142,7 @@ class PassManagerBuilder(llvm.Handle):
# Pass manager
#===----------------------------------------------------------------------===
class PassManager(llvm.Handle):
class PassManager(object):
@staticmethod
def new():
@ -150,7 +151,8 @@ class PassManager(llvm.Handle):
def __init__(self, ptr):
self.ptr = ptr
_finalizer = _core.LLVMDisposePassManager
def __del__(self):
_core.LLVMDisposePassManager(self.ptr)
def add(self, pass_obj):
'''Add a pass to the pass manager.
@ -206,11 +208,9 @@ class Pass(llvm.Ownable):
'''Pass Inferface
'''
def __init__(self, ptr):
llvm.Ownable.__init__(self, ptr)
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass)
self.__name = ''
_finalizer = _core.LLVMDisposePass
@staticmethod
def new(name):
'''Create a new pass by name.

View file

@ -131,7 +131,7 @@ setup(
maintainer = 'Continuum Analytics, Inc.',
maintainer_email = 'llvmpy@continuum.io',
url = 'http://www.llvmpy.org/',
packages = ['llvm', 'llvm_cbuilder', 'llpython', 'llvm._utils'],
packages = ['llvm', 'llvm_cbuilder', 'llpython'],
py_modules = ['llvm.core'],
license = "BSD",
classifiers = [