From b2e1c05d6d5b3ceb22074e5fc9e45eee0c498481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Vis=C3=A9e?= Date: Fri, 29 Dec 2017 16:47:44 +0100 Subject: [PATCH] Implement some multithreading logic --- Cargo.toml | 1 + src/main.rs | 182 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 161 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9a864ce..eb9a07d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" authors = ["Tim Visée "] [dependencies] +bufstream = "*" diff --git a/src/main.rs b/src/main.rs index 32b6b6f..ada4111 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,58 +1,147 @@ -extern crate rand; - -use rand::distributions::{IndependentSample, Range}; +extern crate bufstream; use std::io::Error; use std::io::prelude::*; use std::net::TcpStream; +use std::thread; +use std::thread::JoinHandle; + +use bufstream::BufStream; + + // The target host const HOST: &'static str = "127.0.0.1:8080"; +// The default size of the command output read buffer +const CMD_READ_BUFFER_SIZE: usize = 32; + + + fn main() { // Start println!("Starting..."); - let range = Range::new(1, 1000); - let mut rng = rand::thread_rng(); + // let range = Range::new(1, 1000); + // let mut rng = rand::thread_rng(); - // Create the control stream - let mut stream = create_stream() - .expect("failed to open control stream"); + // Create a new pixelflut canvas + let canvas = PixCanvas::new(HOST, (1000, 1000), 10); - // Create a client - let mut client = PixClient::new(stream); - - // Write a pixel - loop { - client.write_pixel( - range.ind_sample(&mut rng), - range.ind_sample(&mut rng), - &Color::from(255, 0, 0) - ); - } + loop {} } /// Create a stream to talk to the pixelflut server. /// /// The stream is returned as result. +// TODO: Specify a host here! fn create_stream() -> Result { TcpStream::connect(HOST) } +/// A pixflut instance +struct PixCanvas { + host: &'static str, + size: (u16, u16), + painters: Vec>, +} + +impl PixCanvas { + /// Create a new pixelflut canvas. + pub fn new(host: &'static str, size: (u16, u16), painter_count: usize) -> PixCanvas { + // Initialize the object + let mut canvas = PixCanvas { + host, + size, + painters: Vec::with_capacity(painter_count), + }; + + // Spawn some painters + canvas.spawn_painters(); + + // Return the canvas + canvas + } + + /// Spawn the painters for this canvas + fn spawn_painters(&mut self) { + // Spawn some painters + for i in 0..10 { + self.spawn_painter(Rect::from(i * 100, 0, 100, 1000)); + } + } + + /// Spawn a single painter in a thread. + fn spawn_painter(&mut self, area: Rect) { + let thread = thread::spawn(move || { + // Create a new stream + let stream = create_stream() + .expect("failed to open stream to pixelflut"); + + // Create a new client + let client = PixClient::new(stream); + + // Create a painter + let mut painter = Painter::new(client, area); + + // Do some work + loop { + painter.work(); + } + }); + + // Add the painter thread to the list + self.painters.push(thread); + } +} + + + +struct Painter { + client: PixClient, + area: Rect, +} + +impl Painter { + /// Create a new painter. + pub fn new(client: PixClient, area: Rect) -> Painter { + Painter { + client, + area, + } + } + + /// Perform work. + /// Paint the whole defined area. + pub fn work(&mut self) { + // Define the color to draw with + let color = Color::from(0, 155, 0); + + // Loop through all the pixels, and set their color + for x in self.area.x..self.area.x + self.area.w { + for y in self.area.y..self.area.y + self.area.h { + self.client.write_pixel(x, y, &color); + } + } + } +} + + /// A pixelflut client. +/// This client uses a stream to talk to a pixelflut panel. +/// It allows to write pixels to the panel, and read some status. struct PixClient { - stream: TcpStream, + stream: BufStream, } impl PixClient { /// Create a new client instance. pub fn new(stream: TcpStream) -> PixClient { PixClient { - stream, + stream: BufStream::new(stream), } } @@ -64,11 +153,37 @@ impl PixClient { ) } + // /// Read the size of the screen. + // fn read_screen_size(&mut self) { + // // Read the screen size + // let size = self + // .write_read_command("SIZE".into()) + // .expect("Failed to read screen size"); + + // // TODO: Remove this after debugging + // println!("Read size: {}", size); + // } + /// Write the given command to the given stream. fn write_command(&mut self, cmd: String) { self.stream.write(cmd.as_bytes()); self.stream.write("\n".as_bytes()); } + + // /// Write the given command to the given stream, and read the output. + // fn write_read_command(&mut self, cmd: String) -> Result { + // // Write the command + // self.write_command(cmd); + + // // Read the output + // let mut buffer = String::with_capacity(CMD_READ_BUFFER_SIZE); + // println!("Reading line..."); + // self.stream.read_line(&mut buffer)?; + // println!("Done reading"); + + // // Return the read string + // Ok(buffer) + // } } @@ -91,8 +206,31 @@ impl Color { } } - /// Convert the color to a hexadecimal representation. + /// Get a hexadecimal representation of the color, + /// such as `FFFFFF` for white and `FF0000` for red. pub fn as_hex(&self) -> String { format!("{:02X}{:02X}{:02X}", self.r, self.g, self.b) } } + + + +/// Rectangle struct. +pub struct Rect { + // TODO: Make these properties private + pub x: u16, + pub y: u16, + pub w: u16, + pub h: u16, +} + +impl Rect { + pub fn from(x: u16, y: u16, w: u16, h: u16) -> Rect { + Rect { + x, + y, + w, + h, + } + } +}