Futures

Introduction

If you have code that depends on the result of slow functions, you want these functions to be executing in the background in separate threads while your main code is doing something else. Your main thread will then wait if necessary to use the functions' return values. This demonstration code shows you how easy it is to declare and use futures in order to make efficient use of threads.

The preceding page describes an easy way to add the required runtime file com.remobjects.oxygene.rtl.jar to same folder as FunWithFutures.jar.

Study the code below then learn from the screenshot of the informative output below it.

Code of FunWithFutures.pas

namespace FunWithFutures;

interface

type
  ConsoleApp = static class
  private
    method Fast: String;
    method Medium: String;
    method Slow: String;
  public
    method Main(args: array of String);
  end;

implementation

method ConsoleApp.Main(args: array of String);
var 
  f, m, s: future String;
  newLine : String := System.lineSeparator;
begin
  writeLn('Welcome to the Future.' + newLine);  
  writeLn('Test 1: Sync Futures' + newLine);
  writeLn('In this first and simplest case, two variables will be initialized to regular');
  writeLn('NON-ASYNC futures. As a result, "m" will be evaluated after "s":' + newLine);
  s :=  Slow;
  m := Medium;
  writeLn(s + m);

  writeLn(newLine + 'Test 2: One Async Future'#13#10);
  writeLn('Now, we use an ASYNC future for the second value. While "s" is being evaluated');
  writeLn('inline, "m" can already start processing in the background and will, in fact, ');
  writeLn('be ready by the time it is needed.' + newLine);

  s := Slow;
  m := async Medium;
  writeLn(s + m);

  writeLn(newLine + 'Test 3: More Async Futures' + newLine);
  writeLn('In fact, several async futures can run in parallel, CPU cores permitting,');
  writeLn('so that in the following scenario, both "s" and "m" evaluate in the background.' + newLine);
  writeLn('Note that "f" of course finishes first, and execution will then block to wait');
  writeLn('for "s" and then "m" to be finished.' + newLine);

  f := Fast;
  s := async Slow;
  m := async Medium;
  writeLn(f + s + m);

  writeLn(newLine + 'Test 4: Futures with Anonymous Methods and Lambdas' + newLine);
  writeLn('Instead of calling methods, we can also provide a value to a future via');
  writeLn('an anonymous method or a lambda expression (which really are just two');
  writeLn('syntaxes for the same underlying thing. Note also that since we do not');
  writeLn('reassign "m", but do reuse it, the "Medium" method will not be called');
  writeLn('again. A future is evaluated once only per assignment, and its value');
  writeLn('is then available immediately, any time you reference the future.' + newLine);

  f := -> begin writeLn('-> Fast lambda'); result:= 'Fast lambda result '; writeLn('-> Fast lambda'); end;
  s := async method: String 
        begin 
          writeLn('-> Slow anon'); 
          Thread.Sleep(3000);
          result := 'Slow anon result '; 
          writeLn('<- Slow anon'); 
        end;
  writeLn(f + s + m);
  writeLn(newLine + "That's it. press enter to quit."); 
  System.in.read;
end;

method ConsoleApp.Fast: String;
begin
  writeLn('-> Fast');
  Thread.Sleep(10);
  result := 'Fast result ';
  writeLn('<- Fast');
end;

method ConsoleApp.Medium: String;
begin
  writeLn('-> Medium');
  Thread.Sleep(1000);
  result := 'Medium result ';
  writeLn('<- Medium');
end;

method ConsoleApp.Slow: String;
begin
  writeLn('-> Slow');
  Thread.Sleep(3000);
  result := 'Slow result ';
  writeLn('<- Slow');
end;

end.

Output from FunWithFutures

Output from FunWithFutures

Programming - a skill for life!

Language features such as loops, generics, class contracts, asynchronous methods, futures and Sugar in Oxygene for Java