Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When we should use scala.util.DynamicVariable?

When I read the source of scalatra, I found there are some code like:

protected val _response   = new DynamicVariable[HttpServletResponse](null) protected val _request    = new DynamicVariable[HttpServletRequest](null) 

There is an interesting class named DynamicVariable. I've looked at the doc of this class, but I don't know when and why we should use it? It has a withValue() which is usually be used.

If we don't use it, then what code we should use instead, to solve the problem it solved?

(I'm new to scala, if you can provide some code, that will be great)

like image 991
Freewind Avatar asked Feb 25 '11 10:02

Freewind


2 Answers

DynamicVariable is an implementation of the loan and dynamic scope patterns. Use-case of DynamicVariable is pretty much similar to ThreadLocal in Java (as a matter of fact, DynamicVariable uses InheritableThreadLocal behind the scenes) - it's used, when you need to do a computation within an enclosed scope, where every thread has it's own copy of the variable's value:

dynamicVariable.withValue(value){ valueInContext =>   // value used in the context }  

Given that DynamicVariable uses an inheritable ThreadLocal, value of the variable is passed to the threads spawned in the context:

dynamicVariable.withValue(value){ valueInContext =>   spawn{     // value is passed to the spawned thread   } } 

DynamicVariable (and ThreadLocal) is used in Scalatra for the same reason it's used in many other frameworks (Lift, Spring, Struts, etc.) - it's a non-intrusive way to store and pass around context(thread)-specific information.

Making HttpServletResponse and HttpServletRequest dynamic variables (and, thus, binding to a specific thread that processes request) is just the easiest way to obtain them anywhere in the code (not passing through method arguments or anyhow else explicitly).

like image 168
Vasil Remeniuk Avatar answered Nov 08 '22 00:11

Vasil Remeniuk


This is well answered by Vasil, but I'll add an additional simple example that might further help understanding.

Suppose we must use some code that uses println() to write all over stdout. We want this output to go to a log file, but we don't have access to the source.

  • println() uses Console.println()
  • Console.println() (fortunately) is based on a DynamicVariable[PrintStream] that defaults to java.lang.System.out
  • Console defines withOut that just forwards to the dynamic variable's withValue

We can use this to simply fix our issue:

def noisy() { println("robot human robot human") } noisy() // prints to stdout val ps = new java.io.PrintStream("/tmp/mylog") scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file 
like image 31
overthink Avatar answered Nov 08 '22 00:11

overthink