Skip to content

Commit

Permalink
Merge pull request #16 from lsd-ucsc/available-locations-tweaks
Browse files Browse the repository at this point in the history
Location set tweaks
  • Loading branch information
shumbo authored Oct 2, 2023
2 parents 6509a2c + 4663697 commit e499079
Show file tree
Hide file tree
Showing 14 changed files with 323 additions and 149 deletions.
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
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;
# 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
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

0 comments on commit e499079

Please sign in to comment.