From 07c6aec3c3ce31cb350a9f45ae77f6826de89d69 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 9 Jun 2018 16:14:57 +0300 Subject: [PATCH] Detach worker registration from a main initialization routine Workers become more compact with simple type specification. --- examples/multi_thread/README.md | 7 + examples/multi_thread/src/bin/main.rs | 14 +- .../multi_thread/src/bin/native_worker.rs | 14 + examples/multi_thread/src/lib.rs | 8 +- .../src/{worker.rs => native_worker.rs} | 2 + src/agent.rs | 486 ++++++++++-------- src/lib.rs | 9 +- src/prelude.rs | 1 - 8 files changed, 308 insertions(+), 233 deletions(-) create mode 100644 examples/multi_thread/README.md create mode 100644 examples/multi_thread/src/bin/native_worker.rs rename examples/multi_thread/src/{worker.rs => native_worker.rs} (95%) diff --git a/examples/multi_thread/README.md b/examples/multi_thread/README.md new file mode 100644 index 00000000000..f64c7475e6b --- /dev/null +++ b/examples/multi_thread/README.md @@ -0,0 +1,7 @@ +### multi_thread + +You should compile a worker which have to be spawned in a separate thread: + +```sh +cargo web build --bin native_worker --target wasm32-unknown-unknown +``` diff --git a/examples/multi_thread/src/bin/main.rs b/examples/multi_thread/src/bin/main.rs index c90919ba038..a4990217d35 100644 --- a/examples/multi_thread/src/bin/main.rs +++ b/examples/multi_thread/src/bin/main.rs @@ -4,18 +4,10 @@ extern crate multi_thread; use yew::prelude::*; use multi_thread::Model; -use multi_thread::worker; fn main() { web_logger::init(); - match yew::initialize() { - Ambit::Application => { - App::::new().mount_to_body(); - yew::run_loop(); - } - Ambit::Agent => { - worker::Worker::register(); - yew::run_agent(); - } - } + yew::initialize(); + App::::new().mount_to_body(); + yew::run_loop(); } diff --git a/examples/multi_thread/src/bin/native_worker.rs b/examples/multi_thread/src/bin/native_worker.rs new file mode 100644 index 00000000000..906f589bb37 --- /dev/null +++ b/examples/multi_thread/src/bin/native_worker.rs @@ -0,0 +1,14 @@ + +extern crate web_logger; +extern crate yew; +extern crate multi_thread; + +use yew::prelude::*; +use multi_thread::native_worker; + +fn main() { + web_logger::init(); + yew::initialize(); + native_worker::Worker::register(); + yew::run_loop(); +} diff --git a/examples/multi_thread/src/lib.rs b/examples/multi_thread/src/lib.rs index 49c1fbe161e..9ea8bb5cb93 100644 --- a/examples/multi_thread/src/lib.rs +++ b/examples/multi_thread/src/lib.rs @@ -5,14 +5,14 @@ extern crate serde_derive; #[macro_use] extern crate yew; -pub mod worker; +pub mod native_worker; pub mod job; pub mod context; use yew::prelude::*; pub struct Model { - worker: Box>, + worker: Box>, job: Box>, context: Box>, context_2: Box>, @@ -31,7 +31,7 @@ impl Component for Model { fn create(_: Self::Properties, link: ComponentLink) -> Self { let callback = link.send_back(|_| Msg::DataReceived); - let worker = worker::Worker::bridge(callback); + let worker = native_worker::Worker::bridge(callback); let callback = link.send_back(|_| Msg::DataReceived); let job = job::Worker::bridge(callback); @@ -48,7 +48,7 @@ impl Component for Model { fn update(&mut self, msg: Self::Message) -> ShouldRender { match msg { Msg::SendToWorker => { - self.worker.send(worker::Request::GetDataFromServer); + self.worker.send(native_worker::Request::GetDataFromServer); } Msg::SendToJob => { self.job.send(job::Request::GetDataFromServer); diff --git a/examples/multi_thread/src/worker.rs b/examples/multi_thread/src/native_worker.rs similarity index 95% rename from examples/multi_thread/src/worker.rs rename to examples/multi_thread/src/native_worker.rs index 585901e5394..d555bc3a03c 100644 --- a/examples/multi_thread/src/worker.rs +++ b/examples/multi_thread/src/native_worker.rs @@ -65,4 +65,6 @@ impl Agent for Worker { } } } + + fn name_of_resource() -> &'static str { "bin/native_worker.js" } } diff --git a/src/agent.rs b/src/agent.rs index 5f90d93453c..4cd99386df4 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -2,45 +2,43 @@ use std::rc::Rc; use std::cell::RefCell; -use std::any::TypeId; -use std::collections::HashMap; +use std::marker::PhantomData; use serde::{Serialize, Deserialize}; use bincode; use anymap::{AnyMap, Entry}; use slab::Slab; use stdweb::Value; -use stdweb::unstable::TryInto; use scheduler::{Runnable, scheduler}; use callback::Callback; use Shared; -type Pair = (Box, Box)>); - -thread_local! { - pub(crate) static AGENTS: RefCell> = - RefCell::new(HashMap::new()); +#[derive(Serialize, Deserialize)] +enum ToWorker { + Connected(HandlerId), + ProcessInput(HandlerId, T), + Disconnected(HandlerId), + Destroy, } -/// WARNING! This thing depends on implementation of `TypeId` of Rust. -type RawTypeId = u64; - -#[derive(Serialize, Deserialize, Debug)] -enum ToWorker { - SelectType(RawTypeId), - ProcessInput(usize, Vec), +impl Transferable for ToWorker +where + T: Serialize + for <'de> Deserialize<'de>, +{ } -impl Transferable for ToWorker { } - -#[derive(Serialize, Deserialize, Debug)] -enum FromWorker { +#[derive(Serialize, Deserialize)] +enum FromWorker { /// Worker sends this message when `wasm` bundle has loaded. WorkerLoaded, - TypeDetected, - ProcessOutput(usize, Vec), + ProcessOutput(HandlerId, T), +} + +impl Transferable for FromWorker +where + T: Serialize + for <'de> Deserialize<'de>, +{ } -impl Transferable for FromWorker { } /// Represents a message which you could send to an agent. pub trait Transferable @@ -67,9 +65,20 @@ impl Packed for T { } /// Id of responses handler. +#[derive(Serialize, Deserialize, Clone, Copy)] pub struct HandlerId(usize); -type HandlersPool = Rc>>>; +impl From for HandlerId { + fn from(id: usize) -> Self { + HandlerId(id) + } +} + +impl HandlerId { + fn raw_id(&self) -> usize { + self.0 + } +} /// This traits allow to get addres or register worker. pub trait Bridged: Agent + Sized + 'static { @@ -89,27 +98,45 @@ where T: Agent, { fn register() { - // Register function which puts every incoming message to a scheduler. - let scope_base: AgentScope = AgentScope::new(); - let scope = scope_base.clone(); - let creator = move || { - let responder = WorkerResponder { }; - let link = AgentLink::connect(&scope, responder); - let upd = AgentUpdate::Create(link); - scope.send(upd); + let scope = AgentScope::::new(); + let responder = WorkerResponder { }; + let link = AgentLink::connect(&scope, responder); + let upd = AgentUpdate::Create(link); + scope.send(upd); + let handler = move |data: Vec| { + let msg = ToWorker::::unpack(&data); + match msg { + ToWorker::Connected(id) => { + let upd = AgentUpdate::Connected(id); + scope.send(upd); + }, + ToWorker::ProcessInput(id, value) => { + let upd = AgentUpdate::Input(value, id); + scope.send(upd); + }, + ToWorker::Disconnected(id) => { + let upd = AgentUpdate::Disconnected(id); + scope.send(upd); + }, + ToWorker::Destroy => { + let upd = AgentUpdate::Destroy; + scope.send(upd); + js! { + // Terminates web worker + self.close(); + }; + }, + } }; - let scope = scope_base.clone(); - let routine = move |id: HandlerId, data: Vec| { - let msg: T::Input = bincode::deserialize(&data) - .expect("can't deserialize an input message"); - let upd = AgentUpdate::Input(msg, id); - scope.send(upd); + let loaded: FromWorker = FromWorker::WorkerLoaded; + let loaded = loaded.pack(); + js! { + var handler = @{handler}; + self.onmessage = function(event) { + handler(event.data); + }; + self.postMessage(@{loaded}); }; - AGENTS.with(move |agents| { - let type_id = TypeId::of::(); - let pair: Pair = (Box::new(creator), Box::new(routine)); - agents.borrow_mut().insert(type_id, pair); - }); } } @@ -139,17 +166,17 @@ pub trait Bridge { // <<< SAME THREAD >>> -struct LaunchedAgent { +struct LocalAgent { scope: AgentScope, slab: Shared>>, } type Last = bool; -impl LaunchedAgent { +impl LocalAgent { pub fn new(scope: &AgentScope) -> Self { let slab = Rc::new(RefCell::new(Slab::new())); - LaunchedAgent { + LocalAgent { scope: scope.clone(), slab, } @@ -163,19 +190,19 @@ impl LaunchedAgent { let id = self.slab.borrow_mut().insert(callback); ContextBridge { scope: self.scope.clone(), - id, + id: id.into(), } } fn remove_bridge(&mut self, bridge: &ContextBridge) -> Last { let mut slab = self.slab.borrow_mut(); - let _ = slab.remove(bridge.id); + let _ = slab.remove(bridge.id.raw_id()); slab.is_empty() } } thread_local! { - static CONTEXT_POOL: RefCell = RefCell::new(AnyMap::new()); + static LOCAL_AGENTS_POOL: RefCell = RefCell::new(AnyMap::new()); } /// Create a single instance in the current thread. @@ -184,15 +211,15 @@ pub struct Context; impl Discoverer for Context { fn spawn_or_join(callback: Callback) -> Box> { let mut scope_to_init = None; - let bridge = CONTEXT_POOL.with(|pool| { - match pool.borrow_mut().entry::>() { + let bridge = LOCAL_AGENTS_POOL.with(|pool| { + match pool.borrow_mut().entry::>() { Entry::Occupied(mut entry) => { // TODO Insert callback! entry.get_mut().create_bridge(callback) }, Entry::Vacant(entry) => { let scope = AgentScope::::new(); - let launched = LaunchedAgent::new(&scope); + let launched = LocalAgent::new(&scope); let responder = SlabResponder { slab: launched.slab() }; scope_to_init = Some((scope.clone(), responder)); entry.insert(launched).create_bridge(callback) @@ -204,7 +231,7 @@ impl Discoverer for Context { let upd = AgentUpdate::Create(agent_link); scope.send(upd); } - let upd = AgentUpdate::Connected(HandlerId(bridge.id)); + let upd = AgentUpdate::Connected(bridge.id.into()); bridge.scope.send(upd); Box::new(bridge) } @@ -215,44 +242,44 @@ struct SlabResponder { } impl Responder for SlabResponder { - fn response(&self, id: usize, output: AGN::Output) { - let callback = self.slab.borrow().get(id).cloned(); + fn response(&self, id: HandlerId, output: AGN::Output) { + let callback = self.slab.borrow().get(id.raw_id()).cloned(); if let Some(callback) = callback { callback.emit(output); } else { - warn!("Id of handler not exists : {}", id); + warn!("Id of handler not exists : {}", id.raw_id()); } } } struct ContextBridge { scope: AgentScope, - id: usize, + id: HandlerId, } impl Bridge for ContextBridge { fn send(&self, msg: AGN::Input) { - let upd = AgentUpdate::Input(msg, HandlerId(self.id)); + let upd = AgentUpdate::Input(msg, self.id); self.scope.send(upd); } } impl Drop for ContextBridge { fn drop(&mut self) { - CONTEXT_POOL.with(|pool| { + LOCAL_AGENTS_POOL.with(|pool| { let terminate_worker = { - if let Some(launched) = pool.borrow_mut().get_mut::>() { + if let Some(launched) = pool.borrow_mut().get_mut::>() { launched.remove_bridge(self) } else { false } }; - let upd = AgentUpdate::Connected(HandlerId(self.id)); + let upd = AgentUpdate::Disconnected(self.id); self.scope.send(upd); if terminate_worker { let upd = AgentUpdate::Destroy; self.scope.send(upd); - pool.borrow_mut().remove::>(); + pool.borrow_mut().remove::>(); } }); } @@ -268,22 +295,22 @@ impl Discoverer for Job { let agent_link = AgentLink::connect(&scope, responder); let upd = AgentUpdate::Create(agent_link); scope.send(upd); - let upd = AgentUpdate::Connected(JOB_SINGLE_ID); + let upd = AgentUpdate::Connected(SINGLETON_ID); scope.send(upd); let bridge = JobBridge { scope }; Box::new(bridge) } } -const JOB_SINGLE_ID: HandlerId = HandlerId(0); +const SINGLETON_ID: HandlerId = HandlerId(0); struct CallbackResponder { callback: Callback, } impl Responder for CallbackResponder { - fn response(&self, id: usize, output: AGN::Output) { - assert_eq!(id, JOB_SINGLE_ID.0); + fn response(&self, id: HandlerId, output: AGN::Output) { + assert_eq!(id.raw_id(), SINGLETON_ID.raw_id()); self.callback.emit(output); } } @@ -294,14 +321,14 @@ struct JobBridge { impl Bridge for JobBridge { fn send(&self, msg: AGN::Input) { - let upd = AgentUpdate::Input(msg, JOB_SINGLE_ID); + let upd = AgentUpdate::Input(msg, SINGLETON_ID); self.scope.send(upd); } } impl Drop for JobBridge { fn drop(&mut self) { - let upd = AgentUpdate::Disconnected(JOB_SINGLE_ID); + let upd = AgentUpdate::Disconnected(SINGLETON_ID); self.scope.send(upd); let upd = AgentUpdate::Destroy; self.scope.send(upd); @@ -313,122 +340,159 @@ impl Drop for JobBridge { /// Create a new instance for every bridge. pub struct Private; -impl Discoverer for Private { } - -/// Create a single instance in a tab. -pub struct Public; - -impl Discoverer for Public { +impl Discoverer for Private { fn spawn_or_join(callback: Callback) -> Box> { - let worker_base = js! { - // TODO Use relative path. But how? - var worker = new Worker("main.js"); - return worker; - }; - let worker = worker_base.clone(); - let send_to_app = move |msg: ToWorker| { - let bytes = msg.pack(); - let worker = worker.clone(); - js! { - var worker = @{worker}; - worker.postMessage(@{bytes}); - }; - }; - let slab: Slab> = Slab::new(); - let callbacks_base = Rc::new(RefCell::new(slab)); - let callbacks = callbacks_base.clone(); - let handshake = move |data: Vec| { - let msg = FromWorker::unpack(&data); + let handler = move |data: Vec| { + let msg = FromWorker::::unpack(&data); match msg { FromWorker::WorkerLoaded => { - let type_id = TypeId::of::(); - let raw_type_id: RawTypeId = unsafe { ::std::mem::transmute(type_id) }; - let msg = ToWorker::SelectType(raw_type_id); - send_to_app(msg); }, - FromWorker::TypeDetected => { - info!("Worker handshake finished"); - // TODO Send `AgetUpdate::Connected(_)` message - }, - FromWorker::ProcessOutput(id, data) => { - let msg = AGN::Output::unpack(&data); - let callback = callbacks.borrow().get(id).cloned(); - if let Some(callback) = callback { - callback.emit(msg); - } + FromWorker::ProcessOutput(id, output) => { + assert_eq!(id.raw_id(), SINGLETON_ID.raw_id()); + callback.emit(output); }, } }; - let worker = worker_base.clone(); - js! { - var worker = @{worker}; - // TODO Send type id (but on ready event) - var handshake = @{handshake}; + // TODO Need somethig better... + let name_of_resource = AGN::name_of_resource(); + let worker = js! { + var worker = new Worker(@{name_of_resource}); + var handler = @{handler}; worker.onmessage = function(event) { - handshake(event.data); + handler(event.data); }; + return worker; }; - let id = callbacks_base.borrow_mut().insert(callback); - let bridge = PublicBridge { - worker: worker_base, - callbacks: callbacks_base, - id, + let bridge = PrivateBridge { + worker, + _agent: PhantomData, }; Box::new(bridge) } } -/// Create a single instance in a browser. -pub struct Global; +/// A connection manager for components interaction with workers. +pub struct PrivateBridge { + worker: Value, + _agent: PhantomData, +} -impl Discoverer for Global { } +impl Bridge for PrivateBridge { + fn send(&self, msg: AGN::Input) { + // TODO Important! Implement. + // Use a queue to collect a messages if an instance is not ready + // and send them to an agent when it will reported readiness. + let msg = ToWorker::ProcessInput(SINGLETON_ID, msg).pack(); + let worker = &self.worker; + js! { + var worker = @{worker}; + var bytes = @{msg}; + worker.postMessage(bytes); + }; + } +} -/// Declares the behavior of the agent. -pub trait Agent: Sized + 'static { - /// Reach capaility of the agent. - type Reach: Discoverer; - /// Type of an input messagae. - type Message; - /// Incoming message type. - type Input: Transferable; - /// Outgoing message type. - type Output: Transferable; +impl Drop for PrivateBridge { + fn drop(&mut self) { + // TODO Send `Destroy` message. + } +} - /// Creates an instance of an agent. - fn create(link: AgentLink) -> Self; +struct RemoteAgent { + worker: Value, + slab: Shared>>, +} - /// This method called on every update message. - fn update(&mut self, msg: Self::Message); +impl RemoteAgent { + pub fn new(worker: &Value, slab: Shared>>) -> Self { + RemoteAgent { + worker: worker.clone(), + slab, + } + } - /// This method called on when a new bridge created. - fn connected(&mut self, _id: HandlerId) { } + fn create_bridge(&mut self, callback: Callback) -> PublicBridge { + let id = self.slab.borrow_mut().insert(callback); + PublicBridge { + worker: self.worker.clone(), + id: id.into(), + _agent: PhantomData, + } + } - /// This method called on every incoming message. - fn handle(&mut self, msg: Self::Input, id: HandlerId); + fn remove_bridge(&mut self, bridge: &PublicBridge) -> Last { + let mut slab = self.slab.borrow_mut(); + let _ = slab.remove(bridge.id.raw_id()); + slab.is_empty() + } +} - /// This method called on when a new bridge destroyed. - fn disconnected(&mut self, _id: HandlerId) { } +thread_local! { + static REMOTE_AGENTS_POOL: RefCell = RefCell::new(AnyMap::new()); +} - /// Creates an instance of an agent. - fn destroy(&mut self) { } +/// Create a single instance in a tab. +pub struct Public; +impl Discoverer for Public { + fn spawn_or_join(callback: Callback) -> Box> { + let bridge = REMOTE_AGENTS_POOL.with(|pool| { + match pool.borrow_mut().entry::>() { + Entry::Occupied(mut entry) => { + // TODO Insert callback! + entry.get_mut().create_bridge(callback) + }, + Entry::Vacant(entry) => { + let slab_base: Shared>> = + Rc::new(RefCell::new(Slab::new())); + let slab = slab_base.clone(); + let handler = move |data: Vec| { + let msg = FromWorker::::unpack(&data); + match msg { + FromWorker::WorkerLoaded => { + // TODO Use `AtomicBool` lock to check its loaded + }, + FromWorker::ProcessOutput(id, output) => { + let callback = slab.borrow().get(id.raw_id()).cloned(); + if let Some(callback) = callback { + callback.emit(output); + } else { + warn!("Id of handler for remote worker not exists : {}", id.raw_id()); + } + }, + } + }; + let name_of_resource = AGN::name_of_resource(); + let worker = js! { + var worker = new Worker(@{name_of_resource}); + var handler = @{handler}; + worker.onmessage = function(event) { + handler(event.data); + }; + return worker; + }; + let launched = RemoteAgent::new(&worker, slab_base); + entry.insert(launched).create_bridge(callback) + }, + } + }); + Box::new(bridge) + } } /// A connection manager for components interaction with workers. pub struct PublicBridge { worker: Value, - callbacks: HandlersPool, - id: usize, + id: HandlerId, + _agent: PhantomData, } -impl Bridge for PublicBridge { - fn send(&self, msg: AGN::Input) { +impl PublicBridge { + fn send_to_remote(&self, msg: ToWorker) { // TODO Important! Implement. // Use a queue to collect a messages if an instance is not ready // and send them to an agent when it will reported readiness. - let bytes = bincode::serialize(&msg) - .expect("can't serialize message for agent"); - let msg = ToWorker::ProcessInput(self.id, bytes).pack(); + let msg = msg.pack(); let worker = &self.worker; js! { var worker = @{worker}; @@ -438,70 +502,74 @@ impl Bridge for PublicBridge { } } +impl Bridge for PublicBridge { + fn send(&self, msg: AGN::Input) { + let msg = ToWorker::ProcessInput(self.id, msg); + self.send_to_remote(msg); + } +} + impl Drop for PublicBridge { fn drop(&mut self) { - let _ = self.callbacks.borrow_mut().remove(self.id); + REMOTE_AGENTS_POOL.with(|pool| { + let terminate_worker = { + if let Some(launched) = pool.borrow_mut().get_mut::>() { + launched.remove_bridge(self) + } else { + false + } + }; + let upd = ToWorker::Disconnected(self.id); + self.send_to_remote(upd); + if terminate_worker { + let upd = ToWorker::Destroy; + self.send_to_remote(upd); + pool.borrow_mut().remove::>(); + } + }); } } -/// This function selects the agent to start. -pub(crate) fn run_agent() { - let sender = |msg: FromWorker| { - let data = msg.pack(); - js! { - var data = @{data}; - self.postMessage(data); - }; - }; - let mut handler = None; - let handshake = move |data: Vec| { - let msg = ToWorker::unpack(&data); - match msg { - ToWorker::SelectType(raw_type_id) => { - let type_id: TypeId = unsafe { ::std::mem::transmute(raw_type_id) }; - handler = AGENTS.with(move |agents| { - let mut agents = agents.borrow_mut(); - let result = agents.remove(&type_id); - agents.clear(); // Drop unnecessary types of handlers - result.map(|(creator, handler)| { - creator(); - handler - }) - }); - }, - ToWorker::ProcessInput(id, data) => { - let func = handler.as_mut() - .expect("TypeId of agent was not selected."); - let handler_id = HandlerId(id); - func(handler_id, data); - }, - } - }; - js! { - let handshake = @{handshake}; - self.onmessage = function(event) { - handshake(event.data); - }; - // TODO Clean up the allocated memory - }; - sender(FromWorker::WorkerLoaded); -} -pub(crate) fn detect_ambit() -> Ambit { - let res = js! { - return !(self.document === undefined); - }; - let is_window = res.try_into().expect("can't check the type of self environment"); - if is_window { Ambit::Application } else { Ambit::Agent } +/// Create a single instance in a browser. +pub struct Global; + +impl Discoverer for Global { } + +/// Declares the behavior of the agent. +pub trait Agent: Sized + 'static { + /// Reach capaility of the agent. + type Reach: Discoverer; + /// Type of an input messagae. + type Message; + /// Incoming message type. + type Input: Transferable; + /// Outgoing message type. + type Output: Transferable; + + /// Creates an instance of an agent. + fn create(link: AgentLink) -> Self; + + /// This method called on every update message. + fn update(&mut self, msg: Self::Message); + + /// This method called on when a new bridge created. + fn connected(&mut self, _id: HandlerId) { } + + /// This method called on every incoming message. + fn handle(&mut self, msg: Self::Input, id: HandlerId); + + /// This method called on when a new bridge destroyed. + fn disconnected(&mut self, _id: HandlerId) { } + + /// Creates an instance of an agent. + fn destroy(&mut self) { } + + /// Represents the name of loading resorce for remote workers which + /// have to live in a separate files. + fn name_of_resource() -> &'static str { "main.js" } -} -/// Represents the kind of environment where the instance lives. -pub enum Ambit { - /// `Window` environment - Application, - /// `Worker` environment - Agent, } /// This sctruct holds a reference to a component and to a global scheduler. @@ -534,15 +602,15 @@ impl AgentScope { } trait Responder { - fn response(&self, id: usize, output: AGN::Output); + fn response(&self, id: HandlerId, output: AGN::Output); } struct WorkerResponder { } impl Responder for WorkerResponder { - fn response(&self, id: usize, output: AGN::Output) { - let msg = FromWorker::ProcessOutput(id, output.pack()); + fn response(&self, id: HandlerId, output: AGN::Output) { + let msg = FromWorker::ProcessOutput(id, output); let data = msg.pack(); js! { var data = @{data}; @@ -570,7 +638,7 @@ impl AgentLink { } /// Send response to an actor. - pub fn response(&self, HandlerId(id): HandlerId, output: AGN::Output) { + pub fn response(&self, id: HandlerId, output: AGN::Output) { self.responder.response(id, output); } diff --git a/src/lib.rs b/src/lib.rs index ed6931fdcb6..bee090e4473 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,18 +91,11 @@ type Shared = Rc>; struct Hidden; /// Initializes yew framework. It should be called first. -pub fn initialize() -> agent::Ambit { +pub fn initialize() { stdweb::initialize(); - agent::detect_ambit() } /// Starts event loop. pub fn run_loop() { stdweb::event_loop(); } - -/// Starts event loop. -pub fn run_agent() { - agent::run_agent(); - stdweb::event_loop(); -} diff --git a/src/prelude.rs b/src/prelude.rs index c73e0693d56..de35f1d73b5 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -40,7 +40,6 @@ pub use stdweb::web::event::{ }; pub use agent::{ - Ambit, Bridge, Bridged, Threaded,