Exemplo n.º 1
0
def design(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Design by community")

    list = content.box()
    list_item(list).text("Open source")
    list_item(list).text("RFC")
    list.box(width=700, height=200, p_top=40).image("imgs/rust-rfc.png")

    slide = slides.new_slide()
    content = slide_header(slide, "Backwards compatibility")

    small = s(size=28)

    list = content.box()
    list_item(list).text("Strong BC guarantees")
    list_item(list, show="2+").text("New version every 6 weeks")
    list_item(list, show="2+", level=1).text(
        "Thousands of libraries tested to spot regressions", style=small)
    list_item(list, show="3+").text("Big changes => new edition")
    list_item(list, show="3+", level=1).text("Rust 2015 vs Rust 2018",
                                             style=small)

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Unstable features")

    code(content.box(), """
#![feature(async_await)]
async fn foo() {
    ...
}""")

    content.box(height=20)
    bash(content.box(show="2+"), "$ cargo +nightly build")
Exemplo n.º 2
0
def parallelization(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Concurrency primitives")

    list = content.box()
    list_item(list).text("Mutexes")
    list_item(list, show="next+").text("Condition variables")
    list_item(list, show="next+").text("Atomics")
    list_item(list, show="next+").text("Synchronized queues")

    slide = slides.new_slide()
    slide.update_style("code", s(size=30))
    content = slide_header(slide, "Shared-memory parallelism")
    content.box().text("No OpenMP ☹")

    code_width = 800

    content.box(height=40)
    rayon = content.box(show="2+")
    rayon_box = rayon.box(horizontal=True)
    rayon_box.box().text("Rayon (+ Rayon adaptive")
    rayon_box.box(width=20)
    rayon_box.box(width=60).image("imgs/saurabh.png")
    rayon_box.box().text(" )")
    rayon.box(height=30)
    code_box = code(rayon.box(),
                    """
fn sum_of_squares(input: &[i32]) -> i32 {
    input.par_iter()
         .map(|&i| i * i)
         .sum()
}""",
                    width=code_width)
    code_box.line_box(1, z_level=99, x=165, width=165,
                      show="3+").rect(bg_color=CODE_HIGHLIGHT_COLOR)

    code(rayon.box(show="4+"),
         """
#[parallel]
for x in 0..10 {
    println!("{}", x);
}""",
         width=code_width)

    slide = slides.new_slide()
    slide.update_style("code", s(size=26))
    content = slide_header(slide, "Message-passing")
    code(
        content, """
let universe = mpi::initialize();
let world = universe.world();
let size = world.size();
let rank = world.rank();

if rank == 0 {
    let (msg, status) = world.any_process().receive_vec();
}
""")
Exemplo n.º 3
0
def intrinsics(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=38))

    content = slide_header(slide, "Branch prediction")

    code(
        content.box(), """
if core::intrinsic::likely(condition) {
    ...
} else #[cold] {
    ...
}""")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    content = slide_header(slide, "SIMD")

    code_width = 900
    code(content.box(),
         """
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::_mm256_add_epi64;

_mm256_add_epi64(...);""",
         width=code_width)

    content.box(height=50)
    code(content.box(show="2+"),
         """
data.simd_iter()
    .simd_map(|v| {
        f32s(9.0) * v.abs().sqrt().ceil() -
        f32s(4.0) - f32s(2.0)
    })
    .scalar_collect();""",
         width=code_width)

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Inline assembly")

    code(
        content.box(), """
fn add(a: i32, b: i32) -> i32 {
    let c: i32;
    unsafe {
        asm!("add $2, $0"
             : "=r"(c)
             : "0"(a), "r"(b));
    }
    c
}""")
Exemplo n.º 4
0
def rust_safety(slides: Slides):
    slide = slides.new_slide()
    slide.set_style("text", s(size=60, bold=True))

    slide.box().text("Rust is safe...", style="text")
    slide.box(show="2+").text("...but from what?", style="text")

    slide = slides.new_slide()
    content = slide_header(slide, "Undefined behaviour")
    content.box(width=800).image("imgs/cpp-undefined.png")

    slide = slides.new_slide()
    content = slide_header(slide, "UB in Java")
    content.box().text("Java::Iterator::remove")
    with_bg(content.box()).text(
        """“The behavior of an iterator is ~emph{unspecified} if the underlying
collection is modified while the iteration is in progress in any way
other than by calling this method, unless an overriding class has specified
a concurrent modification policy.”
""",
        style=s(size=28, align="left"))

    slide = slides.new_slide()
    content = slide_header(slide, "UB in Python")
    content.box().text("~tt{for} statement")
    with_bg(content.box()).text(
        """“There is a subtlety when the sequence is being modified by the loop (this can only
occur for mutable sequences, e.g. lists). An internal counter is used to keep track
of which item ... ~emph{This can lead to nasty bugs} that can be avoided by making a
temporary copy using a slice of the whole sequence ...”
""",
        style=s(size=24, align="left"))

    slide = slides.new_slide()
    content = slide_header(slide, "Sources of UB")
    list = content.box()
    items = [
        "Null pointer dereference", "Double-free", "Use-after-free",
        "Out-of-bounds access", "Integer conversion", "Integer overflow",
        "Iterator invalidation", "Invalid alignment", "…"
    ]
    for item in items:
        list_item(list, show="next+").text(item)

    content.box(height=20)
    content.box(show="next+").text(
        "Rust tries very hard to avoid all of the above",
        style=s(size=44, bold=True))
Exemplo n.º 5
0
def intro_slide(slides: Slides):
    slide = slides.new_slide()
    slide.set_style("text", s(size=60, bold=True))
    slide.set_style("orange",
                    slide.get_style("text").compose(s(color="orange")))

    safe = slide.box()
    safe.text("Fast & ~orange{Safe}", style="text")

    slide.box(height=100)

    line = slide.box(width="fill", horizontal=True)
    development = line.box(width="50%", y=0)
    development.overlay(show="2-3").text("Memory safety")
    development.overlay(show="4").text("Memory safety",
                                       style=s(color="orange"))
    performance = line.box(width="50%", y=0, show="3+")
    performance.text("Fearless concurrency")

    arrow = Arrow(20)
    slide.box(show="2+").line(
        [safe.p("80%", "100%"), development.p("50%", 0)],
        stroke_width=5,
        color="orange",
        end_arrow=arrow)
    slide.box(show="3+").line(
        [safe.p("80%", "100%"), performance.p("50%", 0)],
        stroke_width=5,
        color="orange",
        end_arrow=arrow)
Exemplo n.º 6
0
def adt(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=26))
    content = slide_header(
        slide, """Algebraic data types/tagged unions/sum types/
discriminated unions/variants""")

    code_width = 960
    code(content.box(),
         """
enum Packet {
    Header { source: u32, tag: u32, data: Vec<u8> },
    Payload { data: Vec<u8> },
    Ack { seq: u64 }
}""",
         width=code_width)

    content.box(height=10)
    content.box(show="next+").text("Pattern matching",
                                   style=s(bold=True, size=40))

    code(content.box(show="last+"),
         """
match socket.get_packet() {
    Header {data, ..} | Payload {data, ..} => { },
    _ => { println!("Packet without data"); }
}
""",
         width=code_width)

    content.box(height=10)
    content.box(
        show="next+").text("The compiler forces you to handle all variants")
Exemplo n.º 7
0
def zero_cost(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Zero-cost abstractions")
    content.box().text("Bjarne Stroustrup:", s(size=60))

    with_bg(content.box()).text("""What you don’t use, you don’t pay for.
What you do use, you couldn’t hand code any better.""")
Exemplo n.º 8
0
def structures(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=26))
    content = slide_header(slide, "Structures")

    code_width = 920
    code(content.box(),
         """
struct Person {
    pub age: u32,
    name: String
}
""",
         width=code_width)

    code(content.box(show="next+"),
         """
impl Person {
    pub fn new(age: u32, name: String) -> Person {
        Person { age, name }
    }
    pub fn is_adult(&self) -> bool {
        self.age >= 18
    }
}    
""",
         width=code_width)
Exemplo n.º 9
0
def intro_slide(slides: Slides):
    slide = slides.new_slide()
    slide.set_style("text", s(size=60, bold=True))
    slide.set_style("orange", slide.get_style("text"), s(color="orange"))

    fast = slide.box()
    fast.text("~orange{Fast} & Safe", style="text")

    slide.box(height=100)

    line = slide.box(width="fill", horizontal=True)
    development = line.box(width="50%", y=0)
    development.overlay().text("Quick development")
    performance = line.box(width="50%", y=0)
    performance.text("High performance", style=s(color="orange"))

    arrow = Arrow(20)
    slide.box().line(
        [fast.p("15%", "100%"), development.p("50%", 0)],
        stroke_width=5,
        color="orange",
        end_arrow=arrow)
    slide.box().line(
        [fast.p("15%", "100%"), performance.p("50%", 0)],
        stroke_width=5,
        color="orange",
        end_arrow=arrow)
Exemplo n.º 10
0
def benchmark_game(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Benchmark game")
    content.box(width=900).image("imgs/benchmark-game.png")
    content.box().text(
        "https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/gpp"
        "-rust.html",
        style=s(size=20))
Exemplo n.º 11
0
def runtime(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("default", s(size=40))
    content = slide_header(slide, "Minimal runtime")

    list = content.box()
    list_item(list, show="next+").text("No GC")
    list.box(width=600, height=400, show="last+",
             padding=0).image("imgs/gc.svg")
    list_item(list, show="next+").text("No exceptions")
    list_item(list, show="next+").text("Tight data layout")
    list_item(list, show="next+").text("Supports embedded platforms")
Exemplo n.º 12
0
def llvm_iterator(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Compiles to LLVM")
    content.box(height=600, x=350).image("imgs/llvm-flow.svg")

    slide = slides.new_slide()
    content = slide_header(slide, "Compiles to LLVM")
    src = content.box(width=700, height=100)
    src.image("imgs/godbolt-dot-product.svg")

    content.box(height=60)
    assembly = content.box(width="fill", height=400, show="2+")
    assembly.image("imgs/godbolt-dot-product-assembly.svg")

    arrow = Arrow(20)
    content.box(show="2+").line(
        [src.p("50%", "100%"),
         assembly.p("50%", "0%").add(0, -10)],
        stroke_width=5,
        color="orange",
        end_arrow=arrow)
Exemplo n.º 13
0
def multiphase_compiler(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    content = slide_header(slide, "Multi-phase compiler")

    code(
        content.box(), """
fn main() {
    look_ma_no_forward_declaration();
}

fn look_ma_no_forward_declaration() { }
""")
Exemplo n.º 14
0
def concurrency_issues(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Concurrency issues")

    content.box().text("Rust doesn't prevent:")
    list = content.box()
    list_item(list, show="next+").text("Deadlocks")
    list_item(list, show="next+").text("General race conditions")

    content.box(height=20)
    content.box(show="next+").text("Rust prevents (at compile time):")
    list = content.box()
    list_item(list, show="next+").text("Data races")

    slide = slides.new_slide()
    content = slide_header(slide, "What causes data races?")

    text_style = s(size=50)
    content.box(show="next+").text("Concurrent aliasing and mutability...", style=text_style)
    content.box(show="next+").text("...but Rust already disables that!", style=text_style)

    content.box(height=20)
    content.box(show="next+").text("So how do we get any concurrency at all...?", style=text_style)
Exemplo n.º 15
0
def caveats(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Performance caveats")

    l1_style = s(size=26)

    list = content.box()
    list_item(list).text("Out-of-bounds checks")
    list_item(list, level=1,
              show="2+").text("Can be optimized away (iterators)",
                              style=l1_style)
    list_item(list, show="3+").text("Integer overflow is not undefined")
    list_item(list, level=1,
              show="4+").text("Runtime checks only in debug mode",
                              style=l1_style)
Exemplo n.º 16
0
def constexpr(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=38))

    content = slide_header(slide, "Constexpr functions")

    code(
        content.box(), """
const fn double(x: i32) -> i32 {
    x * 2
}

const FIVE: i32 = 5;
const TEN: i32 = double(FIVE);
""")
Exemplo n.º 17
0
def intro(slides: Slides):
    slide = slides.new_slide()
    slide.set_style("title", s(size=60, bold=True))
    slide.set_style("name", s(size=30))

    slide.sbox(height="30%").image("imgs/logo.svg")
    slide.box(height=80)
    slide.box().text("Rust: Fast & Safe", "title")
    slide.box(height=20)
    slide.box().text("Jakub Beránek, Mathieu Fehr, Saurabh Raje", "name")

    slide = slides.new_slide()
    slide.box(width=500).image("imgs/meme-rust-meeting.jpg")

    slide = slides.new_slide()
    content = slide_header(slide, "What is Rust?")
    content.box().text("""
System programming language for building
reliable and efficient software.""")

    content.box(height=20)
    content.box(width="fill", height=150, show="2+").image("imgs/history.svg")
    content.box(height=20)
    content.box(width="fill", height=350, show="3+").image("imgs/users.svg")
Exemplo n.º 18
0
def generics(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=30))
    content = slide_header(slide, "Generics")

    code_width = 900

    code(content.box(),
         """
struct KeyValue<K, V> {
    key: K,
    value: V
}""",
         width=code_width)
    code(content.box(show="next+"),
         """
trait Buffer<T> {
    fn read(&self) -> T;    
}""",
         width=code_width)

    content.box(height=10)
    code(content.box(show="next+"),
         """
fn print_buffer<B: Buffer<T>, T: Display>(buffer: B) {
    println!("{}", buffer.read());
}""",
         width=code_width)
    code(content.box(show="next+"),
         """
fn print_bigger<T: PartialEq + Display>(a: T, b: T) {
    if (a > b) { println!("{}", a); }
}
""",
         width=code_width)

    content.box(height=10)
    code(content.box(show="next+"),
         """
impl <T: Display> Serialize for T {
    ...
}
""",
         width=code_width)
Exemplo n.º 19
0
def message_passing(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Message passing")

    code_width = 900
    code_step(content.box(width=code_width, height=300), """
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
    tx.send(5);
});
let received = rx.recv();
""", "1", (
        ("               mpsc::channel();", None, None, None, None),
        (0, None, None, None, None),
        (0, 1, 2, 3, None),
        (0, 1, 2, 3, 4)
    ), width=code_width)

    content.box(height=20)
    content.box(show="next+").text("""Splitting a channel into a receiver + sender removes aliasing
    and allows moving the sender independently of the receiver.""", s(size=34))
Exemplo n.º 20
0
def modules(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=24))
    slide.set_style("bold", s(bold=True))
    content = slide_header(slide, "Proper module system")

    line = content.box(width="fill", horizontal=True)
    lib = line.box(width="50%", y=0)
    text_box = lib.box()
    text_box.box(show="1").text("foo.rs")
    text_box.overlay(show="next+").text("~bold{foo}.rs")
    code(
        lib.box(), """
pub fn fun1() {
    println!("fun1");
}
fn fun2() {
    println!("fun2");
}
""")

    main = line.box(width="50%", y=0, show="2+")
    main.box().text("main.rs")
    code(
        main.box(), """
use foo;

fn main() {
    foo::fun1();
    // foo::fun2(); private
}""")

    content.box(height=60)
    advantages = content.box(show="3+")
    advantages.update_style("default", s(size=40))
    list_item(advantages).text("visibility control")
    list_item(advantages).text("self-contained")
Exemplo n.º 21
0
def c_interop(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=26))

    content = slide_header(slide, "C/C++ interop")

    code_width = 940
    c_from_rust = content.box()
    c_from_rust.text("C from Rust")
    code(content,
         """
extern {
    fn snappy_max_compressed_length(len: size_t) -> size_t;
}

let length = unsafe { snappy_max_compressed_length(100) };
""",
         width=code_width)

    content.box(height=20)
    box = content.box(show="2+")
    rust_from_c = box.box()
    rust_from_c.text("Rust from C")
    code(box,
         """
#[repr(C)]
struct Object {
    bar: i32,
}

extern "C" fn foo(param: *mut Object) {
    unsafe {
        (*target).bar = 5;
    }
}""",
         width=code_width)
Exemplo n.º 22
0
def unsafe(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=32))
    content = slide_header(slide, "Where's the catch?")
    content.box().text("We have seen things that mutate through a shared borrow")

    code_width = 800
    code_step(content.box(width=code_width, height=400), """
// Arc::clone
fn clone(&self) -> Arc<T>;
// Mutex::lock
fn lock(&self) -> &mut T;
// AtomicU64::store
fn store(&self, val: u64, order: Ordering);
""", 2, [
        (0, 1, None, None, None, None),
        (0, 1, 2, 3, None, None),
        (0, 1, 2, 3, 4, 5)
    ], width=code_width)

    content.box(show="5+").text("This is called ~tt{interior mutability} and requires unsafe Rust",
                                s(size=32))

    slide = slides.new_slide()
    content = slide_header(slide, "Enter unsafe Rust")
    content.box().text("Some scenarios are not expressible in (safe) Rust")

    content.box(height=20)
    content.box(show="next+").text("In some cases, something more is required to:")

    list = content.box()
    list_item(list, show="next+").text("Express inherently unsafe paradigms")
    list_item(list, show="next+").text("Improve performance")
    list_item(list, show="next+").text("Interact with I/O, OS, hardware, network")

    slide = slides.new_slide()
    content = slide_header(slide, "Unsafe Rust")

    content.box().text("You can mark parts of code with the ~tt{unsafe} keyword")
    content.box(show="next+").text("Unsafe Rust is a ~emph{superset} of Rust")

    def unsafe_slide(header, code_body, content_show="1", code_size=36):
        slide = slides.new_slide()
        slide.update_style("code", s(size=code_size))
        content = slide_header(slide, "Unsafe Rust")
        content.box(y=0).text("Unsafe Rust allows:")

        content.box(height=20)
        content.box(show=content_show).text(header)
        content.box(height=10)
        code(content.box(show=content_show), code_body)

    unsafe_slide("Accessing a global mutable variable", """
static mut COUNTER: u32 = 0;

fn increment_count() {
    unsafe {
        COUNTER += 1;
    }
}""", content_show="2+")
    unsafe_slide("Dereferencing a raw pointer", """
let ptr = 0xCAFECAFE as *mut u32;
unsafe {
    *ptr = 5;
}""")
    unsafe_slide("Calling an unsafe function", """
unsafe {
    zlib_compress(&buffer, buffer.len());
}""")
    unsafe_slide("Implementing an unsafe trait", """
unsafe impl Send for MySuperSafeType {
    ...
}""")

    slide = slides.new_slide()
    slide.update_style("code", s(size=18))
    content = slide_header(slide, "Finding unsafe code - C++")
    code_box = code(content, """
std::atomic<LifecycleId> ArenaImpl::lifecycle_id_generator_;
GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};

void ArenaImpl::Init() {
  lifecycle_id_ =
      lifecycle_id_generator_.fetch_add(1, std::memory_order_relaxed);
  hint_.store(nullptr, std::memory_order_relaxed);
  threads_.store(nullptr, std::memory_order_relaxed);

  if (initial_block_) {
    // Thread which calls Init() owns the first block. This allows the
    // single-threaded case to allocate on the first block without having to
    // perform atomic operations.
    new (initial_block_) Block(options_.initial_block_size, NULL);
    SerialArena* serial =
        SerialArena::New(initial_block_, &thread_cache(), this);
    serial->set_next(NULL);
    threads_.store(serial, std::memory_order_relaxed);
    space_allocated_.store(options_.initial_block_size,
                           std::memory_order_relaxed);
    CacheSerialArena(serial);
  } else {
    space_allocated_.store(0, std::memory_order_relaxed);
  }
}
""")
    code_box.overlay(show="2+", z_level=99).rect(bg_color=CODE_HIGHLIGHT_COLOR)

    slide = slides.new_slide()
    content = slide_header(slide, "Finding unsafe code - Rust")
    bash(content.box(), '$ grep "unsafe" main.rs', text_style=s(size=40))

    slide = slides.new_slide()
    slide.box().text("""Rust builds safe abstractions
on top of unsafe foundations""", s(size=50))
Exemplo n.º 23
0
def cpp_alias_mutate(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("default", s(size=50, bold=True))
    content = slide_header(slide, "Rust's insight")
    content.box(show="next+").text("""Memory errors arise when
aliasing is combined with mutability""")

    slide = slides.new_slide()
    slide.update_style("code", s(size=32))
    slide.set_style("gray",
                    slide.get_style("code").compose(s(color="#BBBBBB")))
    content = slide_header(slide, "C++ UB example")

    style_green = s(size=40, color="green")
    style_red = s(size=style_green.size, color="red")

    header = content.box(width=500, height=50, horizontal=True)
    header.overlay(show="2").text("Aliasing ✓", style=style_green)
    header.overlay(show="3").text("Mutability ✓", style=style_green)
    header.overlay(show="4+").text("Aliasing & Mutability", style=style_red)
    header.box(show="4+", width=100, x=450).image("imgs/boom.svg")

    content.box(height=20)
    wrapper = code_step(content.box(width=700, height=200),
                        """
std::vector<int> vec = { 1, 2, 3 };
int& p = vec[0];
vec.push_back(4);
std::cout << p << std::endl;
""",
                        1, [(0, None, None, None), (0, 1, None, 3),
                            (0, None, 2, None), (0, 1, 2, 3)],
                        language="cpp")

    wrapper.line_box(2, show="4+", z_level=99,
                     width=320).rect(bg_color=CODE_HIGHLIGHT_COLOR)
    wrapper.line_box(3, show="4+", z_level=99, x=235,
                     width=45).rect(bg_color=CODE_HIGHLIGHT_COLOR)

    slide = slides.new_slide()
    content = slide_header(slide, "What to do?")
    content.box(width=1000).image("imgs/meme-rust-aliasing.jpg")

    slide = slides.new_slide()
    content = slide_header(slide, "Rust's solution")

    large = s(size=50, bold=True)

    row = content.box(horizontal=True)
    row.box().text("You can mutate", style=large)
    row.box(width=20)
    row.box(show="next+").text("||", style=large)
    row.box(width=20)
    row.box(show="next+").text("alias", style=large)

    content.box(height=10)
    content.box(show="next+").text(
        "But not both at the same time (w.r.t. a single variable)")
    content.box(height=10)
    content.box(show="next+").text(
        "Rust enforces this at compile time using its type system")
Exemplo n.º 24
0
def shared_state(slides: Slides):
    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Spawning a thread")

    code(content.box(), "fn spawn<F: Fn + Send>(f: F)")

    content.box(height=20)
    content.box(show="next+").text("""Ownership of T can be transferred to another thread
only if T implements the ~emph{Send} trait""")

    content.box(height=20)
    content.box(show="next+").text("""Send is implemented automatically, unless the type
contains values that are not safe to be transferred between threads""", style=s(size=30))

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    content = slide_header(slide, "Shared state concurrency")
    content.box().text("Goal:", style=s(bold=True))
    list = content.box()
    list_item(list, show="next+").text("Spawn a thread")
    list_item(list, show="next+").text("Send a reference to some value to it")
    list_item(list, show="next+").text("Modify the value in the spawned thread")
    list_item(list, show="next+").text("Read the value in the original thread")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    (content, header) = slide_header(slide, "Shared state concurrency", True)
    box = header.box(width=160, y=80)
    box.image("imgs/meme-face-1.jpg")
    box.overlay(show="4").image("imgs/meme-face-2.jpg")

    code_step(content.box(width=800, height=350), """
let value = 5;
let p = &value;
thread::spawn(|| {
    println!("{}", *p);
});
""", 1, [(0, None, None, None, None),
         (0, 1, None, None, None),
         (0, 1, 2, 3, 4)], width=500)

    content.box(height=10)
    with_border(content, show="4+").box(height=220).image("imgs/concurrent-error-1.png")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    (content, header) = slide_header(slide, "Shared state concurrency", True)
    box = header.box(width=160, y=80)
    box.image("imgs/meme-face-2.jpg")
    box.overlay(show="4-5").image("imgs/meme-face-3.png")
    box.overlay(show="6+").image("imgs/meme-face-4.png")

    code_step(content.box(width=800, height=350), """
let p = Rc::new(5);
thread::spawn(|| {
    println!("{}", *p);
});
""", 1, [(0, None, None, None),
         (0, 1, None, None),
         (0, 1, 2, 3),
         (0, 1, 2, 3),
         (0, "thread::spawn(move || {", 2, 3)], width=500)

    border_box = content.box(width=1000, height=220)
    box = with_border(border_box.overlay(), show="4").box(width=800, height=180)
    box.box(show="4", height=220).image("imgs/concurrent-error-2.png")
    box = with_border(border_box.overlay(), show="6+").box(width=800, height=180)
    box.box(show="6+", width=900).image("imgs/concurrent-error-3.png")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    (content, header) = slide_header(slide, "Shared state concurrency", True)
    box = header.box(width=160, y=80)
    box.overlay(show="1-2").image("imgs/meme-face-6.jpg")
    box.overlay(show="3+").image("imgs/meme-face-5.jpg")

    content.box(height=60)
    code_step(content.box(width=800, height=260), """
let p = Arc::new(5);
thread::spawn(move || {
    println!("{}", *p);
});
println!("{}", *p);
""", 1, [(0, 1, 2, 3, None),
         (0, 1, 2, 3, 4),
         ], width=500)
    with_border(content, show="3+").box(width=1000).image(
        "imgs/concurrent-error-4.png")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    (content, header) = slide_header(slide, "Shared state concurrency", True)
    box = header.box(width=160, y=80, show="3+")
    box.image("imgs/meme-face-7.png")

    code_width = 800
    code(content.box(show="2+"), "fn clone(&self) -> Arc<T>;", width=code_width)

    content.box(height=20)
    code(content.box(), """
let p = Arc::new(5);
let tp = p.clone();
thread::spawn(move || {
    println!("{}", *tp);
});
println!("{}", *p);
""", width=code_width)

    content.box(height=10)
    content.box(show="2+").text("""Clone() creates a new Arc.
Multiple variables remove aliasing.""")
    content.box(show="3+").text("Arc only provides ~emph{read-only} access (shared borrow).")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    slide.set_style("code2", slide.get_style("code").compose(s(size=32)))
    content = slide_header(slide, "Shared state concurrency")

    code_width = 800
    code(content.box(show="4+"), """
// Mutex::lock
fn lock(&self) -> &mut T;""", code_style="code2", width=code_width)

    content.box(height=20)
    code_step(content.box(width=code_width, height=320), """
let p = Arc::new(Mutex::new(5));
let tp = p.clone();
thread::spawn(move || {
    *tp.lock() = 10;
});
println!("{}", *p.lock());""", "1", (
        ("                 Mutex::new(5)  ", None, None, None, None, None),
        (0, None, None, None, None, None),
        (0, 1, 2, 3, 4, 5)
    ), width=code_width)
Exemplo n.º 25
0
def lifetimes(slides: Slides):
    def cpp_lifetime(comment=""):
        slide = slides.new_slide()
        slide.update_style("code", s(size=38))
        content = slide_header(slide, "Lifetimes (C++)")
        code(content,
             """
int* p;
{{
    int value = 5;
    p = &value;
}}{comment}
std::cout << *p << std::endl;
""".format(comment=comment),
             "cpp",
             width=800)

    cpp_lifetime()
    cpp_lifetime(" // <-- `value` is destroyed here")

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Lifetimes (Rust)")
    code_box = code(content.box(),
                    """
let p;
{
    let value = 5;
    p = &value;
}
println!("{}", *p);""",
                    width=800)

    def line(start,
             end,
             start_x,
             end_x,
             right_x,
             offset_x,
             color,
             show,
             y="65%"):
        line_start = code_box.line_box(start, width="fill")
        line_end = code_box.line_box(end, width="fill")
        arrow = Arrow(20)

        start = line_start.p(start_x, y)
        end = line_end.p(end_x, y)

        content.box(show=show).line([
            start,
            line_start.p(right_x, y).add(offset_x, 0),
            line_end.p(right_x, y).add(offset_x, 0), end
        ],
                                    start_arrow=arrow,
                                    end_arrow=arrow,
                                    stroke_width=5,
                                    color=color)

    content.box(height=20)
    content.box(width=500, show="2+").text("Lifetime of reference `p`",
                                           style=s(color="orange",
                                                   align="left"))
    line(0, 5, "40%", "100%", "90%", 200, "orange", "2+")

    content.box(height=10)
    content.box(width=500, show="3+").text("Lifetime of `value`",
                                           style=s(color="green",
                                                   align="left"))
    line(2, 4, "100%", "10%", "100%", 50, "green", "3+")

    content.box(height=30)
    content.box(show="4+").text("""Lifetime of a value must be
>= lifetime of a reference to it""",
                                style=s(size=50))

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Lifetimes (Rust)")
    code_box = code(content.box(),
                    """
let p;
{
    let value = 5;
    p = &value;
}
println!("{}", *p);""",
                    width=800)

    content.box(height=20)
    content.box(height=280).image("imgs/lifetime-error.png")

    slide = slides.new_slide()
    slide.update_style("code", s(size=32))
    content = slide_header(slide, "What if compile time is not enough?")
    content.box().text("""If you can't prove to the compiler that the lifetimes
are correct, lifetime can be managed at runtime.""")

    code_width = 1000
    content.box(height=20)
    code_step(content.box(width=code_width, height=400),
              """
fn main() {
    let value = Rc::new(5); // refcount == 1
    {
        let a = value.clone(); // refcount == 2
    } // refcount == 1
} // refcount == 0, value is dropped
""",
              "2", ((0, 1, None, None, None, None), (0, 1, 2, 3, None, None),
                    (0, 1, 2, 3, 4, None), (0, 1, 2, 3, 4, 5)),
              width=code_width)
Exemplo n.º 26
0
def borrowing(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Where's the aliasing?")
    content.box().text("So far, we only have mutability, there's no aliasing:")

    content.box(height=20)
    list = content.box()
    list_item(list, show="next+").text(
        "After a move, the original value is not accessible")
    list_item(list, show="next+").text("After a copy, a new value is created")

    slide = slides.new_slide()
    content = slide_header(slide, "Borrowing")
    content.box().text(
        "Aliasing happens when you create a reference to a value")
    content.box(show="next+").text("This is called borrowing in Rust")

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Shared borrows")

    code_width = 800

    code(content,
         """
let value = Bitmap::load(...);
let a = &value;
let b = &value;
""",
         width=code_width)

    content.box(height=20)
    list = content.box()
    list_item(
        list,
        show="next+").text("Multiple shared borrows of a value may exist")

    list.box(height=10)
    list_item(list,
              show="next+").text("You can't mutate using a shared borrow")
    list.box(height=10)
    code(list.box(show="last+"),
         "a.width = 10; // does not compile",
         width=code_width)

    list.box(height=10)
    list_item(list, show="next+").text("You can't move out of a shared borrow")
    list.box(height=10)
    code(list.box(show="last+"),
         """
fn foo(bitmap: Bitmap) { }
foo(a); // does not compile""",
         width=code_width)

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Unique borrows")

    code_width = 800

    code(content,
         """
let value = Bitmap::load(...);
let c = &mut value;
""",
         width=code_width)

    content.box(height=20)
    list = content.box()
    list_item(list, show="next+").text(
        """If a unique borrow exists, there are no other references
to the same value""",
        style=s(align="left"))
    list_item(list, show="next+").text(
        "You can only create a unique borrow if you own the value")

    list.box(height=10)
    list_item(list, show="next+").text("You can mutate using a unique borrow")
    list.box(height=10)
    code(list.box(show="last+"), "c.width = 10;", width=code_width)

    list.box(height=10)
    list_item(list, show="next+").text("You can't move out of a unique borrow")
    list.box(height=10)
    code(list.box(show="last+"),
         """
fn foo(bitmap: Bitmap) { }
foo(c); // does not compile""",
         width=code_width)

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Vector example (Rust)")

    code_width = 800
    code(content.box(show="3+"),
         """
// Vec::push
fn push(&mut self, value: T)
""",
         width=code_width)
    content.box(height=10)
    code_step(content.box(width=code_width, height=300),
              """
let vec = vec!(1, 2, 3);
let p = &vec[0];
vec.push(4);
println!("{}", p);
""",
              "1", ((0, None, None, None), (0, 1, None, None), (0, 1, 2, None),
                    (0, 1, 2, 3)),
              width=code_width)

    content.box(height=10)
    content.box(height=220, show="next+").image("imgs/borrowck-error.png")

    slide = slides.new_slide()
    slide.update_style("code", s(size=34))
    content = slide_header(slide, "What if compile time is not enough?")
    content.box().text(
        """If you can't prove to the compiler that your borrows are safe,
borrow checking can be done at runtime.""")
    content.box(
        show="next+").text("If any rules are broken, the program panics.")

    content.box(height=20)
    code_box = code(
        content.box(show="next+"), """
let value = RefCell::new(5);
let a = value.borrow();     // shared borrow
let b = value.borrow_mut(); // unique borrow""")
    pointer_to_line(slide,
                    code_box,
                    2,
                    100,
                    600,
                    "4+",
                    textbox_pos=("40%", 0),
                    code_pos=("40%", "100%")).text(
                        """This would panic, since there already is
a shared borrow""",
                        style=s(color="orange", align="left"))
Exemplo n.º 27
0
def ownership(slides: Slides):
    slide = slides.new_slide()
    content = slide_header(slide, "Memory safety using the type system")
    list = content.box()
    list_item(list).text("Ownership")
    list_item(list, show="next+").text("Borrowing")
    list_item(list, show="next+").text("Lifetimes")

    slide = slides.new_slide()
    content = slide_header(slide, "Ownership")
    content.box().text("Every value in Rust has exactly one owner", s(size=50))
    content.box(height=10)
    content.box(show="next+").text(
        "When that owner goes out of scope, the value is dropped",
        style=s(size=36))

    def person_slide(end=""):
        slide = slides.new_slide()
        slide.update_style("code", s(size=50))
        content = slide_header(slide, "Ownership")
        return (slide,
                code(content,
                     """
fn foo(bitmap: Bitmap) {{
    ...
}}{}""".format(end),
                     width=840))

    (slide, box) = person_slide()
    pointer_to_line(slide,
                    box,
                    0,
                    100,
                    150,
                    "2+",
                    textbox_pos=("50%", "100%"),
                    code_pos=("40%", "10%")).text(
                        """No one else has any access to `bitmap`.
It can be mutated arbitrarily.""",
                        style=s(color="orange", size=40))

    person_slide(" // bitmap is dropped here")

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Ownership - move semantics")
    code_box = code(
        content.box(), """
fn foo(bitmap: Bitmap) { ... }

fn main() {
    let bitmap = Bitmap::load(...);
    foo(bitmap);
    ...
}
""")
    pointer_to_line(slide,
                    code_box,
                    4,
                    200,
                    120,
                    "2+",
                    textbox_pos=("40%", "100%"),
                    code_pos=("46%", "60%")).text("""`bitmap` is moved here.
It will not be `dropped` in the current scope.
""",
                                                  style=s(color="orange",
                                                          align="left"))

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Ownership - move semantics")
    code(
        content.box(), """
fn foo(bitmap: Bitmap) { ... }

fn main() {
    let bitmap = Bitmap::load(...);
    foo(bitmap);
    println!("{}", bitmap.width);
}
""")
    content.box(height=20)
    content.box(height=180, show="2+").image("imgs/ownership-moved.png")

    slide = slides.new_slide()
    content = slide_header(slide, "Constructors")
    list = content.box()
    list_item(list).text("Move constructors? Nope.")
    list_item(list, show="next+").text("Move assignment constructors? Nope.")

    slide = slides.new_slide()
    content = slide_header(slide, "Why are they needed in C++?")
    content.box(height=600).image("imgs/meme-lvalue.jpg")

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, "Why are they needed in C++?")
    box = code(
        content, """
void foo(Bitmap&& bitmap) { ... }

Bitmap bitmap(...);
foo(std::move(bitmap));
std::cout << bitmap.width << std::endl;""", "cpp")
    pointer_to_line(slide,
                    box,
                    4,
                    100,
                    600,
                    "2+",
                    textbox_pos=("40%", "0"),
                    code_pos=("40%", "100%")).text(
                        """`bitmap` is still accessible here.
It will be `dropped` at the end of scope.
Its state HAD to be reset in the move constructor.""",
                        style=s(color="orange", align="left"))

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, '"Copy" semantics')
    content.box().text("""Values are copied instead of moved
if they implement the `Copy` trait""",
                       style=s(bold=True))

    content.box(height=20)
    content.box(show="next+").text("Types are `Copy` if:")
    list = content.box()
    list_item(list,
              show="next+").text("they are primitive (integers, floats, etc.)")
    list_item(list, show="next+").text("they are marked as Copy")

    content.box(height=20)
    code(content.box(show="next+"),
         """
#[derive(Copy)]
struct Person {
    age: u32,
    male: bool
}""",
         width=500)

    slide = slides.new_slide()
    slide.update_style("code", s(size=38))
    content = slide_header(slide, '"Copy" semantics')
    box = code(
        content.box(), """
fn foo(num: u32) { ... }

let number = 5;
foo(number);
println!("{}", number); // no error""")

    pointer_to_line(slide,
                    box,
                    3,
                    200,
                    600,
                    "2+",
                    textbox_pos=("40%", "0"),
                    code_pos=("34%", "60%")).text("""`number` is copied here.
    It can be still accessed after the call.""",
                                                  style=s(color="orange"))
Exemplo n.º 28
0
from elsie import Slides, Arrow

# Let us our primary colors used in slides
COLOR1 = "#328cc1"
COLOR2 = "#d9b310"

# Top-level slide instances
slides = Slides()

# Modyfy global text styles
slides.update_style("default", color=COLOR1)  # Default font
slides.update_style("emph", color=COLOR2)  # Emphasis

# First slide #############################################

# Create a new slide, it actually returns instance of Box.
# We are going to create a lots of boxes
slide = slides.new_slide()

# Create text styles that are local for this slide
# Actually, any Box can have own styles that are inherited
# to any sub-boxes.
slide.new_style("header", size=35, color="white")
slide.new_style("header2", size=25, color=COLOR1)

# Create a box that fill the whole slide horizontaly
title_box1 = slide.box(width="fill", height=120)
title_box1.rect(bg_color=COLOR2)  # Draw a filled rectangle

# Create a sub-box in title_box1.
# "fbox" is shortcut for box(width="fill", height="fill")
Exemplo n.º 29
0
from elsie import Slides, TextStyle as s

from part1 import features
from part2 import performance
from part3 import memory_safety
from part4 import fearless_concurrency
from utils import slide_header

COLOR1 = "black"
COLOR2 = "#f74f00"

slides = Slides()

slides.update_style("default", s(font="Raleway-v4020", size=36, color=COLOR1))  # Default font
slides.update_style("emph", s(color=COLOR2))     # Emphasis
slides.set_style("code2", slides.get_style("code").compose(s(size=40, align="left")))


def intro(slides: Slides):
    slide = slides.new_slide()
    slide.set_style("title", s(size=60, bold=True))
    slide.set_style("name", s(size=30))

    slide.sbox(height="30%").image("imgs/logo.svg")
    slide.box(height=80)
    slide.box().text("Rust: Fast & Safe", "title")
    slide.box(height=20)
    slide.box().text("Jakub Beránek, Mathieu Fehr, Saurabh Raje", "name")

    slide = slides.new_slide()
    slide.box(width=500).image("imgs/meme-rust-meeting.jpg")
Exemplo n.º 30
0
def outro(slides: Slides):
    slide = slides.new_slide()
    slide.box().text("Thanks, our curse has finally been lifted", s(size=50))
    slide.box(height=20)
    slide.box(show="next+").text("Now YOU have to go and spread the word about Rust",
                                 s(size=40))