Narazil jsem na pěkné vysvětlení IFuture s pěkným příkladem od Malcolma Grovese. Zásadní informace je, že IFuture není hodnota, kterou budete počítat v budoucnu, ale hodnota, kterou budete v budoucnu potřebovat. Tato jemná nuance je zásadní.
Krása použití paralelního programování v XE7 vynikne, až člověk změní myšlení. Přiznám se, že mi to trvá.
Uvedený příklad z klasického programování. Mějme metodu, která provádí operaci po dvou dlouhých suboperacích.
procedure TFormThreading.OrderItem(const CustomerID, ItemID: String; OrderQty: Integer);
var
StockLevel : Integer;
PaidTheirBills : Boolean;
begin
StockLevel := GetStockLevel(ItemID); // velmi pomalé
PaidTheirBills := HaveTheyPaid(CustomerID); // také velmi pomalé
if (StockLevel >= OrderQty) and (PaidTheirBills) then
// proveď objednávku
end;
Pokud použijeme paralelní zpracování, konkrétně IFuture (a budou splněny podmínky jako počet procesorů, resp. např. neblokování připojení k DB), dosáhneme velmi výrazné úspory, která závisí na tom, jaký je poměr délky vykonávání dílčích úkolů. Pokud trvají zhruba stejně, dostaneme se na polovinu celkového času.
procedure TFormThreading.OrderItem(const CustomerID, ItemID: String; OrderQty: Integer);
var
StockLevel : IFuture<Integer>;
PaidTheirBills : Boolean;
begin
StockLevel := TTask.Future(function : Integer
begin
// velmi pomalé
Result := GetStockLevel(ItemID);
end);
PaidTheirBills := HaveTheyPaid(CustomerID); // také velmi pomalé
if (StockLevel.Value >= OrderQty) and (PaidTheirBills) then
// proveď objednávku
end;
Všimněte si prosím, jak StockLevel je prováděn přes IFuture za pomocí anonymní metody. Tímto je StockLevel prováděn paralelně a hlavní vykonávání začíná počítat PaidTheirBills.
Výsledná podmínka je kritická, protože:
Tudíž celá podmínka je provedena až po dokončení výpočtu obou hodnot.
Není to krása?