views:

111

answers:

3

OK the question might not say much, but here's the deal: I'm learning scala and decided to make an utility class "FuncThread" with a method which receives a by-name parameter function (I guess its called that because it's a function but without a parameter list) and then starts a thread with a runable which in turn executes the passed function, I wrote such a class as follows:

class FuncThread
{
   def runInThread( func: => Unit)
   {
     val thread = new Thread(new Runnable()
     {
        def run()
        {
          func
        }
     }

     thread.start()
   }
}

Then I wrote a junit test as follows:

@Test
def weirdBehaivorTest()
{
  var executed = false
  val util = new FuncThread()
  util.runInThread
  {
    executed = true
  }

  //the next line makes the test pass....
  //val nonSense : () => Unit  = () => { Console println "???" }

  assertTrue(executed)
}

If I uncomment the second commented line, the test passes but if it remains commented the test fails, is this the correct behaviour? how and when do by-name parameter functions get executed?

I know Scala has the actors library but I wanted to try this since I've always wanted to do this in Java

+6  A: 

Is this just a race condition? runInThread starts the thread but your assertion tests 'executed' before the other thread sets it to true. Adding your extra line means more code (and so time) is executed before the test, making it more likely that 'executed' has been set to true

Paul
wow that was it, a race condition, just added a sleep(10) and that fixed it!
Harima555
No, you added a sleep(10) and that masked the error, without fixing it.
Dave Griffith
yes you are right, ,i should use wait/notify instead, but just wanted to throw a quick test to play with scala =)
Harima555
@Harima555 In fact, without a memory barrier, such as what is provided by synchronize, you can never guarantee changes made by one thread get seen by the other thread. Look up Java Memory Model.
Daniel
A: 

This is not an answer, it's a comment, but I can't add a comment yet...

-You are missing a closed parenthesis just before thread.start()

-And welcome to the "I've always wanted to do this in Java" club

Adrian
+2  A: 

It's also worth noting that (as of Scala 2.8), the construct you were trying to write is available in the standard library

import scala.actors.Futures._

future{
    executed = true
}

This construct is actually more powerful than what you're describing, the thread calculation can return a value, and which can be waited for.

import scala.actors.Futures._

//forks off expensive calculation
val expensiveToCalculateNumber:Future[Int] = future{
    bigExpensiveCalculation()  
}

// do a lot of other stuff

//print out the result of the expensive calculation if it's ready, otherwise wait until it is
println( expensiveToCalculateNumber());
Dave Griffith
so nice! thanks for pointing at it, i haven't taken a full look at the actor's package, but the more i discover scala the more i fall in love with it =)
Harima555