speice.io/assets/js/71d18034.0eabaf41.js

1 line
18 KiB
JavaScript
Raw Permalink Normal View History

"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4558"],{10:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return i},default:function(){return p},frontMatter:function(){return o},metadata:function(){return a},toc:function(){return c}});var a=n(9098),r=n(5893),s=n(65);let o={slug:"2018/01/captains-cookbook-part-2",title:"Captain's Cookbook: Practical usage",date:new Date("2018-01-16T13:00:00.000Z"),authors:["bspeice"],tags:[]},i=void 0,d={authorsImageUrls:[void 0]},c=[{value:"Attempt 1: Move the reference",id:"attempt-1-move-the-reference",level:2},{value:"Attempt 2: Put the <code>Reader</code> in a <code>Box</code>",id:"attempt-2-put-the-reader-in-a-box",level:2},{value:"Attempt 3: The <code>TypedReader</code>",id:"attempt-3-the-typedreader",level:2}];function h(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:"A look at more practical usages of Cap'N Proto"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"/2018/01/captains-cookbook-part-1",children:"Part 1"})," of this series took a look at a basic starting project\nwith Cap'N Proto. In this section, we're going to take the (admittedly basic) schema and look at how we can add a pretty\nbasic feature - sending Cap'N Proto messages between threads. It's nothing complex, but I want to make sure that there's\nsome documentation surrounding practical usage of the library."]}),"\n",(0,r.jsxs)(t.p,{children:["As a quick refresher, we build a Cap'N Proto message and go through the serialization/deserialization steps\n",(0,r.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs",children:"here"}),". Our current example is going to build on\nthe code we wrote there; after the deserialization step, we'll try and send the ",(0,r.jsx)(t.code,{children:"point_reader"})," to a separate thread\nfor verification."]}),"\n",(0,r.jsxs)(t.p,{children:["I'm going to walk through the attempts as I made them and my thinking throughout.\nIf you want to skip to the final project, check out the code available ",(0,r.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_2",children:"here"})]}),"\n",(0,r.jsx)(t.h2,{id:"attempt-1-move-the-reference",children:"Attempt 1: Move the reference"}),"\n",(0,r.jsx)(t.p,{children:"As a first attempt, we're going to try and let Rust move the reference. Our code will look something like:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-rust",children:"fn main() {\n\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from\n // somewhere else\n\n let deserialized = capnp::serialize::read_message(\n &mut buffer.as_slice(),\n capnp::message::ReaderOptions::new()\n ).unwrap();\n\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\n\n // By using `point_reader` inside the new thread, we're hoping that Rust can\n // safely move the reference and invalidate the original thread's usage.\n // Since the original thread doesn't use `point_reader` again, this should\n // be safe, right?\n let handle = std::thread:spawn(move || {\n\n assert_eq!(point_reader.get_x(), 12);\n\n assert_eq!(point_reader.get_y(), 14);\n });\n\n handle.join().unwrap()\n}\n"})}),"\n",(0,r.jsx)(t.p,{children:"Well, the Rust compiler doesn't really like this. We get four distinct errors back:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` \n --\x3e src/main.rs:31:18 \n | \n31 | let handle = std::thread::spawn(mo