【Rust】グローバル(static)で変更可能なベクタ

クラスの外部から静的メンバ変数を定義するには「クラス名+”::”+静的メンバ変数名」という名前のグローバル変数を定義する。

static data: &str = "this is static variable";

fn func1(){
    println!("func1: {:?}", data);
}

fn func2(){
    println!("func2: {:?}", data);
}

fn main(){
    
    func1();
    func2();
    println!("main: {:?}", data);
}

$ ./main
func1: “this is static variable”
func2: “this is static variable”
main: “this is static variable”
staticな変数を宣言することはできるが、mutableにできない。

### once_cell
once_cellを使用すると、mutableなstaticを作成できる。

use once_cell::sync::Lazy;
use std::sync::Mutex;

static ARRAY: Lazy<Mutex<Vec<u8>>> = Lazy::new(|| Mutex::new(vec![]));

fn do_a_call(){
    ARRAY.lock().unwrap().push(1);
}

fn main() {
    do_a_call();
    do_a_call();
    do_a_call();

    println!("called {}", ARRAY.lock().unwrap().len());
}

vectorの型をu8ではなく構造体にして、一定数以上になったら関数を実行するように編集する

use once_cell::sync::Lazy;
use std::sync::Mutex;

struct Transaction {
    x: String,
    y: String,
    z: u32,
}

static Pool: Lazy<Mutex<Vec<Transaction>>> = Lazy::new(|| Mutex::new(vec![]));

fn make_block (){
    println!("blockを作成しました。");
    Pool.lock().unwrap().clear();

}

fn do_a_call(){
    let t = Transaction { x: "A".to_string(), y: "B".to_string(), z: 10};
    if Pool.lock().unwrap().len() > 4 {
        make_block();
    }
    Pool.lock().unwrap().push(t);
}

fn main() {
    do_a_call();
    do_a_call();
    do_a_call();
    do_a_call();
    do_a_call();
    do_a_call();
    do_a_call();

    println!("called {}", Pool.lock().unwrap().len());
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s
Running `target/debug/my_web_app`
blockを作成しました。
called 2

なるほど、やりたいことはできました。これをPostされたトランザクションに対して、トランザクションプールに入れるように実装します。

static Pool: Lazy<Mutex<Vec<SignedTransaction>>> = Lazy::new(|| Mutex::new(vec![]));

fn make_block (){
    println!("blockを作成しました。");
    Pool.lock().unwrap().clear();
}

#[post("/handshake")]
async fn handshake(req_body: String)-> impl Responder {
    let req : SignedTransaction = serde_json::from_str(&req_body).unwrap();
    Pool.lock().unwrap().push(req.clone());
    if Pool.lock().unwrap().len() > 1 {
        make_block();
    }
    println!("{}", req.signature);
    HttpResponse::Ok().body(req_body)

}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.94s
Running `target/debug/hoge`
8000E340A55A517D0F27F3A63FBE39ED576BA491DFAC89B44654AB147EC66B206B054BAAF53E318EB2721DC892B4736630F400547989AE9F7C069034ECB4DF98
blockを作成しました。
8000E340A55A517D

おおおおおおお、イイネ!