Skip to content

Instantly share code, notes, and snippets.

@VigneshChennai
Created November 17, 2016 06:33
Show Gist options
  • Save VigneshChennai/97477b29d46ba2920bdf1e21ef8288b5 to your computer and use it in GitHub Desktop.
Save VigneshChennai/97477b29d46ba2920bdf1e21ef8288b5 to your computer and use it in GitHub Desktop.
Controlled recursion in python
def controlled_recursion(default=None, depth=0):
def entangle(f):
lock = threading.Lock()
f.call_counts = {}
def increment():
with lock:
call_count = f.call_counts.get(threading.currentThread().ident, 0)
call_count += 1
f.call_counts[threading.currentThread().ident] = call_count
return call_count
def decrement():
with lock:
f.call_counts[threading.currentThread().ident] -= 1
if f.call_counts[threading.currentThread().ident] <= 0:
del f.call_counts[threading.currentThread().ident]
def inner(*args, **kwargs):
call_count = increment()
try:
if call_count > (depth + 1):
logger.warning("Recursion depth(%s) crossed the allowed depth (%s)."
"Returning default value(%s).", call_count - 1, depth, default)
return default
else:
return f(*args, **kwargs)
finally:
decrement()
return inner
return entangle
@VigneshChennai
Copy link
Author

VigneshChennai commented Nov 17, 2016

Usage

import threading
import logging as logger

@controlled_recursion(depth=3)
def info():
    print "info() called."
    info()

info()

Output:

info() called.
info() called.
info() called.
info() called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment