use std::sync::{Arc, Mutex};
use std::{thread, time::Duration};
use std::collections::HashMap;
type Callback = Box<dyn FnOnce() + Send + 'static>;
enum MessageType {
CallbackFunction,
LiteMessage,
Terminate,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Object {
Bool(bool),
Char(char),
I8(i8),
U8(u8),
I16(i16),
U16(u16),
I32(i32),
U32(u32),
I64(i64),
U64(u64),
F32(f32),
F64(f64),
String(String),
BoolArray(Vec<bool>),
CharArray(Vec<char>),
I8Array(Vec<i8>),
U8Array(Vec<u8>),
I16Array(Vec<i16>),
U16Array(Vec<u16>),
I32Array(Vec<i32>),
U32Array(Vec<u32>),
I64Array(Vec<i64>),
U64Array(Vec<u64>),
F32Array(Vec<f32>),
F64Array(Vec<f64>),
StringArray(Vec<String>),
}
#[derive(Clone, Debug, PartialEq)]
struct Bundle {
data: HashMap<String, Object>,
}
impl Bundle {
pub fn new() -> Bundle {
let data = HashMap::<String, Object>::new();
Bundle {
data,
}
}
pub fn set_bool(&mut self, k: String, v: bool) {
let o = Object::Bool(v);
self.data.insert(k, o);
}
pub fn get_bool(&self, k: String, default_v: bool) -> bool {
let val = self.data.get(&k);
match val {
Some(v) => {
match v {
Object::Bool(v) => {
*v
}
_ => {
default_v
}
}
},
None => {
default_v
}
}
}
pub fn set_i32(&mut self, k: String, v: i32) {
self.data.insert(k, Object::I32(v));
}
pub fn get_i32(&self, k: String, default_v: i32) -> i32 {
let val = self.data.get(&k);
match val {
Some(v) => {
match v {
Object::I32(v) => {
*v
}
_ => {
default_v
}
}
},
None => {
default_v
}
}
}
pub fn set_string(&mut self, k: String, v: String) {
self.data.insert(k, Object::String(v));
}
pub fn get_string(&self, k: String, default_v: String) -> String {
let val = self.data.get(&k);
match val {
Some(v) => {
match v {
Object::String(v) => {
v.clone()
}
_ => {
default_v
}
}
},
None => {
default_v
}
}
}
}
#[derive(Clone, Debug, PartialEq)]
struct LiteMessage {
what: i32,
arg1: i32,
arg2: i32,
data: Bundle,
}
impl LiteMessage {
pub fn new() -> LiteMessage {
LiteMessage {
what: -1,
arg1: -1,
arg2: -1,
data: Bundle::new(),
}
}
pub fn set_what(&mut self, w: i32) {
self.what = w;
}
pub fn get_what(&self) -> i32 {
self.what
}
pub fn set_arg1(&mut self, a: i32) {
self.arg1 = a;
}
pub fn get_arg1(&self) -> i32 {
self.arg1
}
pub fn set_arg2(&mut self, a: i32) {
self.arg2 = a;
}
pub fn get_arg2(&self) -> i32 {
self.arg2
}
pub fn put_bool(&mut self, k: String, v: bool) {
self.data.set_bool(k, v);
}
pub fn get_bool(&self, k: String, default_v: bool) -> bool {
self.data.get_bool(k, default_v)
}
pub fn put_i32(&mut self, k: String, v: i32) {
self.data.set_i32(k, v);
}
pub fn get_i32(&self, k: String, default_v: i32) -> i32 {
self.data.get_i32(k, default_v)
}
pub fn put_string(&mut self, k: String, v: String) {
self.data.set_string(k, v);
}
pub fn get_string(&self, k: String, default_v: String) -> String {
self.data.get_string(k, default_v)
}
}
struct Message {
msg_type: MessageType,
cb: Option<Callback>,
lite_msg: Option<LiteMessage>,
}
impl Message {
pub fn new_with_cb(cb: Callback) -> Message {
Message {
msg_type: MessageType::CallbackFunction,
cb: Some(cb),
lite_msg: None,
}
}
pub fn new_with_lite(lite_msg: LiteMessage) -> Message {
Message {
msg_type: MessageType::LiteMessage,
cb: None,
lite_msg: Some(lite_msg),
}
}
}
struct MessageQueue {
messages: std::collections::VecDeque<Message>,
}
impl MessageQueue {
pub fn new() -> MessageQueue {
MessageQueue {
messages: std::collections::VecDeque::new(),
}
}
pub fn pop_message(&mut self) -> Option<Message> {
let msg = self.messages.pop_front();
msg
}
pub fn push_message(&mut self, msg: Message) {
self.messages.push_back(msg);
}
}
struct MessageHandler {
message_queue: Arc<Mutex<MessageQueue>>,
message_handler_thread: thread::JoinHandle<()>,
}
impl MessageHandler {
pub fn new() -> MessageHandler {
let message_queue = Arc::new(Mutex::new(MessageQueue::new()));
let message_queue_clone = Arc::clone(&message_queue);
let handler_thread = thread::Builder::new().name("MessageHandler".to_string()).spawn(move || {
loop {
let message = message_queue_clone.lock().unwrap().pop_message();
match message {
Some(msg) => {
println!("please handle new message");
let msg_type = msg.msg_type;
match msg_type {
MessageType::CallbackFunction => {
println!("do callback function");
match msg.cb {
Some(func) => {
func();
},
None => {
println!("invalid callback function");
}
}
},
MessageType::LiteMessage => {
println!("handle lite message");
match msg.lite_msg {
Some(lite_msg) => {
println!("received lite message: {:?}", lite_msg);
let v_bool = lite_msg.get_bool("key_bool_1".to_string(), false);
let v_i32 = lite_msg.get_i32("key_i32_1".to_string(), -1);
let v_string = lite_msg.get_string("key_string_1".to_string(), "default_string".to_string());
println!("v_bool: {}, v_i32: {}, v_string: {}", v_bool, v_i32, v_string);
},
None => {
println!("invalied lite message");
}
}
},
MessageType::Terminate => {
println!("received Terminate message, exit!");
break;
}
}
},
None => {
continue;
}
}
}
});
MessageHandler {
message_handler_thread: handler_thread.unwrap(),
message_queue,
}
}
pub fn send_lite_message(&mut self, msg: LiteMessage) {
println!("send lite message");
let msg = Message::new_with_lite(msg);
self.message_queue.lock().unwrap().push_message(msg);
}
pub fn send_cb_message(&mut self, cb: Callback) {
println!("send callback message");
let msg = Message::new_with_cb(cb);
self.message_queue.lock().unwrap().push_message(msg);
}
pub fn send_pure_cb_message<T>(&mut self, cb: T)
where
T: FnOnce() + Send + 'static, {
let cb = Box::new(cb);
self.send_cb_message(cb);
}
pub fn send_terminate_message(&mut self) {
println!("send terminate message");
let msg = Message {
msg_type: MessageType::Terminate,
cb: None,
lite_msg: None,
};
self.message_queue.lock().unwrap().push_message(msg);
}
}
fn handle_message(val: Arc<Mutex<i32>>) {
println!("handle message now, thread name = {:?}, val = {}", thread::current().name().unwrap(), val.lock().unwrap());
}
fn main() {
// let mut bundle = Bundle::new();
// bundle.set_bool("key_bool_1".to_string(), true);
// bundle.set_bool("key_bool_2".to_string(), false);
// let val_bool_1 = bundle.get_bool("key_bool_1".to_string(), false);
// let val_bool_2 = bundle.get_bool("key_bool_2".to_string(), true);
// println!("val_bool_1 = {}, val_bool_2 = {}", val_bool_1, val_bool_2);
// bundle.set_i32("key_i32_1".to_string(), 8);
// bundle.set_i32("key_i32_2".to_string(), 16);
// let val_i32_1 = bundle.get_i32("key_i32_1".to_string(), -1);
// let val_i32_2 = bundle.get_i32("key_i32_2".to_string(), -1);
// println!("val_i32_1 = {}, val_i32_2 = {}", val_i32_1, val_i32_2);
// bundle.set_string("key_string_1".to_string(), "test_string_1".to_string());
// bundle.set_string("key_string_2".to_string(), "test_string_2".to_string());
// let val_string_1 = bundle.get_string("key_string_1".to_string(), "default string".to_string());
// let val_string_2 = bundle.get_string("key_string_2".to_string(), "default string".to_string());
// println!("val_string_1 = {}, val_string_2 = {}", val_string_1, val_string_2);
let msg_handler = Arc::new(Mutex::new(MessageHandler::new()));
let msg_h_1 = Arc::clone(&msg_handler);
let msg_h_2 = Arc::clone(&msg_handler);
let msg_h_3 = Arc::clone(&msg_handler);
let v: i32 = 0;
let counter = Arc::new(Mutex::new(v));
let counter_1 = Arc::clone(&counter);
let counter_2 = Arc::clone(&counter);
let t1 = thread::Builder::new().name("thread_1".to_string()).spawn(move || {
loop {
{
let mut num = counter_1.lock().unwrap();
if *num == 10 {
println!("thread name = {:?}, send terminate message", thread::current().name().unwrap());
msg_h_1.lock().unwrap().send_terminate_message();
break;
}
let counter_1 = Arc::clone(&counter_1);
println!("thread name = {:?}, send cb message, val = {}", thread::current().name().unwrap(), num);
msg_h_1.lock().unwrap().send_pure_cb_message(move || {
handle_message(counter_1);
});
*num += 1;
}
thread::sleep(Duration::from_millis(500));
}
});
let t2 = thread::Builder::new().name("thread_2".to_string()).spawn(move || {
loop {
{
let mut num = counter_2.lock().unwrap();
if *num == 10 {
println!("thread name = {:?}, send terminate message", thread::current().name().unwrap());
msg_h_2.lock().unwrap().send_terminate_message();
break;
}
let counter_2 = Arc::clone(&counter_2);
println!("thread name = {:?}, send cb message, val = {}", thread::current().name().unwrap(), num);
msg_h_2.lock().unwrap().send_pure_cb_message(move || {
handle_message(counter_2);
});
*num += 1;
}
thread::sleep(Duration::from_millis(500));
}
});
let t3 = thread::Builder::new().name("thread_3".to_string()).spawn(move || {
let mut counter: i32 = 0;
loop {
if counter == 10 {
println!("counter is 10, exit loop");
// msg_h_3.lock().unwrap().send_terminate_message();
break;
} else {
let mut lite_msg = LiteMessage::new();
lite_msg.set_what(1);
lite_msg.set_arg1(counter);
lite_msg.set_arg2(counter);
lite_msg.put_bool("key_bool_1".to_string(), true);
lite_msg.put_i32("key_i32_1".to_string(), 8);
lite_msg.put_string("key_string_1".to_string(), "test_string_1".to_string());
msg_h_3.lock().unwrap().send_lite_message(lite_msg);
counter += 1;
}
}
});
t1.unwrap().join();
t2.unwrap().join();
t3.unwrap().join();
}
rust实现向handler post函数,在handler的独立线程中按照顺序执行函数对象
于 2022-04-25 19:54:14 首次发布