Skip to content

Commit

Permalink
Merge pull request #35 from torfmaster/bugfix/consume-mut-callbacks
Browse files Browse the repository at this point in the history
Fix subscription part of #33
  • Loading branch information
alevy authored Apr 9, 2018
2 parents 4eb0fed + de86c43 commit 968a3fe
Show file tree
Hide file tree
Showing 18 changed files with 263 additions and 246 deletions.
7 changes: 6 additions & 1 deletion examples/ble_scanning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extern crate tock;
use alloc::*;
use tock::ble_parser;
use tock::led;
use tock::simple_ble::BleCallback;
use tock::simple_ble::BleDriver;
use tock::syscalls;

Expand All @@ -26,7 +27,8 @@ struct LedCommand {
#[allow(unreachable_code)]
fn main() {
let mut shared_memory = BleDriver::share_memory().unwrap();
let _subscription = BleDriver::start(|_: usize, _: usize| {

let mut callback = BleCallback::new(|_: usize, _: usize| {
match ble_parser::find(
shared_memory.to_bytes(),
tock::simple_ble::gap_data::SERVICE_DATA as u8,
Expand All @@ -48,8 +50,11 @@ fn main() {
}
});

let _subscription = BleDriver::start(&mut callback);

loop {
syscalls::yieldk();
}

_subscription.unwrap();
}
3 changes: 2 additions & 1 deletion examples/button_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use tock::timer::Duration;

fn main() {
let mut console = Console::new();
let mut buttons = buttons::with_callback(|_, _| {}).unwrap();
let mut with_callback = buttons::with_callback(|_, _| {});
let mut buttons = with_callback.init().unwrap();
let mut button = buttons.iter_mut().next().unwrap();
let button = button.enable().unwrap();

Expand Down
6 changes: 4 additions & 2 deletions examples/button_subscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ use tock::timer::Duration;
fn main() {
let mut console = Console::new();

let mut buttons = buttons::with_callback(|button_num: usize, state| {
let mut with_callback = buttons::with_callback(|button_num: usize, state| {
console.write(String::from("\nButton: "));
console.write(fmt::u32_as_hex(button_num as u32));
console.write(String::from(" - State: "));
console.write(String::from(match state {
ButtonState::Pressed => "pressed",
ButtonState::Released => "released",
}));
}).unwrap();
});

let mut buttons = with_callback.init().unwrap();

for mut button in &mut buttons {
button.enable().unwrap();
Expand Down
10 changes: 5 additions & 5 deletions examples/hardware_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use alloc::string::String;
use alloc::vec::Vec;
use tock::console::Console;
use tock::ipc_cs;
use tock::ipc_cs::IpcClientCallback;
use tock::ipc_cs::ServerHandle;
use tock::timer;
use tock::timer::Duration;
Expand All @@ -35,15 +36,14 @@ fn main() {

server.share(&mut buf, &mut payload);

let handle = server.subscribe_callback(|_: usize, _: usize| {
let filtered = buf.to_vec()
.into_iter()
.filter(|x| *x != 0)
.collect::<Vec<u8>>();
let mut callback = IpcClientCallback::new(|_: usize, _: usize| {
let filtered = buf.iter().cloned().filter(|&x| x != 0).collect::<Vec<_>>();
let s = String::from_utf8_lossy(&filtered);
console.write(String::from(s).clone());
console.write(String::from("test=\"done\"\n"));
});

let handle = server.subscribe_callback(&mut callback);
server.notify();

for _ in 0.. {
Expand Down
18 changes: 10 additions & 8 deletions examples/hardware_test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ extern crate tock;
use alloc::string::String;
use alloc::vec::Vec;
use tock::ipc_cs;
use tock::ipc_cs::IpcServerCallback;
use tock::ipc_cs::IpcServerDriver;

#[allow(unreachable_code)]
// Prints the payload and adds one to the first byte.
fn main() {
let cb = &mut |pid: usize, _: usize, message: &mut [u8]| {
let mut callback = IpcServerCallback::new(|pid: usize, _: usize, message: &mut [u8]| {
let filtered = message
.to_vec()
.into_iter()
.filter(|x| *x != 0)
.iter()
.cloned()
.filter(|&x| x != 0)
.collect::<Vec<u8>>();
let s = String::from_utf8_lossy(&filtered);
if s == String::from("client") {
Expand All @@ -25,12 +26,13 @@ fn main() {
message[..l].clone_from_slice(b);
ipc_cs::notify_client(pid);
}
};
#[allow(unused_variables)]
let server = IpcServerDriver::start(cb);
});

let _server = IpcServerDriver::start(&mut callback);

loop {
tock::syscalls::yieldk();
}
server.unwrap();

_server.unwrap();
}
13 changes: 9 additions & 4 deletions examples/ipcclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,31 @@ use alloc::boxed::Box;
use alloc::string::String;
use tock::console::Console;
use tock::fmt;
use tock::ipc_cs::*;
use tock::ipc_cs;
use tock::ipc_cs::IpcClientCallback;
use tock::ipc_cs::ServerHandle;
use tock::timer;

#[allow(unreachable_code)]
// Calls the ipc_server and prints result
fn main() {
let mut buf: Box<[u8]> = reserve_shared_buffer();
let mut buf: Box<[u8]> = ipc_cs::reserve_shared_buffer();
timer::sleep(timer::Duration::from_ms(1000));

loop {
let mut server = ServerHandle::discover_service(String::from("ipcserver")).unwrap();
let mut payload: [u8; 32] = [5; 32];

server.share(&mut buf, &mut payload);
let handle = server.subscribe_callback(|_: usize, _: usize| {

let mut callback = IpcClientCallback::new(|_: usize, _: usize| {
let mut console = Console::new();
console.write(String::from("Client: \"Payload: "));
console.write(fmt::u32_as_hex(buf[0] as u32));
console.write(String::from("\"\n"));
});

let handle = server.subscribe_callback(&mut callback);

server.notify();
timer::sleep(timer::Duration::from_ms(1000));
handle.unwrap();
Expand Down
9 changes: 6 additions & 3 deletions examples/ipcserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use alloc::string::String;
use tock::console::Console;
use tock::fmt::*;
use tock::ipc_cs;
use tock::ipc_cs::IpcServerCallback;
use tock::ipc_cs::IpcServerDriver;

#[allow(unreachable_code)]
Expand All @@ -15,8 +16,7 @@ fn main() {
let mut console = Console::new();
console.write(String::from("Start service:\n"));

#[allow(unused_variables)]
let server = IpcServerDriver::start(|pid: usize, _: usize, message: &mut [u8]| {
let mut callback = IpcServerCallback::new(|pid: usize, _: usize, message: &mut [u8]| {
console.write(String::from("Server: \"Payload: "));

console.write(u32_as_hex(message[0] as u32));
Expand All @@ -25,8 +25,11 @@ fn main() {
ipc_cs::notify_client(pid);
});

let _server = IpcServerDriver::start(&mut callback);

loop {
tock::syscalls::yieldk();
}
server.unwrap();

_server.unwrap();
}
13 changes: 6 additions & 7 deletions examples/temperature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ extern crate tock;

use alloc::string::String;
use tock::console::Console;
use tock::temperature::TemperatureDriver;
use tock::temperature;

#[allow(unreachable_code)]
fn main() {
let mut console = Console::new();
#[allow(unused_variables)]
let temperature = TemperatureDriver::start_measurement(|result: isize| {
console.write(String::from("Temperature:"));

let mut with_callback = temperature::with_callback(|result: isize| {
console.write(String::from("Temperature: "));
console.write(tock::fmt::i32_as_decimal(result as i32));
console.write(String::from("\n"));
});

let _temperature = with_callback.start_measurement();

loop {
tock::syscalls::yieldk();
}
// FIXME: Find another solution to prevent the compiler from calling drop too early.
temperature.unwrap();
}
7 changes: 5 additions & 2 deletions examples/timer_subscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ use tock::timer::Duration;

fn main() {
let mut console = Console::new();
let timer = timer::with_callback(|_, _| {

let mut with_callback = timer::with_callback(|_, _| {
console.write(String::from(
"This line is printed 2 seconds after the start of the program.",
))
}).unwrap();
});

let mut timer = with_callback.init().unwrap();

timer.set_alarm(Duration::from_ms(2000)).unwrap();
loop {
Expand Down
73 changes: 36 additions & 37 deletions src/buttons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,48 @@ mod subscribe_nr {
pub const SUBSCRIBE_CALLBACK: usize = 0;
}

pub fn with_callback<CB: FnMut(usize, ButtonState)>(
pub fn with_callback<CB>(callback: CB) -> WithCallback<CB> {
WithCallback { callback }
}

pub struct WithCallback<CB> {
callback: CB,
) -> TockResult<Buttons<CB>, ButtonsError> {
let count = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0) };
}

if count < 1 {
return Err(TockValue::Expected(ButtonsError::NotSupported));
impl<CB: FnMut(usize, ButtonState)> SubscribableCallback for WithCallback<CB> {
fn call_rust(&mut self, button_num: usize, state: usize, _: usize) {
(self.callback)(button_num, state.into());
}
}

let (return_code, subscription) = syscalls::subscribe(ButtonsCallback { callback });
impl<CB> WithCallback<CB>
where
Self: SubscribableCallback,
{
pub fn init(&mut self) -> TockResult<Buttons, ButtonsError> {
let count = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0) };
if count < 1 {
return Err(TockValue::Expected(ButtonsError::NotSupported));
}

let subscription =
syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::SUBSCRIBE_CALLBACK, self);

match return_code {
result::SUCCESS => Ok(Buttons {
count: count as usize,
subscription,
}),
result::ENOMEM => Err(TockValue::Expected(ButtonsError::SubscriptionFailed)),
unexpected => Err(TockValue::Unexpected(unexpected)),
match subscription {
Ok(subscription) => Ok(Buttons {
count: count as usize,
subscription,
}),
Err(result::ENOMEM) => Err(TockValue::Expected(ButtonsError::SubscriptionFailed)),
Err(unexpected) => Err(TockValue::Unexpected(unexpected)),
}
}
}

pub struct Buttons<CB: FnMut(usize, ButtonState)> {
pub struct Buttons<'a> {
count: usize,
#[allow(dead_code)] // Used in drop
subscription: CallbackSubscription<ButtonsCallback<CB>>,
subscription: CallbackSubscription<'a>,
}

#[derive(Copy, Clone, Debug)]
Expand All @@ -51,7 +68,7 @@ pub enum ButtonsError {
SubscriptionFailed,
}

impl<CB: FnMut(usize, ButtonState)> Buttons<CB> {
impl<'a> Buttons<'a> {
pub fn iter_mut(&mut self) -> ButtonIter {
ButtonIter {
curr_button: 0,
Expand All @@ -61,24 +78,6 @@ impl<CB: FnMut(usize, ButtonState)> Buttons<CB> {
}
}

struct ButtonsCallback<CB> {
callback: CB,
}

impl<CB: FnMut(usize, ButtonState)> SubscribableCallback for ButtonsCallback<CB> {
fn driver_number(&self) -> usize {
DRIVER_NUMBER
}

fn subscribe_number(&self) -> usize {
subscribe_nr::SUBSCRIBE_CALLBACK
}

fn call_rust(&mut self, button_num: usize, state: usize, _: usize) {
(self.callback)(button_num, state.into());
}
}

#[derive(Copy, Clone, Debug)]
pub enum ButtonState {
Pressed,
Expand All @@ -95,9 +94,9 @@ impl From<usize> for ButtonState {
}
}

impl<'a, CB: FnMut(usize, ButtonState)> IntoIterator for &'a mut Buttons<CB> {
type Item = ButtonHandle<'a>;
type IntoIter = ButtonIter<'a>;
impl<'a, 'b> IntoIterator for &'b mut Buttons<'a> {
type Item = ButtonHandle<'b>;
type IntoIter = ButtonIter<'b>;

fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
Expand Down
30 changes: 24 additions & 6 deletions src/callback.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
use core::ptr;
use syscalls;

pub trait SubscribableCallback {
fn driver_number(&self) -> usize;
fn call_rust(&mut self, arg0: usize, arg1: usize, arg2: usize);
}

fn subscribe_number(&self) -> usize;
pub struct CallbackSubscription<'a> {
driver_number: usize,
subscribe_number: usize,
_lifetime: &'a (),
}

fn call_rust(&mut self, arg0: usize, arg1: usize, arg2: usize);
impl<'a> CallbackSubscription<'a> {
pub fn new(driver_number: usize, subscribe_number: usize) -> CallbackSubscription<'a> {
CallbackSubscription {
driver_number,
subscribe_number,
_lifetime: &(),
}
}
}

pub struct CallbackSubscription<CB: SubscribableCallback> {
#[allow(dead_code)] // Used in drop
pub(crate) callback: CB,
impl<'a> Drop for CallbackSubscription<'a> {
fn drop(&mut self) {
unsafe {
syscalls::subscribe_ptr(self.driver_number, self.subscribe_number, ptr::null(), 0);
}
}
}
Loading

0 comments on commit 968a3fe

Please sign in to comment.