I would like to create a smart recursion prevention mechanism. I would like to be able to annotate a piece of code somehow, to mark that it should not be executed in recursion, and if it is indeed executed in recursion, then I want to throw a custom error (which can be caught to allow executing custom code when this happens)
Here is my attempt until here:
import scala.collection.mutable.{Set => MutableSet, HashSet => MutableHashSet } case class RecursionException(uniqueID:Any) extends Exception("Double recursion on " + uniqueID) object Locking { var locks:MutableSet[Any] = new MutableHashSet[Any] def acquireLock (uniqueID:Any) : Unit = { if (! (locks add uniqueID)) throw new RecursionException(uniqueID) } def releaseLock (uniqueID:Any) : Unit = { locks remove uniqueID } def lock1 (uniqueID:Any, f:() => Unit) : Unit = { acquireLock (uniqueID) try { f() } finally { releaseLock (uniqueID) } } def lock2[T] (uniqueID:Any, f:() => T) : T = { acquireLock (uniqueID) try { return f() } finally { releaseLock (uniqueID) } } } and now to lock a code segment I do:
import Locking._ lock1 ("someID", () => { // Custom code here }) My questions are:
- Is there any obvious way to get rid of the need for hard coding a unique identifier? I need a unique identifier which will actually be shared between all invocations of the function containing the locked section (so I can't have something like a counter for generating unique values, unless somehow scala has static function variables). I thought on somehow
- Is there any way to prettify the syntax of the anonymouse function? Specifically, something that will make my code look like
lock1 ("id") { /* code goes here */ }or any other prettier look. - A bit silly to ask in this stage, but I'll ask anyway - Am I re-inventing the wheel? (i.e. does something like this exist?)
Wild final thought: I know that abusing the synchronized keyword (at least in java) can gaurantee that there would be only one execution of the code (in the sense that no multiple threads can enter that part of the code at the same time). I don't think it prevents from the same thread to execute the code twice (although I may be wrong here). Anyway, if it does prevent it, I still don't want it (even thoug my program is single threaded) since I'm pretty sure it will lead to a deadlock and won't report an exception.
Edit: Just to make it clearer, this project is for error debugging purposes and for learning scala. It has no real useage other than easily finding code errors at runtime (for detecting recursion where it shouldn't happen). See the comments to this post.
def bad:Unit = { lock1("hi", () => bad) }and then runbad. I agree that this mechanisem can be used for more than just preventing recursion, but recursion prevention was the original reason it was created for