Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Location set tweaks #16

Merged
merged 14 commits into from
Oct 2, 2023
16 changes: 7 additions & 9 deletions chorus_book/src/guide-projector.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ To create a `Projector`, you need to provide the target location and the transpo

```rust
# extern crate chorus_lib;
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
# use chorus_lib::core::{ChoreographyLocation, Projector};
# use chorus_lib::{LocationSet};
# let transport_channel = LocalTransportChannel::new().with(Alice).with(Bob);
# let alice_transport = LocalTransport::new(Alice, transport_channel.clone());
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};
# use chorus_lib::core::{ChoreographyLocation, Projector, LocationSet};
# #[derive(ChoreographyLocation)]
# struct Alice;
# #[derive(ChoreographyLocation)]
# struct Bob;
# let transport_channel = LocalTransportChannelBuilder::new().with(Alice).with(Bob).build();
# let alice_transport = LocalTransport::new(Alice, transport_channel.clone());
let projector = Projector::new(Alice, alice_transport);
```

Expand All @@ -28,10 +27,9 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro

```rust
# extern crate chorus_lib;
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp};
# use chorus_lib::{LocationSet};
# let transport_channel = LocalTransportChannel::new().with(Alice).with(Bob);
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};
# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp, LocationSet};
# let transport_channel = LocalTransportChannelBuilder::new().with(Alice).with(Bob).build();
# let alice_transport = LocalTransport::new(Alice, transport_channel.clone());
# #[derive(ChoreographyLocation)]
# struct Alice;
Expand Down
72 changes: 39 additions & 33 deletions chorus_book/src/guide-transport.md
ihaveint marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,48 @@ ChoRus provides two built-in transports: `local` and `http`.

### The Local Transport

The `local` transport is used to execute choreographies on the same machine on different threads. This is useful for testing and prototyping. Each `local` transport is defined over `LocalTransportChannel`, which contains the set of `ChoreographyLocation` that the `local` transport operates on. You can build a `LocalTransportChannel` by importing the `LocalTransportChannel` struct from the `chorus_lib` crate.
The `local` transport is used to execute choreographies on the same machine on different threads. This is useful for testing and prototyping.

To use the local transport, we first need to create a `LocalTransportChannel`, which works as a channel between threads and allows them to send messages to each other. To do so, we use the `LocalTransportChannelBuilder` struct from the `chorus_lib` crate.

```rust
# extern crate chorus_lib;
# use chorus_lib::core::{ChoreographyLocation};
# use chorus_lib::{LocationSet};
# use chorus_lib::core::{ChoreographyLocation, LocationSet};
# #[derive(ChoreographyLocation)]
# struct Alice;
# #[derive(ChoreographyLocation)]
# struct Bob;
use chorus_lib::transport::local::LocalTransportChannel;
use chorus_lib::transport::local::LocalTransportChannelBuilder;

let transport_channel = LocalTransportChannel::new().with(Alice).with(Bob);
let transport_channel = LocalTransportChannelBuilder::new()
.with(Alice)
.with(Bob)
.build();
```

To use the `local` transport, first import the `LocalTransport` struct from the `chorus_lib` crate.
Then build the transport by using the `LocalTransport::new` associated function, which takes a target location (explained in the [Projector section](./guide-projector.md)) and the `LocalTransportChannel`.
Using the `with` method, we add locations to the channel. When we call `build`, it will create an instance of `LocalTransportChannel`.

Then, create a transport by using the `LocalTransport::new` function, which takes a target location (explained in the [Projector section](./guide-projector.md)) and the `LocalTransportChannel`.

```rust
# extern crate chorus_lib;
# use chorus_lib::core::{ChoreographyLocation};
# use chorus_lib::{LocationSet};
# use chorus_lib::core::{ChoreographyLocation, LocationSet};
# #[derive(ChoreographyLocation)]
# struct Alice;
# use chorus_lib::transport::local::LocalTransportChannel;
# let transport_channel = LocalTransportChannel::new().with(Alice);
# use chorus_lib::transport::local::LocalTransportChannelBuilder;
# let transport_channel = LocalTransportChannelBuilder::new().with(Alice).build();
use chorus_lib::transport::local::{LocalTransport};

let alice_transport = LocalTransport::new(Alice, transport_channel.clone());
```

Because of the nature of the `Local` transport, you must use the same `LocalTransportChannel` instance for all locations. You can `clone` the `LocalTransprotChannel` instance and pass it to each `Projector::new` constructor.
Because of the nature of the `Local` transport, you must use the same `LocalTransportChannel` instance for all locations. You can `clone` the `LocalTransportChannel` instance and pass it to each `Projector::new` constructor.

```rust
# extern crate chorus_lib;
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};
# use std::thread;
# use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, Projector};
# use chorus_lib::{LocationSet};
# use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, Projector, LocationSet};
# #[derive(ChoreographyLocation)]
# struct Alice;
# #[derive(ChoreographyLocation)]
Expand All @@ -58,7 +60,10 @@ Because of the nature of the `Local` transport, you must use the same `LocalTran
# fn run(self, op: &impl ChoreoOp<Self::L>) {
# }
# }
let transport_channel = LocalTransportChannel::new().with(Alice).with(Bob);
let transport_channel = LocalTransportChannelBuilder::new()
.with(Alice)
.with(Bob)
.build();
let mut handles: Vec<thread::JoinHandle<()>> = Vec::new();
{
// create a transport for Alice
Expand All @@ -82,21 +87,23 @@ let mut handles: Vec<thread::JoinHandle<()>> = Vec::new();

The `http` transport is used to execute choreographies on different machines. This is useful for executing choreographies in a distributed system.

To use the `http` transport, import the `HttpTransport` struct and the `HttpTransportConfig` type alias from the `chorus_lib` crate.
To use the `http` transport, import `HttpTransport` and `HttpTransportConfigBuilder` from the `chorus_lib` crate.

```rust
# extern crate chorus_lib;
use chorus_lib::transport::http::{HttpTransport, HttpTransportConfig};
use chorus_lib::transport::http::{HttpTransport, HttpTransportConfigBuilder};
```

The primary constructor requires an argument of type `HttpTransportConfig`. To create an instance of this configuration, start with `HttpTransportConfig::for_target(target_location, (hostname, port))`. It will create set a projection target and the hostname and port to listen on. Then, provide information to connect to other locations by method-chaining the `.with(other_location, (hostname, port))` method. You can think of `HttpTransportConfig` as a mapping from locations to their hostnames and ports.
We need to construct a `HttpTransportConfig` using the `HttpTransportConfigBuilder`. First, we specify the target location and the hostname and port to listen on using the `for_target` method. Then, we specify the other locations and their `(hostname, port)` pairs using the `with` method.

```rust
{{#include ./header.txt}}
# use chorus_lib::transport::http::{HttpTransport, HttpTransportConfig};
let config = HttpTransportConfig::for_target(Alice, ("localhost".to_string(), 8080))
.with(Bob, ("localhost".to_string(), 8081));

# use chorus_lib::transport::http::{HttpTransport, HttpTransportConfigBuilder};
// `Alice` listens on port 8080 on localhost
let config = HttpTransportConfigBuilder::for_target(Alice, ("localhost".to_string(), 8080))
// Connect to `Bob` on port 8081 on localhost
.with(Bob, ("localhost".to_string(), 8081))
.build();
let transport = HttpTransport::new(config);
```

Expand All @@ -108,24 +115,23 @@ You can also create your own transport by implementing the `Transport` trait. It

```rust
{{#include ./header.txt}}
# use chorus_lib::transport::TransportConfig;
let config = TransportConfig::for_target(Alice, ())
# use chorus_lib::transport::TransportConfigBuilder;
let config = TransportConfigBuilder::for_target(Alice, ())
.with(Bob, ("localhost".to_string(), 8081))
.with(Carol, ("localhost".to_string(), 8082));
.with(Carol, ("localhost".to_string(), 8082))
.build();
```

See the API documentation for more details.


### Note on the location set of the Choreography

Note that when calling `epp_and_run` on a `Projector`, you will get a compile error if the location set of the `Choreography` is not a subset of the location set of the `Transport`. In other words, the `Transport` should have information about every `ChoreographyLocation` that `Choreography` can talk about. So this will fail:
Note that when calling `epp_and_run` on a `Projector`, you will get a compile error if the location set of the `Choreography` is not a subset of the location set of the `Transport`. In other words, the `Transport` should have information about every `ChoreographyLocation` that `Choreography` can talk about. So this will fail:

```rust, compile_fail
# extern crate chorus_lib;
ihaveint marked this conversation as resolved.
Show resolved Hide resolved
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp};
# use chorus_lib::{LocationSet};
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};
# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp, LocationSet};

# #[derive(ChoreographyLocation)]
# struct Alice;
Expand All @@ -138,7 +144,7 @@ impl Choreography for HelloWorldChoreography {
}
}

let transport_channel = LocalTransportChannel::<LocationSet!(Alice)>::new();
let transport_channel = LocalTransportChannelBuilder::new().with(Alice).build();
let transport = LocalTransport::new(Alice, transport_channel.clone());
let projector = Projector::new(Alice, transport);
projector.epp_and_run(HelloWorldChoreography);
Expand Down
7 changes: 3 additions & 4 deletions chorus_book/src/header.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# extern crate chorus_lib;
# use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector, Located, Superposition, Runner};
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
# use chorus_lib::{LocationSet};
# use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector, Located, Superposition, Runner, LocationSet};
# use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};
# #[derive(ChoreographyLocation)]
# struct Alice;
# #[derive(ChoreographyLocation)]
# struct Bob;
# #[derive(ChoreographyLocation)]
# struct Carol;
# let transport_channel = LocalTransportChannel::new().with(Alice).with(Bob).with(Carol);
# let transport_channel = LocalTransportChannelBuilder::new().with(Alice).with(Bob).with(Carol).build();
# let alice_transport = LocalTransport::new(Alice, transport_channel.clone());
# let bob_transport = LocalTransport::new(Bob, transport_channel.clone());
# let carol_transport = LocalTransport::new(Carol, transport_channel.clone());
11 changes: 7 additions & 4 deletions chorus_lib/examples/bookseller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ extern crate chorus_lib;
use std::io;
use std::thread;

use chorus_lib::transport::local::LocalTransportChannelBuilder;
use chrono::NaiveDate;

use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector};
use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
use chorus_lib::LocationSet;
use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, LocationSet, Projector};
use chorus_lib::transport::local::LocalTransport;

fn get_book(title: &str) -> Option<(i32, NaiveDate)> {
match title.trim() {
Expand Down Expand Up @@ -73,7 +73,10 @@ impl Choreography for BooksellerChoreography {
}

fn main() {
let transport_channel = LocalTransportChannel::new().with(Seller).with(Buyer);
let transport_channel = LocalTransportChannelBuilder::new()
.with(Seller)
.with(Buyer)
.build();
let transport_seller = LocalTransport::new(Seller, transport_channel.clone());
let transport_buyer = LocalTransport::new(Buyer, transport_channel.clone());

Expand Down
10 changes: 5 additions & 5 deletions chorus_lib/examples/bookseller2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ use std::collections::HashMap;
use std::sync::Arc;
use std::thread;

use chorus_lib::LocationSet;
use chorus_lib::{
core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Projector},
transport::local::{LocalTransport, LocalTransportChannel},
core::{ChoreoOp, Choreography, ChoreographyLocation, Located, LocationSet, Projector},
transport::local::{LocalTransport, LocalTransportChannelBuilder},
};
use chrono::NaiveDate;

Expand Down Expand Up @@ -143,10 +142,11 @@ fn main() {
i
};

let transport_channel = LocalTransportChannel::new()
let transport_channel = LocalTransportChannelBuilder::new()
.with(Seller)
.with(Buyer1)
.with(Buyer2);
.with(Buyer2)
.build();

let seller_projector = Arc::new(Projector::new(
Seller,
Expand Down
16 changes: 9 additions & 7 deletions chorus_lib/examples/hello.rs
ihaveint marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ extern crate chorus_lib;

use std::thread;

use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector};
use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
use chorus_lib::LocationSet;
use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, LocationSet, Projector};
use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};

// --- Define two locations (Alice and Bob) ---

Expand All @@ -19,6 +18,9 @@ struct HelloWorldChoreography;

// Implement the `Choreography` trait for `HelloWorldChoreography`
impl Choreography for HelloWorldChoreography {
// Define the set of locations involved in the choreography.
// In this case, the set consists of `Alice` and `Bob` and
// the choreography can use theses locations.
type L = LocationSet!(Alice, Bob);
fn run(self, op: &impl ChoreoOp<Self::L>) {
// Create a located value at Alice
Expand All @@ -40,19 +42,19 @@ impl Choreography for HelloWorldChoreography {
fn main() {
let mut handles: Vec<thread::JoinHandle<()>> = Vec::new();
// Create a transport channel
// let transport_channel = LocalTransportChannel::<LocationSet!(Bob, Alice)>::new();
let transport_channel = LocalTransportChannel::new().with(Alice).with(Bob);
let transport_channel = LocalTransportChannelBuilder::new()
.with(Alice)
.with(Bob)
.build();
// Run the choreography in two threads
{
// let transport_channel = transport_channel.clone();
let transport = LocalTransport::new(Alice, transport_channel.clone());
handles.push(thread::spawn(move || {
let p = Projector::new(Alice, transport);
p.epp_and_run(HelloWorldChoreography);
}));
}
{
// let transport_channel = transport_channel.clone();
let transport = LocalTransport::new(Bob, transport_channel.clone());
handles.push(thread::spawn(move || {
let p = Projector::new(Bob, transport);
Expand Down
5 changes: 1 addition & 4 deletions chorus_lib/examples/input-output.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
extern crate chorus_lib;
use chorus_lib::{
core::{ChoreoOp, Choreography, ChoreographyLocation, Located},
LocationSet,
};
use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Located, LocationSet};
#[derive(ChoreographyLocation)]
struct Alice;
#[derive(ChoreographyLocation)]
Expand Down
10 changes: 5 additions & 5 deletions chorus_lib/examples/loc-poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ use std::fmt::Debug;
use std::thread;

use chorus_lib::core::{
ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, Projector,
ChoreoOp, Choreography, ChoreographyLocation, Located, LocationSet, Portable, Projector,
};
use chorus_lib::transport::local::{LocalTransport, LocalTransportChannel};
use chorus_lib::LocationSet;
use chorus_lib::transport::local::{LocalTransport, LocalTransportChannelBuilder};

#[derive(ChoreographyLocation)]
struct Alice;
Expand Down Expand Up @@ -57,10 +56,11 @@ impl Choreography<Located<i32, Alice>> for MainChoreography {
}

fn main() {
let transport_channel = LocalTransportChannel::new()
let transport_channel = LocalTransportChannelBuilder::new()
.with(Alice)
.with(Bob)
.with(Carol);
.with(Carol)
.build();

let mut handles = vec![];
{
Expand Down
5 changes: 2 additions & 3 deletions chorus_lib/examples/runner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
extern crate chorus_lib;
use chorus_lib::{
core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Runner, Superposition},
LocationSet,
use chorus_lib::core::{
ChoreoOp, Choreography, ChoreographyLocation, Located, LocationSet, Runner, Superposition,
};

#[derive(ChoreographyLocation)]
Expand Down
Loading
Loading