systems programming beyond using c and d three unlikely
play

Systems Programming & Beyond using C++ and D Three Unlikely - PowerPoint PPT Presentation

Systems Programming & Beyond using C++ and D Three Unlikely Successful Features of D Andrei Alexandrescu andrei@erdani.com Prepared for LASER Summer School 2012 1 / 42 2012 Andrei Alexandrescu. c 1. The scope Statement: Casual


  1. Systems Programming & Beyond using C++ and D Three Unlikely Successful Features of D Andrei Alexandrescu andrei@erdani.com Prepared for LASER Summer School 2012 1 / 42 � 2012– Andrei Alexandrescu. c

  2. 1. The scope Statement: Casual Correct Code 2 / 42 � 2012– Andrei Alexandrescu. c

  3. � action � 3 / 42 � 2012– Andrei Alexandrescu. c

  4. � action � � cleanup � 3 / 42 � 2012– Andrei Alexandrescu. c

  5. � action � � cleanup � � next � 3 / 42 � 2012– Andrei Alexandrescu. c

  6. � action � � cleanup � � next � � rollback � 3 / 42 � 2012– Andrei Alexandrescu. c

  7. C if ( � action � ) { if (! � next � ) { � rollback � } � cleanup � } 4 / 42 � 2012– Andrei Alexandrescu. c

  8. C++ class RAII { RAII() { � action � } ~RAII() { � cleanup � } }; ... RAII raii; try { � next � } catch (...) { � rollback � throw; } 5 / 42 � 2012– Andrei Alexandrescu. c

  9. Java, C# � action � try { � next � } catch (Exception e) { � rollback � throw e; } finally { � cleanup � } 6 / 42 � 2012– Andrei Alexandrescu. c

  10. Go result, error := � action � if error != nil { defer � cleanup � if ! � next � � rollback � } 7 / 42 � 2012– Andrei Alexandrescu. c

  11. Composition

  12. C if ( � action 1 � ) { if ( � action 2 � ) { if (! � next 2 � ) { � rollback 2 � � rollback 1 � } � cleanup 2 � } else { � rollback 1 � } � cleanup 1 � } 9 / 42 � 2012– Andrei Alexandrescu. c

  13. C++ class RAII1 { RAII1() { � action 1 � } ~RAII1() { � cleanup 1 � } }; class RAII2 { RAII2() { � action 2 � } ~RAII2() { � cleanup 2 � } }; ... 10 / 42 � 2012– Andrei Alexandrescu. c

  14. C++ RAII1 raii1; try { RAII2 raii2; try { � next 2 � } catch (...) { � rollback 2 � throw; } } catch (...) { � rollback 1 � throw; } 11 / 42 � 2012– Andrei Alexandrescu. c

  15. Java, C# � action 1 � try { � action 2 � try { � next 2 � } catch (Exception e) { � rollback 2 � throw e; } finally { � cleanup 2 � } } catch (Exception e) { � rollback 1 � throw e; } finally { � cleanup 1 � } 12 / 42 � 2012– Andrei Alexandrescu. c

  16. Go result1, error := � action 1 � if error != nil { defer � cleanup 1 � result2, error := � action 2 � if error != nil { defer � cleanup 2 � if ! � next 2 � � rollback 2 � } else { � rollback 2 � } } 13 / 42 � 2012– Andrei Alexandrescu. c

  17. Dislocation + Nesting = Fail 14 / 42 � 2012– Andrei Alexandrescu. c

  18. “Programs must be written for people to read, and only incidentally for machines to execute.” – Abelson/Sussman, SICP 15 / 42 � 2012– Andrei Alexandrescu. c

  19. “Error handling is about maintaining program invariants, and only incidentally about dealing with the error itself.” – I. Meade Etop 16 / 42 � 2012– Andrei Alexandrescu. c

  20. Enter D � action � scope(failure) � rollback � scope(exit) � cleanup � 17 / 42 � 2012– Andrei Alexandrescu. c

  21. But wait, there’s more (of the same) � action 1 � scope(failure) � rollback 1 � scope(exit) � cleanup 1 � � action 2 � scope(failure) � rollback 2 � scope(exit) � cleanup 2 � 18 / 42 � 2012– Andrei Alexandrescu. c

  22. Three’s a charm � action 1 � scope(failure) � rollback 1 � scope(exit) � cleanup 1 � � action 2 � scope(failure) � rollback 2 � scope(exit) � cleanup 2 � � action 3 � scope(failure) � rollback 3 � scope(exit) � cleanup 3 � ... moar please ... 19 / 42 � 2012– Andrei Alexandrescu. c

  23. Transactional File Copy import std.exception, std.file, std.stdio; void main(string[] args) { enforce(args.length == 3, "Usage: ..."); scope(success) rename(args[2] ~ ".tmp", args[2]); auto src = File(args[1]), tgt = File(args[2] ~ ".tmp", "w"); scope(failure) remove(args[2] ~ ".tmp"); foreach (chunk; src.byChunk(1024 * 64)) { tgt.rawWrite(chunk); } } 20 / 42 � 2012– Andrei Alexandrescu. c

  24. 2-5x improvement on relevant metrics 21 / 42 � 2012– Andrei Alexandrescu. c

  25. . . . on code you write 22 / 42 � 2012– Andrei Alexandrescu. c

  26. Straight line + Implicit flow = Win 23 / 42 � 2012– Andrei Alexandrescu. c

  27. 2. Built-in Arrays 24 / 42 � 2012– Andrei Alexandrescu. c

  28. Systems-Level Language 25 / 42 � 2012– Andrei Alexandrescu. c

  29. Pointers? 26 / 42 � 2012– Andrei Alexandrescu. c

  30. Unsafe iteration Unsafe arithmetic Efficient 27 / 42 � 2012– Andrei Alexandrescu. c

  31. D array = pointer + length a · · · · · · 1 5 2 3 6 b 28 / 42 � 2012– Andrei Alexandrescu. c

  32. Safe iteration Safe indexing Efficient Enabling 29 / 42 � 2012– Andrei Alexandrescu. c

  33. Cheap, type-preserving slicing b = b[1 .. $ - 1]; a · · · · · · 1 5 2 3 6 b 30 / 42 � 2012– Andrei Alexandrescu. c

  34. Convenient bool palindrome(T)(T[] a) { for (; a.length > 1; a = a[1 .. $ - 1]) { if (a[0] != a[$ - 1]) return false; } return true; } 31 / 42 � 2012– Andrei Alexandrescu. c

  35. Value Range Propagation 32 / 42 � 2012– Andrei Alexandrescu. c

  36. Integral types • The usual menagerie: 8, 16, 32, 64 signed and unsigned integrals • 32, 64 and sometimes 80-bit floating point types • The C operator paraphernalia ◦ Defined the same way in all implementations ◦ C code: either compiles and runs with same results, or doesn’t compile 33 / 42 � 2012– Andrei Alexandrescu. c

  37. Conversions • Many type widths beget conversion problems short a; byte b; uint c; auto d = a * b + c; // what’s the type of d? • auto increases the cost of complicated rules • Each language tried to work it out its own set of rules 34 / 42 � 2012– Andrei Alexandrescu. c

  38. C Rules • Default result of operators is int • Unless a long is involved • Unless an unsigned is within a mile radius • Unless the unsigned is shorter than the result type computed as above • Bottom line: everything is (u)int or (u)long • Trust the programmer ⇒ long to char is implicit! 35 / 42 � 2012– Andrei Alexandrescu. c

  39. High Level/Scripting Languages • Generally use unbounded-length integrals • Devise representation based on actual magnitude • That path can’t be taken by a systems language • However, D has a heavily optimized library type BigInt 36 / 42 � 2012– Andrei Alexandrescu. c

  40. Java, C# • Start from C’s rules • Play it Safe ⇒ No narrowing conversions allowed // This is not D code byte a, b, c; a = (byte) (a | b & c); b = (byte) (b | 1); • Net result: casts galore 37 / 42 � 2012– Andrei Alexandrescu. c

  41. Value Range Propagation (VRP) • During an expression, maintain the min/max values of intermediate results • For compile-time constants: min_c = max_c = c • For variables: the representable limits byte a, b, c; a = a | b & c; // range -128..127 b = b | 1; // range 0..1 • No casts needed • Yet typeof(b | 1) is int ! 38 / 42 � 2012– Andrei Alexandrescu. c

  42. VRP Never Truncates • D allows implicit narrowing if and only if the range fits within the target type byte a, b, c; a = a | b + c; // error b = c * 2; // error 39 / 42 � 2012– Andrei Alexandrescu. c

  43. VRP Is Imperfect • No “memory” beyond one statement byte a, b, c; a = 1; b = c | a; // error • However, it practically works surprisingly well • Can be improved to work across statements • Can be improved to account for control flow • Extra compilation costs (time, memory) must be justifiable 40 / 42 � 2012– Andrei Alexandrescu. c

  44. Summary 41 / 42 � 2012– Andrei Alexandrescu. c

  45. Summary 1. The scope statement 42 / 42 � 2012– Andrei Alexandrescu. c

  46. Summary 1. The scope statement 2. Built-in arrays 42 / 42 � 2012– Andrei Alexandrescu. c

  47. Summary 1. The scope statement 2. Built-in arrays 3. Value range propagation 42 / 42 � 2012– Andrei Alexandrescu. c

Recommend


More recommend