CS 330 Lecture 37 – Promises and Futures
Agenda
- what ?s
- evaluate this
- synchronous asynchronicity
- futures in Scala
- promises in JavaScript
TODO
- Some folks have asked for a few more opportunities for participation points. I will grant 3 extra credit participation points to any student who gives a semi-lightning talk and demo (5-8 minutes) during lecture next Wednesday on some contained and interesting programming language feature. You may work in pairs. Please express your interest and submit your topic before Monday. You need not be an expert on the subject; just be curious and do some investigation. Some topics I would strongly encourage you to report on include:
- JavaScript’s inheritance mechanism
- Actor-based program design
- Lambdas in Java 8
- Java’s Streams API
Intentions
- I recognize the tension between synchronicity, which tends to produce straightforward but slow code, and asynchronicity, which tends to produce paranoid but fast code.
- I am familiar with several mechanisms (futures and promises) for introducing asynchronous operations but retaining a synchronous feel of control.
Evaluate This
How should we evaluate the following entities? Eagerly? Eagerly but asynchronously? Lazily?
- A nearby region in an interactive 3D world
- Full resolution images hosted by a photo storage service and accessed on a mobile app
- The hash code of a string
- An index of your hard drive
- The bodies of email messages
- The balance of your checking account
Code
Future.scala
import java.awt.image.BufferedImage
import javax.swing.JLabel
import javax.swing.ImageIcon
import java.awt.Color
import java.io.File
import java.awt.Robot
import javax.swing.JFrame
import javax.imageio.ImageIO
import scala.math._
class Future[T](thunk : => T) {
private var cache : T = _
private val thread = new Thread {
override def run {
cache = thunk
}
}
println("about to start thread")
// thread.run
thread.start
println("started thread")
def apply(): T = {
while (cache == null) {
try {
println("force")
thread.join
} catch {
case e : InterruptedException => {}
}
}
cache
}
}
object Main {
def main(args: Array[String]) {
val future = new Future[BufferedImage]({
val in = ImageIO.read(new File("/Users/johnch/Desktop/front_page.jpg"))
Thread.sleep(5000)
val out = new BufferedImage(in.getWidth, in.getHeight, in.getType)
for (c <- 0 until out.getWidth; r <- 0 until out.getHeight) {
val color = new Color(in.getRGB(c, r));
val swappedColor = new Color(color.getBlue, color.getGreen, color.getRed);
out.setRGB(c, r, swappedColor.getRGB);
}
out
})
println("other important stuff")
// Do other very important work.
val radius = 120
val r = new Robot
for (t <- 0 to 720 by 2) {
val x = 4.0 * sin(toRadians(t))
val y = sin(2 * toRadians(t))
r.mouseMove((radius * x + 600).toInt, (radius * 1.5 * y + 300).toInt)
r.delay(10)
}
new ImagePopup(future())
new ImagePopup(future())
new ImagePopup(future())
new ImagePopup(future())
new ImagePopup(future())
}
}
class ImagePopup(val image : BufferedImage) extends JFrame {
add(new JLabel(new ImageIcon(image)))
pack
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
setVisible(true)
}
promise.html
<!DOCTYPE html>
<html>
<head>
<title>...</title>
</head>
<body>
<img src="" id="red"/>
<img src="" id="yellow"/><br/>
<img src="" id="green"/>
<img src="" id="blue"/>
<script>
function load(color, delay) {
var img = document.querySelector('#' + color);
img.onload = function() {
console.log(color);
// resolve();
}
img.src = 'slow_image.php?color=' + color + '&delay=' + delay;
}
load('red', 1);
load('yellow', 2);
load('green', 3);
load('blue', 4);
</script>
</body>
</html>
Haiku
on callback hell
Old Phoenix burned up
But he forgot to hit Next
No more phoenixes
Old Phoenix burned up
But he forgot to hit Next
No more phoenixes