Reverse finalizer
This commit is contained in:
parent
5fc5ba2e66
commit
371e940c83
7 changed files with 41 additions and 111 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
18
llvm/core.py
18
llvm/core.py
|
|
@ -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)
|
||||
|
||||
|
||||
#===----------------------------------------------------------------------===
|
||||
|
|
|
|||
25
llvm/ee.py
25
llvm/ee.py
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -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 = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue