#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(fnbox)]
#![feature(try_from)]
#[macro_use] extern crate unwrap;
extern crate colored;
extern crate rand;
extern crate simplelog;
extern crate macro_machines;
#[macro_use] extern crate apis;
pub const LOG_LEVEL
: simplelog::LevelFilter = simplelog::LevelFilter::Info;
static THING_DROPPED
: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
#[derive(Debug,Default)]
pub struct Dropthing;
impl Drop for Dropthing {
fn drop (&mut self) {
println!("dropping...");
let already_dropped
= THING_DROPPED.swap (true, std::sync::atomic::Ordering::SeqCst);
assert!(!already_dropped);
}
}
def_program! {
program Myprogram where
let result = session.run()
{
MODES [
mode chargen_upcase::ChargenUpcase {
println!("result: {:?}", result);
Some (EventId::ToRandSource)
}
mode rand_source::RandSource
]
TRANSITIONS [
transition ToRandSource
<chargen_upcase::ChargenUpcase> => <rand_source::RandSource> [
Upcase (upcase) => RandGen (randgen) {
randgen.dropthing = upcase.dropthing.take();
}
]
]
initial_mode: ChargenUpcase
}
}
pub mod chargen_upcase {
use ::apis;
def_session! {
context ChargenUpcase {
PROCESSES where
let process = self,
let message_in = message_in
[
process Chargen (update_count : u64) {
kind {
apis::process::Kind::Isochronous { tick_ms: 20, ticks_per_update: 1 }
}
sourcepoints [Charstream]
endpoints []
handle_message { unreachable!() }
update {
let mut result = apis::process::ControlFlow::Continue;
if process.update_count % 5 == 0 {
result = process.send (
ChannelId::Charstream, Charstreammessage::Achar ('z')
).into();
}
if process.update_count % 7 == 0 {
result = process.send (
ChannelId::Charstream, Charstreammessage::Achar ('y')
).into();
}
if process.update_count % 9 == 0 {
result = process.send (
ChannelId::Charstream, Charstreammessage::Achar ('x')
).into();
}
process.update_count += 1;
const MAX_UPDATES : u64 = 5;
assert!(process.update_count <= MAX_UPDATES);
if result == apis::process::ControlFlow::Continue
&& process.update_count == MAX_UPDATES
{
let _
= process.send (ChannelId::Charstream, Charstreammessage::Quit);
result = apis::process::ControlFlow::Break;
}
result
}
}
process Upcase (
history : String,
dropthing : Option <::Dropthing> = Some (Default::default())
) {
kind { apis::process::Kind::asynchronous_default() }
sourcepoints []
endpoints [Charstream]
handle_message {
match message_in {
GlobalMessage::Charstreammessage (charstreammessage) => {
match charstreammessage {
Charstreammessage::Quit => {
apis::process::ControlFlow::Break
}
Charstreammessage::Achar (ch) => {
process.history.push (ch.to_uppercase().next().unwrap());
apis::process::ControlFlow::Continue
}
}
}
}
}
update {
if *process.inner.state().id() == apis::process::inner::StateId::Ended {
println!("upcase history final: {}", process.history);
} else {
println!("upcase history: {}", process.history);
}
apis::process::ControlFlow::Continue
}
}
]
CHANNELS [
channel Charstream <Charstreammessage> (Simplex) {
producers [Chargen]
consumers [Upcase]
}
]
MESSAGES [
message Charstreammessage {
Achar (char),
Quit
}
]
}
}
}
pub mod rand_source {
use rand;
use apis;
def_session!{
context RandSource {
PROCESSES where
let process = self,
let message_in = message_in
[
process RandGen (
update_count : u64,
dropthing : Option <::Dropthing> = None
) {
kind {
apis::process::Kind::Isochronous { tick_ms: 20, ticks_per_update: 1 }
}
sourcepoints [Randints]
endpoints []
handle_message { unreachable!() }
update {
use rand::Rng;
use apis::FromPrimitive;
let mut rng = rand::thread_rng();
let rand_id = ProcessId::from_u64 (rng.gen_range::<u64> (1, 5))
.unwrap();
let rand_int = rng.gen_range::<u64> (1,100);
let mut result = process.send_to (
ChannelId::Randints, rand_id, Randintsmessage::Anint (rand_int)
).into();
process.update_count += 1;
const MAX_UPDATES : u64 = 5;
if result == apis::process::ControlFlow::Break
|| MAX_UPDATES < process.update_count
{
let _ = process.send_to (
ChannelId::Randints, ProcessId::Sum1, Randintsmessage::Quit);
let _ = process.send_to (
ChannelId::Randints, ProcessId::Sum2, Randintsmessage::Quit);
let _ = process.send_to (
ChannelId::Randints, ProcessId::Sum3, Randintsmessage::Quit);
let _ = process.send_to (
ChannelId::Randints, ProcessId::Sum4, Randintsmessage::Quit);
result = apis::process::ControlFlow::Break
}
result
}
}
process Sum1 (sum : u64) {
kind { apis::process::Kind::asynchronous_default() }
sourcepoints []
endpoints [Randints]
handle_message {
match message_in {
GlobalMessage::Randintsmessage (Randintsmessage::Anint (anint)) => {
process.sum += anint;
apis::process::ControlFlow::Continue
}
GlobalMessage::Randintsmessage (Randintsmessage::Quit) => {
apis::process::ControlFlow::Break
}
}
}
update {
if *process.inner.state().id() == apis::process::inner::StateId::Ended {
println!("sum 1 final: {}", process.sum);
} else {
println!("sum 1: {}", process.sum);
}
apis::process::ControlFlow::Continue
}
}
process Sum2 (sum : u64) {
kind { apis::process::Kind::asynchronous_default() }
sourcepoints []
endpoints [Randints]
handle_message {
match message_in {
GlobalMessage::Randintsmessage (Randintsmessage::Anint (anint)) => {
process.sum += anint;
apis::process::ControlFlow::Continue
}
GlobalMessage::Randintsmessage (Randintsmessage::Quit) => {
apis::process::ControlFlow::Break
}
}
}
update {
if *process.inner.state().id() == apis::process::inner::StateId::Ended {
println!("sum 2 final: {}", process.sum);
} else {
println!("sum 2: {}", process.sum);
}
apis::process::ControlFlow::Continue
}
}
process Sum3 (sum : u64) {
kind { apis::process::Kind::asynchronous_default() }
sourcepoints []
endpoints [Randints]
handle_message {
match message_in {
GlobalMessage::Randintsmessage (Randintsmessage::Anint (anint)) => {
process.sum += anint;
apis::process::ControlFlow::Continue
}
GlobalMessage::Randintsmessage (Randintsmessage::Quit) => {
apis::process::ControlFlow::Break
}
}
}
update {
if *process.inner.state().id() == apis::process::inner::StateId::Ended {
println!("sum 3 final: {}", process.sum);
} else {
println!("sum 3: {}", process.sum);
}
apis::process::ControlFlow::Continue
}
}
process Sum4 (sum : u64) {
kind { apis::process::Kind::asynchronous_default() }
sourcepoints []
endpoints [Randints]
handle_message {
match message_in {
GlobalMessage::Randintsmessage (Randintsmessage::Anint (anint)) => {
process.sum += anint;
apis::process::ControlFlow::Continue
}
GlobalMessage::Randintsmessage (Randintsmessage::Quit) => {
apis::process::ControlFlow::Break
}
}
}
update {
if *process.inner.state().id() == apis::process::inner::StateId::Ended {
println!("sum 4 final: {}", process.sum);
} else {
println!("sum 4: {}", process.sum);
}
apis::process::ControlFlow::Continue
}
}
]
CHANNELS [
channel Randints <Randintsmessage> (Source) {
producers [RandGen]
consumers [Sum1, Sum2, Sum3, Sum4]
}
]
MESSAGES [
message Randintsmessage {
Anint (u64),
Quit
}
]
}
} }
fn main() {
use colored::Colorize;
let example_name = std::path::PathBuf::from (std::env::args().next().unwrap())
.file_name().unwrap().to_str().unwrap().to_string();
println!("{}", format!("{} main...", example_name).green().bold());
unwrap!(simplelog::TermLogger::init (LOG_LEVEL, simplelog::Config::default()));
use std::io::Write;
use macro_machines::MachineDotfile;
let mut f = unwrap!(std::fs::File::create (format!("{}.dot", example_name)));
unwrap!(f.write_all (Myprogram::dotfile().as_bytes()));
drop (f);
use apis::Program;
let mut myprogram = Myprogram::initial();
Myprogram::report_sizes();
myprogram.run();
println!("{}", format!("...{} main", example_name).green().bold());
}