diff --git a/src/development/design/actor.md b/src/development/design/actor.md index eda0f6a..2494795 100644 --- a/src/development/design/actor.md +++ b/src/development/design/actor.md @@ -14,7 +14,7 @@ It reduces work of implementation, and all implementations can use the functions ```rust // Different possible types of actors (more to be added) enum ActorType { - GUI(Widget), + GUI(photon::Widget), ProgramInterface, } @@ -62,19 +62,24 @@ impl Actor { } impl KeyPair { - fn generate_keypair(&mut self) -> Self; - fn get_pubkey(&self) -> u128; - fn sign(&self, &[u8]) -> Result<&[u8], Error>; - fn verify_signature(&[u8], u128) -> Result<(), Error>; + async fn generate_keypair(&mut self) -> Self; // Generate a public/private keypair (threaded) + fn get_pubkey(&self) -> u128; // Return the keypair of an Actor + async fn sign(&self, &[u8]) -> Result<&[u8], Error>; // Sign some data with a private key (threaded) + async fn verify_signature(&[u8], u128) -> Result<(), Error>; // Verify signed data (threaded) } trait FilesystemInterface { // Interfacing with the filesystem - fn read(&mut self) -> Result<(), Error>; // Read the data from the disk into the Actor using the Uuid as a search key - fn write(&self) -> Result<(), Error>; // Write the data to the disk using the Uuid as a key + async fn read(&mut self) -> Result<(), Error>; // Read the data from the disk into the Actor using the Uuid as a search key + async fn write(&self) -> Result<(), Error>; // Write the data to the disk using the Uuid as a key } trait DataInterface { // Necessary data functions - fn to_bytes(&self) -> Result<&[u8], Error>; // Convert the data into a byte array + async fn to_bytes(&self) -> Result<&[u8], Error>; // Convert the data into a byte array +} + +trait MessageInterface { // Sending & receiving messages + async fn send_message(&self, MessageType, Uuid) -> Result<(), Error>; // Send a message to a recipient + async fn receive_message(&self, Channel) -> Message; // Asynchronously wait for an incoming message, and deal with the first one we get } ``` @@ -85,7 +90,20 @@ trait DataInterface { // Necessary data functions - [postcard](https://lib.rs/crates/postcard) for message passing - Priority Queue for processing multiple messages, while dealing with higher-priority ones first +Messages will be fully modelled so an actor can know *exactly* what they have to deal with, and what they can send. +Different channels are used to make each one less clogged up, and used only for a specific purpose. +Actors can read from/write to a specific channel, allowing them to ignore the others. +They can then also deal with channels in different ways, maybe deprioritizing the `Test` channel. + ```rust +enum Channel { // Channels for sending/receiving messages on + Graphics, // Low-latency graphics updates + Test, // Designated channel for testing messages + Filesystem, // Batch filesystem operations + Print, // Printing text + Executable, // Executable-related messages +} + enum ProcessCode { Exit, // Exit the process Save, // Save data @@ -102,6 +120,7 @@ enum MessageType { } struct Message { + id: Uuid, // UUID of the message itself m_type: MessageType, // Message type & content priority: u8, // For priority queueing sender: Uuid, // Who is sending the message @@ -109,4 +128,15 @@ struct Message { } ``` +An example message handling loop may look like this: +```rust +loop { // Continuously loop through message sending & receiving + actor.send_message(MessageType::Ping("hello!".to_string())).await; // Block and await until we can send the test message. + match actor.receive_message(&self, Channel::Test).await.m_type { // Match on a message type + Ping(s) => println!("We got pinged! {}", s), // Print if we got pinged + _ => {}, // Ignore other states + } +} +``` + ### Latency