Rust全局动态变量踩坑记
### 有个宇宙难题就是Rust的全局动态变量
但是很不巧桌面应用就是得对全局变量进行大量读写,在与热心网友的沟通中发现了有个 rwlock<arc<any>> 可以实现全局变量的读写 于是我就很欢乐的放弃掉了问题很多的 lazy_static 宏魔法,于是开启了连续三天的与编译器斗其乐无穷的乐趣
#### 很多版本是吧 冰山一角而已
!(https://cos.kiic.top//202310060034631.webp?imageMogr2/quality/90/format/webp)
#### 踩坑之路1.0
测试rwlock<arc<any>> 是否有效
- **这里的 RwLock<Arc<any>>是一个变量存储容器允许多个线程同时读 只允许一个线程写**
- **确实有效 而且非常好用**(**但是不支持多线程**奇怪吧 用来支持多线程的变量容器不支持多线程更新 )
```rust
use std::ptr::null_mut;
use std::sync::{Arc, RwLock};
thread_local! {
static CURRENT_CONFIG: RwLock<Arc<String>> = RwLock::new(Arc::new(String::new()));
}
macro_rules! write_rw_lock {
($rw_lock_var: expr,$value:expr) => {{
let mut result = false;
// 写入
$rw_lock_var.with(|config| {
if let Result::Ok(mut write_lock) = config.write() {
*write_lock = Arc::new($value);
result = true;
}
});
result
}};
}
macro_rules! read_rw_lock {
($rw_lock_var: expr) => {{
let mut read_value = Default::default();
// 读取
$rw_lock_var.with(|config| {
if let Result::Ok(mut read_data) = config.read() {
read_value = Some(read_data.clone());
} else {
read_value = None;
}
});
read_value
}};
}
fn main() {
write_rw_lock!(CURRENT_CONFIG, "1111111111".to_string());
read_rw_lock!(CURRENT_CONFIG);
if let Option::Some(read_value) = read_rw_lock!(CURRENT_CONFIG) {
println!("Current config: {}", read_value);
}
println!("Current config: {}", read_rw_lock!(CURRENT_CONFIG).unwrap());
write_rw_lock!(CURRENT_CONFIG, "222222222222222222".to_string());
write_rw_lock!(CURRENT_CONFIG, "888888888888888888888888".to_string());
if let Option::Some(read_value) = read_rw_lock!(CURRENT_CONFIG) {
println!("Current config: {}", read_value);
}
}
```
#### 当我风风火火的把几十变量编辑的函数改成 rwlock<arc<any>>了 *** <u>坑出现了!!!</u>***【多线程副本不更新 对没错 一个有数据一个没有数据 访问的同一个变量】
- 于是开始疯狂搜索资料
- Rust `RwLock` `Arc` 多线程 不更新数据问题 ,Rust 并发编程 下 `RwLock` `Arc` 数据不更新
- Rust `RwLock` `Arc` многопоточность не обновляет данные , Проблема с обновлением данных при использовании `RwLock` и `Arc` в Rust
- Rust `RwLock` `Arc` multithreading not updating data,Rust concurrency issue with `RwLock` and `Arc` not updating data
- **很棒一个有用的都没有**
于是我开始换了个角度思考 既然lazy_static 的原理是进行线程死锁,那么原子也可以做得到 而且还能防止线程卡死,还可以细分化变量编辑
#### 新的踩坑开始
#### 使用原子锁 +static mut
- 这次终于解决了多线程读写会线程死锁了**但是问题又来了 我存储为了方便 使用的是map哈希表进行数据键值对存储**
```rust
#!
use std::sync::atomic::{AtomicBool, AtomicI32, AtomicUsize, Ordering,AtomicI64};
use std::sync::{Arc, Condvar, Mutex,RwLock};
static mut STRING: String = String::new();
static STRING_BIND: AtomicUsize = AtomicUsize::new(0);
fn main() {
let mut new_str = String::from("这是一个文本");
// 原子互斥锁
let mutex = Arc::new(Mutex::new(&STRING_BIND));
mutex.lock();
// 获取当前编辑次数 以便下次叠加 也可以防止因为数据没有更新 原子锁被释放
let the_value:usize = STRING_BIND.load(Ordering::SeqCst);
// mut 的 static 都是必须要在unsafe 里面执行的 无论读写 因为多线程下极有可能出现脏数据 这就是为什么要加原子锁的原因
unsafe{
//
STRING = new_str.clone();
}
// 写入编辑次数 为什么这里会有这一步 因为原子锁可能会在上面已经被释放掉了 那么加锁就没有意义了
STRING_BIND.store(the_value+1, Ordering::SeqCst);
// 释放原子锁(避免奇怪的没有释放的问题)
drop(mutex);
}
```
##### 试试哈希表全局变量
```rust
#!
use std::sync::atomic::{AtomicBool, AtomicI32, AtomicUsize, Ordering,AtomicI64};
use std::sync::{Arc, Condvar, Mutex,RwLock};
use std::collections::HashMap;
static mut STRING_MAP: HashMap<String,String> = HashMap::new();
static STRING_BIND: AtomicUsize = AtomicUsize::new(0);
fn main() {}
```
#### 很好,被编译器骂了 而且骂的很难听 甚至还有点理不直气也壮的感觉
- 提醒的使用 `Lazy` 好像挺不错 但是我一看到后面有个 `once_cell` 这个我知道 这个是个只能赋值一次的容器
- 你猜猜我为啥要加个mut 申明?
!(https://cos.kiic.top//202310060109628.png?imageMogr2/quality/90/format/webp)
#### 于是我拿`Option`包裹了一层 这回终于成功了
```rust
#!
use std::sync::atomic::{AtomicBool, AtomicI32, AtomicUsize, Ordering,AtomicI64};
use std::sync::{Arc, Condvar, Mutex,RwLock};
use std::collections::HashMap;
static mut STRING_MAP: Option<HashMap<String,String>> = Option::None;
static STRING_BIND: AtomicUsize = AtomicUsize::new(0);
fn main() {
let key = String::from("key");
let mutex = Arc::new(Mutex::new(&STRING_BIND));
mutex.lock();
let the_value:usize = STRING_BIND.load(Ordering::SeqCst);
unsafe {
// 初始化
STRING_MAP.replace(HashMap::new());
// 写
if let Some(value) = STRING_MAP.as_mut() {
value.insert(key.clone(),String::from("你好啊小螃蟹"));
}
// 读
if let Some(value) = &STRING_MAP {
if let Some(get_data) = value.get(&*key.clone()) {
println!("很高兴认识你 : {}",get_data);
}
}
}
STRING_BIND.store(the_value+1, Ordering::SeqCst);
drop(mutex);
}
```
!(https://cos.kiic.top//202310060124630.png?imageMogr2/quality/90/format/webp)
#### 来个我自用的全局变量模块全文
```rust
#!
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, AtomicI32, AtomicI64, AtomicUsize, Ordering};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, OnceLock, RwLock};
// 哈希表
static mut VARIABLE_U64: Option<HashMap<String, u64>> = Option::None;
static mut VARIABLE_STRING: Option<HashMap<String, String>> = Option::None;
static mut VARIABLE_I32: Option<HashMap<String, i32>> = Option::None;
static mut VARIABLE_I128: Option<HashMap<String, i128>> = Option::None;
static mut VARIABLE_BOOL: Option<HashMap<String, bool>> = Option::None;
static mut VARIABLE_VEC_STRING: Option<HashMap<String, Vec<String>>> = Option::None;
static mut VARIABLE_VEC_I32: Option<HashMap<String, Vec<i32>>> = Option::None;
// 绑定的原子锁
static VARIABLE_STRING_BIND: AtomicUsize = AtomicUsize::new(0);
static VARIABLE_I32_BIND: AtomicUsize = AtomicUsize::new(0);
static VARIABLE_I128_BIND: AtomicUsize = AtomicUsize::new(0);
static VARIABLE_BOOL_BIND: AtomicUsize = AtomicUsize::new(0);
static VARIABLE_VEC_STRING_BIND: AtomicUsize = AtomicUsize::new(0);
static VARIABLE_VEC_I32_BIND: AtomicUsize = AtomicUsize::new(0);
static VARIABLE_U64_BIND: AtomicUsize = AtomicUsize::new(0);
// 已经初始化哈希表了
static VARIABLE_INITIALIZE: OnceLock<bool> = OnceLock::new();
// 初始化全部类型哈希表
fn initialize() {
if *(VARIABLE_INITIALIZE.get().unwrap_or_else(|| &false)) {
return;
}
unsafe {
if VARIABLE_U64.is_none() {
VARIABLE_U64.replace(HashMap::new());
}
}
unsafe {
if VARIABLE_STRING.is_none() {
VARIABLE_STRING.replace(HashMap::new());
}
}
unsafe {
if VARIABLE_I32.is_none() {
VARIABLE_I32.replace(HashMap::new());
}
}
unsafe {
if VARIABLE_I128.is_none() {
VARIABLE_I128.replace(HashMap::new());
}
}
unsafe {
if VARIABLE_BOOL.is_none() {
VARIABLE_BOOL.replace(HashMap::new());
}
}
unsafe {
if VARIABLE_VEC_STRING.is_none() {
VARIABLE_VEC_STRING.replace(HashMap::new());
}
}
unsafe {
if VARIABLE_VEC_I32.is_none() {
VARIABLE_VEC_I32.replace(HashMap::new());
}
}
VARIABLE_INITIALIZE.set(true);
}
// 母函数
// 设置 u64 键值对
pub fn set_u64(key: &str, value: u64) {
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_U64_BIND));
mutex.lock();
let the_value: usize = VARIABLE_U64_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_U64.as_mut().unwrap();
mut_hash.insert(key.to_string(), value);
};
VARIABLE_U64_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
}
// 获取 u64 键值
pub fn get_u64(key: &str) -> Option<u64> {
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_U64_BIND));
mutex.lock();
let the_value: usize = VARIABLE_U64_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_U64.as_mut().unwrap();
if let Some(value) = mut_hash.get(&key.to_string()) {
return Some(value.clone());
};
};
// 写入操作记录到原子并解锁
VARIABLE_U64_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
None
}
// 获取 u64 键值 没有则返回另外的值
pub fn get_u64_or(key: &str, or_value: u64) -> u64 {
if let Some(value) = get_u64(key) {
return value;
}
or_value
}
// 获取 u64 键值 没有则返回另外的值
pub fn get_u64_default(key: &str) -> u64 {
let or_value: u64 = 0;
if let Some(value) = get_u64(key) {
return value;
}
or_value
}
// 判断 u64 键存在
pub fn has_u64(key: &str) -> bool {
initialize();
let mut result = false;
let mutex = Arc::new(Mutex::new(&VARIABLE_U64_BIND));
mutex.lock();
let the_value: usize = VARIABLE_U64_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_U64.as_mut().unwrap();
result = mut_hash.get(&key.to_string()).is_some();
};
// 写入操作记录到原子并解锁
VARIABLE_U64_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}
// 设置值的宏
macro_rules! set_map_bind_variable {
($variable_mut_static: expr,$variable_atomic_bind: expr,$key:expr ,$value:expr) => {{
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
mut_hash.insert($key.to_string(), $value);
};
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
}};
}
// 获取值的宏
macro_rules! get_map_bind_variable {
($variable_mut_static: expr,$variable_atomic_bind: expr,$key:expr ) => {{
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
if let Some(value) = mut_hash.get(&$key.to_string()) {
return Some(value.clone());
};
};
// 写入操作记录到原子并解锁
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
None
}};
}
// 判断键的宏
macro_rules! has_map_bind_variable {
($variable_mut_static: expr,$variable_atomic_bind: expr,$key:expr ) => {{
initialize();
let mut result = false;
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
result = mut_hash.get(&$key.to_string()).is_some();
};
// 写入操作记录到原子并解锁
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}};
}
// 宏生成的
// 设置 i32 键值对
pub fn set_i32(key: &str, value: i32) {
set_map_bind_variable!(VARIABLE_I32, VARIABLE_I32_BIND, key, value)
}
// 获取 i32 键值
pub fn get_i32(key: &str) -> Option<i32> {
get_map_bind_variable!(VARIABLE_I32, VARIABLE_I32_BIND, key)
}
// 获取 i32 键值 没有则返回另外的值
pub fn get_i32_or(key: &str, or_value: i32) -> i32 {
if let Some(value) = get_i32(key) {
return value;
}
or_value
}
// 获取 i32 键值 没有则返回另外的值
pub fn get_i32_default(key: &str) -> i32 {
let or_value: i32 = 0;
if let Some(value) = get_i32(key) {
return value;
}
or_value
}
// 判断 i32 键存在
pub fn has_i32(key: &str) -> bool {
has_map_bind_variable!(VARIABLE_I32, VARIABLE_I32_BIND, key)
}
// 设置 i128 键值对
pub fn set_i128(key: &str, value: i128) {
set_map_bind_variable!(VARIABLE_I128, VARIABLE_I128_BIND, key, value)
}
// 获取 i128 键值
pub fn get_i128(key: &str) -> Option<i128> {
get_map_bind_variable!(VARIABLE_I128, VARIABLE_I128_BIND, key)
}
// 获取 i128 键值 没有则返回另外的值
pub fn get_i128_or(key: &str, or_value: i128) -> i128 {
if let Some(value) = get_i128(key) {
return value;
}
or_value
}
// 获取 i128 键值 没有则返回另外的值
pub fn get_i128_default(key: &str) -> i128 {
let or_value: i128 = 0;
if let Some(value) = get_i128(key) {
return value;
}
or_value
}
// 判断 i128 键存在
pub fn has_i128(key: &str) -> bool {
has_map_bind_variable!(VARIABLE_I128, VARIABLE_I128_BIND, key)
}
// 设置 bool 键值对
pub fn set_bool(key: &str, value: bool) {
set_map_bind_variable!(VARIABLE_BOOL, VARIABLE_BOOL_BIND, key, value)
}
// 获取 bool 键值
pub fn get_bool(key: &str) -> Option<bool> {
get_map_bind_variable!(VARIABLE_BOOL, VARIABLE_BOOL_BIND, key)
}
// 获取 bool 键值 没有则返回另外的值
pub fn get_bool_or(key: &str, or_value: bool) -> bool {
if let Some(value) = get_bool(key) {
return value;
}
or_value
}
// 获取 bool 键值 没有则返回另外的值
pub fn get_bool_default(key: &str) -> bool {
let or_value: bool = false;
if let Some(value) = get_bool(key) {
return value;
}
or_value
}
// 判断 bool 键存在
pub fn has_bool(key: &str) -> bool {
has_map_bind_variable!(VARIABLE_BOOL, VARIABLE_BOOL_BIND, key)
}
// 设置 string 键值对
pub fn set_string(key: &str, value: String) {
set_map_bind_variable!(VARIABLE_STRING, VARIABLE_STRING_BIND, key, value)
}
// 获取 string 键值
pub fn get_string(key: &str) -> Option<String> {
get_map_bind_variable!(VARIABLE_STRING, VARIABLE_STRING_BIND, key)
}
// 获取 string 键值 没有则返回另外的值
pub fn get_string_or(key: &str, or_value: String) -> String {
if let Some(value) = get_string(key) {
return value;
}
or_value
}
// 获取 String 键值 没有则返回另外的值
pub fn get_string_default(key: &str) -> String {
let or_value: String = String::new();
if let Some(value) = get_string(key) {
return value;
}
or_value
}
// 判断 string 键存在
pub fn has_string(key: &str) -> bool {
has_map_bind_variable!(VARIABLE_STRING, VARIABLE_STRING_BIND, key)
}
// 设置 Vec<String> 键值对
pub fn set_vec_string(key: &str, value: Vec<String>) {
set_map_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key, value)
}
// 获取 Vec<String> 键值
pub fn get_vec_string(key: &str) -> Option<Vec<String>> {
get_map_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key)
}
// 获取 Vec<String> 键值 没有则返回另外的值
pub fn get_vec_string_or(key: &str, or_value: Vec<String>) -> Vec<String> {
if let Some(value) = get_vec_string(key) {
return value;
}
or_value
}
// 获取 Vec<String> 键值 没有则返回另外的值
pub fn get_vec_string_default(key: &str) -> Vec<String> {
let or_value = Vec::new();
if let Some(value) = get_vec_string(key) {
return value;
}
or_value
}
// 判断 Vec<String> 键存在
pub fn has_vec_string(key: &str) -> bool {
has_map_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key)
}
// 设置 Vec<i32> 键值对
pub fn set_vec_i32(key: &str, value: Vec<i32>) {
set_map_bind_variable!(VARIABLE_VEC_I32, VARIABLE_VEC_I32_BIND, key, value)
}
// 获取 Vec<i32> 键值
pub fn get_vec_i32(key: &str) -> Option<Vec<i32>> {
get_map_bind_variable!(VARIABLE_VEC_I32, VARIABLE_VEC_I32_BIND, key)
}
// 获取 Vec<i32> 键值 没有则返回另外的值
pub fn get_vec_i32_or(key: &str, or_value: Vec<i32>) -> Vec<i32> {
if let Some(value) = get_vec_i32(key) {
return value;
}
or_value
}
// 获取 Vec<i32> 键值 没有则返回另外的值
pub fn get_vec_i32_default(key: &str) -> Vec<i32> {
let or_value = Vec::new();
if let Some(value) = get_vec_i32(key) {
return value;
}
or_value
}
// 判断 Vec<i32> 键存在
pub fn has_vec_i32(key: &str) -> bool {
has_map_bind_variable!(VARIABLE_VEC_I32, VARIABLE_VEC_I32_BIND, key)
}
// 添加一个数组的所有值
pub fn insert_vec_i32(key: &str, value: Vec<i32>) {
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_VEC_I32_BIND));
mutex.lock();
let the_value: usize = VARIABLE_VEC_I32_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_VEC_I32.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&key.to_string()) {
for data in value {
vec_value.push(data);
}
} else {
mut_hash.insert(key.to_string(), value);
}
};
VARIABLE_VEC_I32_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
}
// 添加数组值
pub fn push_vec_i32(key: &str, value: i32) {
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_VEC_I32_BIND));
mutex.lock();
let the_value: usize = VARIABLE_VEC_I32_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_VEC_I32.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&key.to_string()) {
vec_value.push(value);
} else {
mut_hash.insert(key.to_string(), Vec::from(vec!));
}
};
VARIABLE_VEC_I32_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
}
// 取出并清空数组
pub fn retrieve_vec_i32(key: &str) -> Vec<i32> {
let mut result = Vec::new();
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_VEC_I32_BIND));
mutex.lock();
let the_value: usize = VARIABLE_VEC_I32_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_VEC_I32.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&key.to_string()) {
for value in &mut *vec_value {
result.push(value.clone());
}
vec_value.clear();
} else {
mut_hash.insert(key.to_string(), Vec::new());
}
};
VARIABLE_VEC_I32_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}
// 获取数组的数量
pub fn get_vec_i32_len(key: &str) -> usize {
let mut result: usize = 0;
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_VEC_I32_BIND));
mutex.lock();
let the_value: usize = VARIABLE_VEC_I32_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_VEC_I32.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&key.to_string()) {
result = vec_value.len();
} else {
mut_hash.insert(key.to_string(), Vec::new());
}
};
VARIABLE_VEC_I32_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}
// 获取数组的指定索引
pub fn get_vec_i32_from_index(key: &str, index: usize) -> Option<i32> {
let mut result: Option<i32> = Option::None;
initialize();
let mutex = Arc::new(Mutex::new(&VARIABLE_VEC_I32_BIND));
mutex.lock();
let the_value: usize = VARIABLE_VEC_I32_BIND.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = VARIABLE_VEC_I32.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&key.to_string()) {
if let Some(value) = vec_value.get(index) {
result = Some(value.clone());
}
} else {
mut_hash.insert(key.to_string(), Vec::new());
}
};
VARIABLE_VEC_I32_BIND.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}
macro_rules! insert_map_vec_bind_variable {
($variable_mut_static:expr,$variable_atomic_bind:expr,$key:expr, $value: expr) => {{
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&$key.to_string()) {
for data in $value {
vec_value.push(data);
}
} else {
mut_hash.insert($key.to_string(), $value);
}
};
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
}};
}
macro_rules! push_map_vec_bind_variable {
($variable_mut_static:expr,$variable_atomic_bind:expr,$key:expr, $value:expr) => {{
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&$key.to_string()) {
vec_value.push($value);
} else {
mut_hash.insert($key.to_string(), Vec::from(vec![$value]));
}
};
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
}};
}
macro_rules! retrieve_map_vec_bind_variable {
($variable_mut_static:expr,$variable_atomic_bind:expr,$key: expr) => {{
let mut result = Vec::new();
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&$key.to_string()) {
for value in &mut *vec_value {
result.push(value.clone());
}
vec_value.clear();
} else {
mut_hash.insert($key.to_string(), Vec::new());
}
};
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}};
}
macro_rules! from_index_map_vec_bind_variable {
($variable_mut_static:expr,$variable_atomic_bind:expr,$key: expr, $index: expr) => {{
let mut result = Option::None;
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&$key.to_string()) {
if let Some(value) = vec_value.get($index) {
result = Some(value.clone());
}
} else {
mut_hash.insert($key.to_string(), Vec::new());
}
};
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}};
}
macro_rules! len_map_vec_bind_variable {
($variable_mut_static:expr,$variable_atomic_bind:expr,$key:expr) => {{
let mut result: usize = 0;
initialize();
let mutex = Arc::new(Mutex::new(&$variable_atomic_bind));
mutex.lock();
let the_value: usize = $variable_atomic_bind.load(Ordering::SeqCst);
unsafe {
let mut mut_hash = $variable_mut_static.as_mut().unwrap();
if let Some(vec_value) = mut_hash.get_mut(&$key.to_string()) {
result = vec_value.len();
} else {
mut_hash.insert($key.to_string(), Vec::new());
}
};
$variable_atomic_bind.store(the_value + 1, Ordering::SeqCst);
drop(mutex);
result
}};
}
// 添加一个数组的所有值
pub fn insert_vec_string(key: &str, value: Vec<String>) {
insert_map_vec_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key, value)
}
// 添加数组值
pub fn push_vec_string(key: &str, value: String) {
push_map_vec_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key, value)
}
// 取出并清空数组
pub fn retrieve_vec_string(key: &str) -> Vec<String> {
retrieve_map_vec_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key)
}
// 获取数组的数量
pub fn get_vec_string_len(key: &str) -> usize {
len_map_vec_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key)
}
// 获取数组的指定索引
pub fn get_vec_string_from_index(key: &str, index: usize) -> Option<String> {
from_index_map_vec_bind_variable!(VARIABLE_VEC_STRING, VARIABLE_VEC_STRING_BIND, key, index)
}
```
#### 如何调用
```rust
fn main() {
let mut key = "u64_key";
println!("{} -> {}", key, has_u64(key));
println!("{} -> {}", key, get_u64_default(key));
println!("{} -> {}", key, get_u64_or(key, 3506615415));
set_u64(key, 50560);
println!("{} -> {}", key, has_u64(key));
println!("{} -> {}", key, get_u64(key).unwrap());
println!("------------------------------------------------------------------------------------");
key="i32";
println!("{} -> {}", key, has_i32(key));
println!("{} -> {}", key, get_i32_default(key));
println!("{} -> {}", key, get_i32_or(key, 350661));
set_i32(key, 50560);
println!("{} -> {}", key, has_i32(key));
println!("{} -> {}", key, get_i32(key).unwrap());
println!("------------------------------------------------------------------------------------");
key="i128";
println!("{} -> {}", key, has_i128(key));
println!("{} -> {}", key, get_i128_default(key));
println!("{} -> {}", key, get_i128_or(key, 3506615415));
set_i128(key, 50560);
println!("{} -> {}", key, has_i128(key));
println!("{} -> {}", key, get_i128(key).unwrap());
println!("------------------------------------------------------------------------------------");
key="bool";
println!("{} -> {}", key, has_bool(key));
println!("{} -> {}", key, get_bool_default(key));
println!("{} -> {}", key, get_bool_or(key, true));
set_bool(key, false);
println!("{} -> {}", key, has_bool(key));
println!("{} -> {}", key, get_bool(key).unwrap());
println!("------------------------------------------------------------------------------------");
key="String";
println!("{} -> {}", key, has_string(key));
println!("{} -> {}", key, get_string_default(key));
println!("{} -> {}", key, get_string_or(key, String::from("没有数据啊")));
set_string(key, String::from("这回有数据了"));
println!("{} -> {}", key, has_string(key));
println!("{} -> {}", key, get_string(key).unwrap());
println!("------------------------------------------------------------------------------------");
key="Vec<String>";
println!("{} -> {}", key, has_vec_string(key));
println!("{} -> {:?}", key, get_vec_string_default(key));
println!("{} -> {:?}", key, get_vec_string_or(key, Vec::from(vec!["这么多年了".to_string(),"有没有好好学过Rust".to_string(),"有没有好好思考".to_string(),"一直都是这么难写的".to_string(),"不要乱讲".to_string()])));
set_vec_string(key, Vec::from(vec!["真的很抱歉".to_string(),"我不知道原来这么难".to_string(),"没有好好学习".to_string(),"写不出这个功能".to_string(),"是我乱讲了".to_string()]) );
println!("{} -> {}", key, has_vec_string(key));
println!("{} -> {:?}", key, get_vec_string(key).unwrap());
println!("{} -> {:?}", key, get_vec_string_len(key));
push_vec_string( key,String::from("sdgsdh"));
println!("{} -> {:?}", key, get_vec_string(key).unwrap());
println!("{} -> {:?}", key, get_vec_string_len(key));
println!("{} -> {:?}", key, get_vec_string_from_index(key,2));
println!("{} -> {:?}", key, retrieve_vec_string(key));
println!("{} -> {:?}", key, get_vec_string(key).unwrap());
println!("------------------------------------------------------------------------------------");
key="Vec<i32>";
println!("{} -> {}", key, has_vec_i32(key));
println!("{} -> {:?}", key, get_vec_i32_default(key));
println!("{} -> {:?}", key, get_vec_i32_or(key, Vec::from(vec!)));
set_vec_i32(key, Vec::from(vec!) );
println!("{} -> {}", key, has_vec_i32(key));
println!("{} -> {:?}", key, get_vec_i32(key).unwrap());
println!("{} -> {:?}", key, get_vec_i32_len(key));
push_vec_i32( key,666);
println!("{} -> {:?}", key, get_vec_i32(key).unwrap());
println!("{} -> {:?}", key, get_vec_i32_len(key));
println!("{} -> {:?}", key, get_vec_i32_from_index(key,2));
println!("{} -> {:?}", key, retrieve_vec_i32(key));
println!("{} -> {:?}", key, get_vec_i32(key).unwrap());
}
```
!(https://cos.kiic.top//202310060132583.png?imageMogr2/quality/90/format/webp) 做个记号,回头研究研究 赞,有心了,跟着学习 厉害厉害,不得不说c++,rust,一个比一个抽象。 DEATHTOUCH 发表于 2023-10-6 11:52
厉害厉害,不得不说c++,rust,一个比一个抽象。
无可奈何最佳搭配是Rust搭CPP,一个内存过于自由一个内存过于严格,如果两者能缝合在一起就是个好语言了 Rust语言是好语言,只是对新手来说难度有点大,生态没建起来,有问题也不知道怎么解决,基本放弃了 给大佬点个赞,请教大佬,用Rust写中大型项目的编程体验如何,一直很好奇,写惯了传统C系代码,看rust的代码总感觉乱乱的 hongyemosuo 发表于 2023-10-7 16:48
给大佬点个赞,请教大佬,用Rust写中大型项目的编程体验如何,一直很好奇,写惯了传统C系代码,看rust的代 ...
其实还好 ,目前几万行的中型项目还是挺好写的 ,不至于找不到修改的地方,编译器非常智能 如果需要一次性改多处引用只需要让主函数出错 其他的路径都会暴露出来,但是难受的是为了实现一个简单的功能你可能需要绕道走好多个地方去实现,并且很容易几天白忙活,比如现在讲的全局变量 大佬为啥不把你写的那一堆函数封装成一个crate呢?这样添加也方便一点,直接cargo add ...就行了。 本帖最后由 kihlh 于 2023-10-12 16:39 编辑
大白痴先生 发表于 2023-10-12 12:43
大佬为啥不把你写的那一堆函数封装成一个crate呢?这样添加也方便一点,直接cargo add ...就行了。
如果要做成包现在还不够完整,例如类型自判断等的这些 还有key记录 自定义默认值变化回调函数 等 我暂时没那个时间
页:
[1]