锘??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美激情在线,亚洲国产日韩欧美在线动漫,国产日韩精品视频一区http://www.shnenglu.com/jinq0123/category/21420.htmlzh-cnWed, 05 Oct 2022 13:26:52 GMTWed, 05 Oct 2022 13:26:52 GMT60Implementation of user data in cursive::Cursivehttp://www.shnenglu.com/jinq0123/archive/2022/10/02/229436.html閲戝簡閲戝簡Sun, 02 Oct 2022 08:38:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/10/02/229436.htmlhttp://www.shnenglu.com/jinq0123/comments/229436.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/10/02/229436.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229436.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229436.htmlImplementation of user data in cursive::Cursive

(Jin Qing's Column, Oct., 2022)

cursive::Cursive can store any user data:

pub struct Cursive { ... // User-provided data. user_data: Box<dyn Any>, } impl Cursive { ... pub fn set_user_data<T: Any>(&mut self, user_data: T) { self.user_data = Box::new(user_data); } pub fn user_data<T: Any>(&mut self) -> Option<&mut T> { self.user_data.downcast_mut() } pub fn take_user_data<T: Any>(&mut self) -> Option<T> { ... } pub fn with_user_data<F, T, R>(&mut self, f: F) -> Option<R> where F: FnOnce(&mut T) -> R, T: Any, { self.user_data().map(f) }

Example:

let mut siv = cursive_core::Cursive::new(); // Start with a simple `Vec<i32>` as user data. siv.set_user_data(vec![1i32, 2, 3]); assert_eq!(siv.user_data::<Vec<i32>>(), Some(&mut vec![1i32, 2, 3])); // Let's mutate the data a bit. siv.with_user_data(|numbers: &mut Vec<i32>| numbers.push(4)); // If mutable reference is not enough, we can take the data by value. let data: Vec<i32> = siv.take_user_data().unwrap(); assert_eq!(data, vec![1i32, 2, 3, 4]); // At this point the user data was removed and is no longer available. assert_eq!(siv.user_data::<Vec<i32>>(), None);


閲戝簡 2022-10-02 16:38 鍙戣〃璇勮
]]>
Rust sometimes needs manual type annotationhttp://www.shnenglu.com/jinq0123/archive/2022/04/29/229301.html閲戝簡閲戝簡Fri, 29 Apr 2022 02:14:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/29/229301.htmlhttp://www.shnenglu.com/jinq0123/comments/229301.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/29/229301.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229301.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229301.htmlRust sometimes needs manual type annotation

(Jin Qing's Column, Apr., 2022)

This code compiles error:

      trait MyCallback: FnMut(&u32) -> () { }
impl<F: FnMut(&u32) -> ()> MyCallback for F { }
fn process_data(mut f: impl MyCallback) -> () {
    f(&0)
}
fn process_data_2(mut f: impl FnMut(&u32) -> ()) -> () {
    f(&0)
}
fn main() {
    // Doesn't compile
    process_data(|_| ());
    // Compiles
    process_data_2(|_| ());
}

    
      expected type `for<'r> FnMut<(&'r u32,)>`
              found type `FnMut<(&u32,)>`

    

Fix:

          process_data(|_: &_| ());

    

See: https://stackoverflow.com/questions/61671460/rust-type-mismatch-resolving-forr-with-closure-trait-alias-argument

Also see: https://github.com/rust-lang/rust/issues/58639

Sometimes, Rust needs a type annotation in closure.



閲戝簡 2022-04-29 10:14 鍙戣〃璇勮
]]>
How to work around rustup-init failurehttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229295.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:09:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229295.htmlhttp://www.shnenglu.com/jinq0123/comments/229295.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229295.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229295.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229295.htmlHow to work around rustup-init failure

(Jin Qing's Column, Mar., 2022)

rustup-init.exe may fail if some anti-virus software is running with realtime protection.

The error message is like this after many retries:

error: could not rename component file from 'C:\.../rust/html' to 'C:\.../rust/html'

See: https://github.com/rust-lang/rustup/issues/1912

And it is not possible to stop the anti-virus for a corporate laptop.

There is a way to workaround this. Here are the steps:

  1. Run rustup-init until it begins to retry renaming
  2. Kill rustup-init when it is retrying
    • rustup will be installed before the failure
    • do not let rustup-init do the cleanup after the final failure
  3. Run rustup update to install all.
  4. Run rustup-init again to setup others.

rustup update will report that rustc was not found:

C:\Users\jinqing01>rustup update
info: syncing channel updates for 'stable-x86_64-pc-windows-msvc'
...
info: removing previous version of component 'rustc'
warning: during uninstall component rustc was not found
...
info: installing component 'rustc'
...  
info: checking for self-updates
  stable-x86_64-pc-windows-msvc updated - rustc 1.59.0 (9d1b2106e 2022-02-23) (from (rustc does not exist))
info: cleaning up downloads & tmp directories

Rerun rustup-init to setup the toolchain:

C:\Users\jinqing01>cargo --version
error: no override and no default toolchain set
C:\Users\jinqing01>d:
D:\>cd tool
D:\Tool>rustup-init.exe
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
...
Rust is installed now. Great!
Press the Enter key to continue.
D:\Tool>cargo --version
cargo 1.59.0 (49d8809dc 2022-02-10)



閲戝簡 2022-04-24 14:09 鍙戣〃璇勮
]]>
Closure as the function parameterhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229294.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:06:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229294.htmlhttp://www.shnenglu.com/jinq0123/comments/229294.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229294.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229294.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229294.htmlClosure as the function parameter

(Jin Qing's Column, Mar., 2022)

It is best to let the function take a closure trait as the parameter instead of a function pointer.

      fn foo(f: fn()) {
    f()
}
fn main() {
    foo(|| println!("hello"));
    let a = 123;
    foo(move || println!("{}", a))
}

    

compiles error:

      error[E0308]: mismatched types
 --> src/main.rs:9:9
  |
9 |     foo(move || println!("{}", a))
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
  |
  = note: expected fn pointer `fn()`
                found closure `[closure@src/main.rs:9:9: 9:34]`
note: closures can only be coerced to `fn` types if they do not capture any variables
 --> src/main.rs:9:32
  |
9 |     foo(move || println!("{}", a))
  |                                ^ `a` captured here
For more information about this error, try `rustc --explain E0308`.

    

https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html

Function pointers implement all three of the closure traits (Fn, FnMut, and FnOnce), so you can always pass a function pointer as an argument for a function that expects a closure. It’s best to write functions using a generic type and one of the closure traits so your functions can accept either functions or closures.



閲戝簡 2022-04-24 14:06 鍙戣〃璇勮
]]>
Deadlock detection must not run as tokio taskhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229293.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:04:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229293.htmlhttp://www.shnenglu.com/jinq0123/comments/229293.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229293.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229293.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229293.htmldeadlock detection must not run as tokio task

(Jin Qing's Column, Feb., 2022)

parking_lot has an experimental feature: deadlock_detection.

See: https://amanieu.github.io/parking_lot/parking_lot/deadlock/index.html

use std::thread;
use std::time::Duration;
use parking_lot::deadlock;
// Create a background thread which checks for deadlocks every 10s
thread::spawn(move || {
loop {
thread::sleep(Duration::from_secs(10));
let deadlocks = deadlock::check_deadlock();
if deadlocks.is_empty() {
continue;
}
println!("{} deadlocks detected", deadlocks.len());
for (i, threads) in deadlocks.iter().enumerate() {
println!("Deadlock #{}", i);
for t in threads {
println!("Thread Id {:#?}", t.thread_id());
println!("{:#?}", t.backtrace());
}
}
}
});

The output is like this:

1 deadlocks detected
Deadlock #0
Thread Id 16072
0: 0x7ff985cb659d - backtrace::backtrace::dbghelp::trace
at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.63\src\backtrace\dbghelp.rs:98
...
13: 0x7ff985ae92f3 - lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate>::read<parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate>
at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\lock_api-0.4.6\src\rwlock.rs:448
14: 0x7ff985aeadf3 - cgc::scene::SceneData::check_body_collide
at E:\gitlab\yserver\gc\src\scene.rs:99
...
81: 0x7ff9f29b7034 - BaseThreadInitThunk
82: 0x7ff9f2b02651 - RtlUserThreadStart

But the deadlock detection thread can not be changed to a tokio task, because if deadlock happens, all tasks may be blocked, including the deadlock detection, causing no deadlock error output.

In the following example, if the number of the deadlock tasks is larger than the thread number of tokio runtime, all tasks will be blocked.

use std::{thread, time::Duration};
use parking_lot::RwLock;
use tokio::time;
#[tokio::main]
async fn main() {
tokio::spawn(async move {
for i in 0..999999 {
println!("{}", i);
time::sleep(Duration::from_secs(1)).await;
}
});
const MAX: i32 = 100;
for _ in 0..MAX {
tokio::spawn(async move {
{
// DEADLOCK!
let a = RwLock::new(());
let _g1 = a.write();
let _g2 = a.write();
}
time::sleep(Duration::from_secs(9999)).await;
});
}
println!("Hello, world!");
thread::sleep(Duration::from_secs(10));
}

The output is:

0
Hello, world!
_

If no deadlock, or the number of deadlock tasks is small, the output should be:

0
Hello, world!
1
2
3
...



閲戝簡 2022-04-24 14:04 鍙戣〃璇勮
]]>
Tracing usagehttp://www.shnenglu.com/jinq0123/archive/2022/01/02/218556.html閲戝簡閲戝簡Sun, 02 Jan 2022 04:38:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/01/02/218556.htmlhttp://www.shnenglu.com/jinq0123/comments/218556.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/01/02/218556.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/218556.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/218556.htmlTracing usage

(Jin Qing's Column, Jan., 2022)

Tracing is Rust log crate: https://github.com/tokio-rs/tracing

This example code outputs log to stdout and a log file, using a log filter config file, which can be automatically reloaded on change.

https://gitee.com/jinq0123/tracing-example

Dependencies

Add these dependencies to Cargo.toml:

      [dependencies]
anyhow = "1.0.52"
hotwatch = "0.4.6"
tracing = "0.1.29"
tracing-appender = "0.2.0"
tracing-subscriber = { version = "0.3.5", features = [ "env-filter", "json" ] }

    

main.rs

      mod log;
use anyhow::Result;
use std::{thread, time::Duration};
use tracing::info;
fn main() -> Result<()> {
    let _guard = log::init("./log", "example.log", "config/log_filter.txt")?;
    for i in 0..999 {
        info!(i, "Hello, world!");
        thread::sleep(Duration::from_secs(1));
    }
    Ok(())
}

    

log.rs

      //! Init log.
//!
use anyhow::{anyhow, Context as _, Result};
use hotwatch::{Event, Hotwatch};
use std::fs;
use std::path::Path;
use tracing::{debug, warn, Subscriber};
use tracing_appender::{non_blocking::WorkerGuard, rolling};
use tracing_subscriber::{fmt, layer::SubscriberExt, reload::Handle, EnvFilter};
/// Inits log.
/// Returns a WorkerGuard to ensure buffered logs are flushed,
///  and a Hotwatch to watch the log filter file.
pub fn init(
    directory: impl AsRef<Path>,
    file_name_prefix: impl AsRef<Path>,
    log_filter_file: impl AsRef<Path>,
) -> Result<(WorkerGuard, Hotwatch)> {
    let file_appender = rolling::daily(directory, file_name_prefix);
    let (non_blocking, worker_guard) = tracing_appender::non_blocking(file_appender);
    let file_layer = fmt::Layer::default()
        .with_writer(non_blocking)
        .json()
        .flatten_event(true)
        .with_ansi(false);
    let builder = tracing_subscriber::fmt()
        .pretty()
        .with_env_filter(EnvFilter::from_default_env())
        .with_filter_reloading();
    let handle = builder.reload_handle();
    let subscriber = builder.finish();
    let subscriber = subscriber.with(file_layer);
    tracing::subscriber::set_global_default(subscriber).context("set global default subscriber")?;
    reload_filter(handle.clone(), log_filter_file.as_ref());
    let log_filter_path_buf = log_filter_file.as_ref().to_path_buf();
    let mut hotwatch = Hotwatch::new().context("hotwatch failed to initialize!")?;
    hotwatch
        .watch(log_filter_file.as_ref(), move |event: Event| {
            debug!("log filter file event: {:?}", event);
            if let Event::Write(_) = event {
                reload_filter(handle.clone(), log_filter_path_buf.clone());
            }
        })
        .with_context(|| format!("failed to watch file: {:?}", log_filter_file.as_ref()))?;
    Ok((worker_guard, hotwatch))
}
fn reload_filter<S: Subscriber + 'static>(
    handle: Handle<EnvFilter, S>,
    log_filter_file: impl AsRef<Path>,
) {
    let res = try_reload_filter(handle, log_filter_file);
    match res {
        Ok(_) => debug!("reload log filter OK"),
        Err(e) => warn!("reload log filter error: {:?}", e),
    }
}
fn try_reload_filter<S: Subscriber + 'static>(
    handle: Handle<EnvFilter, S>,
    log_filter_file: impl AsRef<Path>,
) -> Result<()> {
    let contents = fs::read_to_string(log_filter_file.as_ref()).with_context(|| {
        format!(
            "something went wrong reading the file: {:?}",
            log_filter_file.as_ref()
        )
    })?;
    let contents = contents.trim();
    debug!("reload log filter: {:?}", contents);
    let new_filter = contents
        .parse::<EnvFilter>()
        .map_err(|e| anyhow!(e))
        .context("failed to parse env filter")?;
    handle.reload(new_filter).context("handle reload error")
}

    

log_filter.txt

log_filter.txt is the configure file for log. The change of this file will trigger the reload.

The log filter file must exist, otherwise it will be error:

      Error: failed to watch file: "config/log_filter.txt"
Caused by:
    緋葷粺鎵句笉鍒版寚瀹氱殑璺緞銆?(os error 3)

    

The content of log_filter.txt is a single line of filter string. A filter string consists of one or more comma-separated directives. The directive syntax is similar to RUST_LOG env val of env_logger’s.

      target[span{field=value}]=level

    

See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html

Example

  • tracing_example enables logs that:
    • target is modules of tracing_example*
  • info will enable logs that:
    • level is info
  • tracing_ex=info enables logs that:
    • target is modules of tracing_ex*
    • level is info or above
  • info,tracing_ex=debug enables logs that:
    • level is info or above
    • or target is tracing_ex* and level is debug
  • [foo]=trace enables logs that:
    • within the span foo
    • level is trace or above
  • [span_b{name=\"bob\"}] enables logs that:
    • have any target,
    • are inside a span named span_b,
    • which has a field named name with value bob,
    • at any level.

Note: span filter directive will keep effective until it exits the span.



閲戝簡 2022-01-02 12:38 鍙戣〃璇勮
]]>
Box<dyn Trait> doesn't implement the traithttp://www.shnenglu.com/jinq0123/archive/2021/12/21/217886.html閲戝簡閲戝簡Tue, 21 Dec 2021 07:09:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/12/21/217886.htmlhttp://www.shnenglu.com/jinq0123/comments/217886.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/12/21/217886.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217886.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217886.html From: 

By default a Box<dyn Trait> doesn't implement the trait of the object it contains. This means that trying to construct PeopleZoo<Box<dyn Person>> won't work out of the box and will give a type error.

Because of this, it's good practice to give a default implementation of your trait for it's boxed counterpart. This can be done by calling as_ref or as_mut on the Box and calling the references relevant method.

For just a small bit of effort you can help a bunch of people that may consume your struct.

trait Person { fn say_hello(&self); } impl Person for Box<dyn Person> { fn say_hello(&self) { self.as_ref().say_hello() } }

 

struct PeopleZoo<P: Person> {
    people: Vec<P>,
}
fn main() { let mut zoo: PeopleZoo<Box<dyn Person>> = PeopleZoo { people: vec![] }; }


閲戝簡 2021-12-21 15:09 鍙戣〃璇勮
]]>
寤鴻鏃ュ織 slog 鏀規崲 tracinghttp://www.shnenglu.com/jinq0123/archive/2021/11/24/217865.html閲戝簡閲戝簡Wed, 24 Nov 2021 10:18:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/24/217865.htmlhttp://www.shnenglu.com/jinq0123/comments/217865.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/24/217865.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217865.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217865.html寤鴻鏃ュ織 slog 鏀規崲 tracing

(閲戝簡鐨勪笓鏍?2021.11)

  • slog 涓嶆槸绔嬪嵆鍐欑洏錛屾渶鍚庣殑鍑犺鏃ュ織浼氫涪澶?/p>

    • tracing 涓嶄細涓㈡棩蹇?/li>
  • slog 涓嶆敮鎸佽繍琛屼腑鍔ㄦ佹洿鏀規棩蹇楃瓑綰?/p>

  • slog 涓嶆敮鎸佷笉鍚屽寘璁劇疆涓嶅悓鏃ュ織絳夌駭

    • tracing 鍙崟鐙墦寮鏌愪釜妯″潡鐨勬棩蹇?/li>
  • 鍙戠幇涓嬈?slog panic: panicked at 'slog::Fuse Drain: Fatal(Custom { kind: BrokenPipe, error: "The logger thread terminated" })'

    • 鎼滃埌鐩稿悓閿欒錛?a target='_blank' class='url'>https://github.com/mimblewimble/grin/issues/946

      • 鍒漢鐨勮В鍐蟲柟娉曟槸: 涓嶇敤slog浜?/li>
  • slog 涓婚〉10鏈堟坊鍔犳帹鑽愪嬌鐢?tracing

  • slog 鎸夌嚎紼嬩繚瀛樹笂涓嬫枃錛宼racing 鎸夊崗紼嬩繚瀛樹笂涓嬫枃

  • tracing github star 1.9K > slog 1.2K

  • tracing crates 涓嬭澆 21M > sloggers 0.4M, slog-scope 2.6M, slog-stdlog 1.9M

  • tracing vs slog: https://www.reddit.com/r/rust/comments/kdo29n/slog_vs_tracing_which_one_do_you_prefer/

  • Rust compiler 2020騫村凡鏀圭敤 tracing錛?a target='_blank' class='url'>https://github.com/rust-lang/rust/pull/74726

  • tracing 鏇村ソ鐢?/p>

    • 鏂囨。鍙婄ず渚嬫洿鍏?/li>
    • 鏀寔搴撴洿澶?/li>


閲戝簡 2021-11-24 18:18 鍙戣〃璇勮
]]>
Named parameters in Rusthttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217862.html閲戝簡閲戝簡Thu, 18 Nov 2021 05:14:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217862.htmlhttp://www.shnenglu.com/jinq0123/comments/217862.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217862.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217862.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217862.htmlNamed parameters in Rust

(Jin Qing's Column, Nov. 18, 2021)

There is no "named function parameters" in Rust, but there is an idiom for this case. If a function needs many parameters, we can define a type with all these parameters as fields, and implement Default trait for this type. Then we can input this type as the function parameter, with some of the fields specified and others using default.

foo(Config {
    a: 123,
    b: bool,
    ...Default::default(),
});


閲戝簡 2021-11-18 13:14 鍙戣〃璇勮
]]>
Rust traits act as generic constraintshttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217861.html閲戝簡閲戝簡Thu, 18 Nov 2021 04:51:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217861.htmlhttp://www.shnenglu.com/jinq0123/comments/217861.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217861.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217861.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217861.htmlRust traits act as generic constraints

(Jin Qing's Column, Nov. 18, 2021)

Rust traits are different from interfaces of C++/Java/Go.

See: https://stevedonovan.github.io/rustifications/2018/09/08/common-rust-traits.html

Rust traits are mechanism for adding behavior to types.

Traits have 2 modes. One is interface as Java.

Another is generic constraint. Generic functions are defined over types that implemented specific traits.

The "complie-time duck typing" in C++ templates is avoided in Rust. Rust will reject a type with quack() method as a Duck type. We must pass a type which implements Duck trait. But in Go, a type with quack() method is sufficient to be used as a Duck interface.

 



閲戝簡 2021-11-18 12:51 鍙戣〃璇勮
]]>
GLIBC_2.29 not foundhttp://www.shnenglu.com/jinq0123/archive/2021/11/05/217853.html閲戝簡閲戝簡Fri, 05 Nov 2021 01:42:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/05/217853.htmlhttp://www.shnenglu.com/jinq0123/comments/217853.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/05/217853.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217853.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217853.htmlGLIBC_2.29 not found

(Jin Qing's Column, Nov. 4, 2021)

My Rust program failed when running in docker:

root@a26b49c91efb:/myapp# ldd libmyapp_py.so
./libmyapp_py.so: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./libmyapp_py.so)

The problem is because I build in "rust:1.56", and run in "debian:buster-slim" which is quite old. Run dpkg -l libc-bin shows the libc version is 2.28:

C:\Users\jinqing01>docker run debian:buster-slim dpkg -l libc-bin
Unable to find image 'debian:buster-slim' locally
buster-slim: Pulling from library/debian
b380bbd43752: Already exists
Digest: sha256:544c93597c784cf68dbe492ef35c00de7f4f6a990955c7144a40b20d86a3475f
Status: Downloaded newer image for debian:buster-slim
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  libc-bin       2.28-10      amd64        GNU C Library: Binaries

Using the latest "debian:bookworm-slim" solved the problem.

Dockerfile:

FROM rust:1.56 as chef
RUN cargo install cargo-chef
WORKDIR /myapp
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /myapp/recipe.json recipe.json
# Build dependencies
RUN cargo chef cook --release --recipe-path recipe.json
# Build application
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim AS runtime
WORKDIR /myapp
RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/*
RUN pip3 install protobuf
COPY --from=builder /myapp/target/release/*.so /myapp/
COPY --from=builder /myapp/target/release/myapp /myapp/
COPY --from=builder /myapp/tests /myapp/tests
CMD ["myapp"]


閲戝簡 2021-11-05 09:42 鍙戣〃璇勮
]]>
Advice for Rust library writers about Errorhttp://www.shnenglu.com/jinq0123/archive/2021/09/02/217805.html閲戝簡閲戝簡Thu, 02 Sep 2021 03:24:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/09/02/217805.htmlhttp://www.shnenglu.com/jinq0123/comments/217805.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/09/02/217805.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217805.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217805.htmlAdvice for library writers

Idioms for Rust libraries are still forming, but if your library needs to report custom errors, then you should probably define your own error type. It’s up to you whether or not to expose its representation (like ErrorKind) or keep it hidden (like ParseIntError). Regardless of how you do it, it’s usually good practice to at least provide some information about the error beyond just its String representation. But certainly, this will vary depending on use cases.

At a minimum, you should probably implement the Error trait. This will give users of your library some minimum flexibility for composing errors. Implementing the Error trait also means that users are guaranteed the ability to obtain a string representation of an error (because it requires impls for both fmt::Debug and fmt::Display).

Beyond that, it can also be useful to provide implementations of From on your error types. This allows you (the library author) and your users to compose more detailed errors. For example, csv::Error provides From impls for both io::Error and byteorder::Error.

Finally, depending on your tastes, you may also want to define a Result type alias, particularly if your library defines a single error type. This is used in the standard library for io::Result and fmt::Result.

From: Error Handling in Rust - Andrew Gallant's Blog (burntsushi.net)



閲戝簡 2021-09-02 11:24 鍙戣〃璇勮
]]>
How to show the first few errors of rustchttp://www.shnenglu.com/jinq0123/archive/2021/09/01/217804.html閲戝簡閲戝簡Wed, 01 Sep 2021 02:55:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/09/01/217804.htmlhttp://www.shnenglu.com/jinq0123/comments/217804.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/09/01/217804.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217804.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217804.html
# How to show the first few errors of rustc

(Jin Qing's Column, Sep. 1, 2021)

When using VS Code to develop Rust, "cargo check" output maybe thousands of lines.
Use "cargo check --color=always 2>&1 | head -n100" to limit the output.

1. Change powershell terminal to cmd, because powershell fails to use pipe
    * Terminal -> New Terminal to open a terminal
    * Open the dropdown list by click the down arrow of "+" on the top-left of terminal
    * Select "Command Prompt"
2. Type and run command: `cargo test 2>&1 --color always | "d:\Program Files\Git\usr\bin\head.exe" -n100`
    * You should change the path of head.exe


閲戝簡 2021-09-01 10:55 鍙戣〃璇勮
]]>
&'a mut self is restrictivehttp://www.shnenglu.com/jinq0123/archive/2021/08/25/217794.html閲戝簡閲戝簡Wed, 25 Aug 2021 05:32:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/08/25/217794.htmlhttp://www.shnenglu.com/jinq0123/comments/217794.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/08/25/217794.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217794.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217794.html
# &'a mut self is restrictive

From https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md#5-if-it-compiles-then-my-lifetime-annotations-are-correct

```
#[derive(Debug)]
struct NumRef<'a>(&'a i32);

impl<'a> NumRef<'a> {
    // my struct is generic over 'a so that means I need to annotate
    // my self parameters with 'a too, right? (answer: no, not right)
    fn some_method(&'a mut self) {}
}

fn main() {
    let mut num_ref = NumRef(&5);
    num_ref.some_method(); // mutably borrows num_ref for the rest of its lifetime
    num_ref.some_method(); // 鉂?/div>
    println!("{:?}", num_ref); // 鉂?/div>
}
```

If we have some struct generic over 'a we almost never want to write a method with a &'a mut self receiver. 
What we're communicating to Rust is "this method will mutably borrow the struct for the entirety of the struct's lifetime". 
In practice this means Rust's borrow checker will only allow at most one call to some_method 
before the struct becomes permanently mutably borrowed and thus unusable. 
The use-cases for this are extremely rare but the code above is very easy for confused beginners to write and it compiles. 
The fix is to not add unnecessary explicit lifetime annotations and let Rust's lifetime elision rules handle it:

```
#[derive(Debug)]
struct NumRef<'a>(&'a i32);

impl<'a> NumRef<'a> {
    // no more 'a on mut self
    fn some_method(&mut self) {}

    // above line desugars to
    fn some_method_desugared<'b>(&'b mut self){}
}

fn main() {
    let mut num_ref = NumRef(&5);
    num_ref.some_method();
    num_ref.some_method(); // 鉁?/div>
    println!("{:?}", num_ref); // 鉁?/div>
}
```


閲戝簡 2021-08-25 13:32 鍙戣〃璇勮
]]>Rust callback idiomhttp://www.shnenglu.com/jinq0123/archive/2021/08/24/217793.html閲戝簡閲戝簡Tue, 24 Aug 2021 02:19:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/08/24/217793.htmlhttp://www.shnenglu.com/jinq0123/comments/217793.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/08/24/217793.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217793.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217793.html
# Rust callback idiom

Code is from: https://stackoverflow.com/questions/41081240/idiomatic-callbacks-in-rust
and
https://morestina.net/blog/793/closure-lifetimes-in-rust

```
struct Processor<'a> {
    callback: Box<dyn FnMut() + 'a>,
}

impl<'a> Processor<'a> {
    fn new() -> Processor<'a> {
        Processor {
            callback: Box::new(|| ()),
        }
    }

    fn set_callback(&mut self, c: impl FnMut() + 'a) {
        self.callback = Box::new(c);
    }

    fn process_events(&mut self) {
        (self.callback)();
    }
}

fn simple_callback() {
    println!("hello");
}

fn main() {
    let _ = Processor::new();
    
    let mut p = Processor {
        callback: Box::new(simple_callback),
    };
    p.process_events();
    let s = "world!".to_string();
    let callback2 = move || println!("hello {}", s);
    p.set_callback(callback2);
    p.process_events();
}
```

Note:
* "impl FnMut()" can only used in function declaration, not in struct declaration.
* dyn FnMut() is unsized, so it must be stored in Box
* set_callback(&mut self, c: impl FnMut()) need a lifetime for c to tell compiler that c outlives structure
    + rustc suggests `impl FnMut() + 'static`, but that is too restrictive
        - In most cases, we do not have a static lifetimed callback
* FnMut() is more restrictive than FnOnce(), but FnOnce() can only be called once
* set_callback(...) is a template method, because each closure has a different type


閲戝簡 2021-08-24 10:19 鍙戣〃璇勮
]]>Rust variable rebinding for closurehttp://www.shnenglu.com/jinq0123/archive/2021/08/22/217787.html閲戝簡閲戝簡Sun, 22 Aug 2021 09:25:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/08/22/217787.htmlhttp://www.shnenglu.com/jinq0123/comments/217787.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/08/22/217787.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217787.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217787.html
From: https://rust-unofficial.github.io/patterns/idioms/pass-var-to-closure.html

Rust closure captures variables by reference by default.
You can use "move" keyword to change to move variables.
In most cases, some variables are moved, and some are referenced.
We can rebind variables in a separate scope before move to the closure.

```
use std::rc::Rc;

let num1 = Rc::new(1);
let num2 = Rc::new(2);
let num3 = Rc::new(3);
let closure = {
    // `num1` is moved
    let num2 = num2.clone();  // `num2` is cloned
    let num3 = num3.as_ref();  // `num3` is borrowed
    move || {
        *num1 + *num2 + *num3;
    }
};
```

Or we can use additional variables to move in the same scope:
```
let num2_clone = num2.clone();
let num3_ref = num3.as_ref();
let closure = move || {
    *num1 + *num2_clone + *num3_ref
}
```

Using separate scope can reuse the variable name, which make the closure body clearer,
but need additional indent.

閲戝簡 2021-08-22 17:25 鍙戣〃璇勮
]]>
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              国色天香一区二区| 亚洲精品日日夜夜| 久久狠狠亚洲综合| 欧美影院在线播放| 狠狠爱综合网| 亚洲电影欧美电影有声小说| 免费久久99精品国产自在现线| 永久555www成人免费| 农村妇女精品| 欧美日韩免费观看一区三区| 亚洲天堂av在线免费观看| 在线中文字幕日韩| 国内自拍一区| 亚洲日本中文| 国产日韩精品久久久| 欧美v亚洲v综合ⅴ国产v| 欧美激情1区2区| 久久精品盗摄| 欧美激情视频在线播放 | 亚洲第一综合天堂另类专| 欧美成人免费在线观看| 欧美日本在线| 久久久99国产精品免费| 欧美超级免费视 在线| 亚洲一区二区三区777| 久久精品女人的天堂av| 一区二区三区免费在线观看| 欧美专区福利在线| 99热这里只有成人精品国产| 欧美一级视频精品观看| 9人人澡人人爽人人精品| 久久av在线看| 亚洲免费在线看| 你懂的国产精品| 久久se精品一区精品二区| 欧美黄色一区| 欧美不卡视频| 国产欧美一区二区在线观看| 91久久国产综合久久91精品网站| 国产日韩视频| 中国女人久久久| 亚洲九九精品| 老司机精品久久| 久久久久这里只有精品| 国产精品女同互慰在线看| 亚洲国产精品久久久久秋霞蜜臀| 国产午夜亚洲精品理论片色戒| 日韩亚洲视频在线| 亚洲国产一区二区在线| 久久精品在线播放| 欧美在线免费视频| 国产精品日日摸夜夜添夜夜av| 亚洲国产精品尤物yw在线观看| 精品51国产黑色丝袜高跟鞋| 亚洲欧美一区二区激情| 亚洲中午字幕| 国产精品久久久久久久久久尿 | 亚洲一区日韩在线| 夜夜夜精品看看| 欧美精品福利在线| 欧美大尺度在线| 亚洲国产经典视频| 蜜桃久久av一区| 欧美粗暴jizz性欧美20| 亚洲国产一区在线观看| 美女精品自拍一二三四| 亚洲高清av| 一本久道久久综合狠狠爱| 欧美寡妇偷汉性猛交| 亚洲激情成人在线| 99国产精品久久久| 欧美日韩亚洲91| 中文av一区特黄| 午夜精品一区二区在线观看| 国产精品视频不卡| 欧美一区二区成人| 美女主播精品视频一二三四| 亚洲福利电影| 欧美片在线观看| 亚洲网在线观看| 欧美在线观看视频| 伊人成年综合电影网| 欧美成年人视频网站欧美| 亚洲激情一区二区| 午夜精品成人在线| 精品9999| 欧美日韩国产三级| 亚洲欧美另类中文字幕| 老妇喷水一区二区三区| 999在线观看精品免费不卡网站| 欧美色欧美亚洲高清在线视频| 99视频在线观看一区三区| 久久精品视频在线| 亚洲精品乱码久久久久久| 欧美日韩日本网| 欧美在线观看天堂一区二区三区 | 日韩一级在线观看| 国产精品男女猛烈高潮激情| 久久精品视频在线观看| 亚洲高清不卡av| 欧美一级电影久久| 亚洲激情在线播放| 国产精品午夜国产小视频| 卡通动漫国产精品| 亚洲免费网址| 亚洲国产精品一区在线观看不卡| 午夜久久黄色| 亚洲乱码国产乱码精品精可以看| 国产精品欧美经典| 欧美激情a∨在线视频播放| 亚洲一区免费网站| 亚洲国产视频直播| 久久婷婷国产综合国色天香| 亚洲一区日韩在线| 亚洲人www| 怡红院精品视频| 国产日韩在线播放| 欧美日韩1区2区| 噜噜噜噜噜久久久久久91| 亚洲一区免费| 夜夜夜久久久| 亚洲人成人一区二区三区| 久久综合久久美利坚合众国| 销魂美女一区二区三区视频在线| 亚洲精选中文字幕| 亚洲精品1区| 在线看视频不卡| 黑人巨大精品欧美黑白配亚洲| 国产精品第13页| 欧美三级网页| 欧美午夜视频在线观看| 欧美日韩精品一区二区在线播放| 久久米奇亚洲| 久久亚洲午夜电影| 久久久免费精品视频| 久久精品免费观看| 欧美在线电影| 久久精品人人做人人综合| 欧美一级久久| 午夜欧美大尺度福利影院在线看| 亚洲一区二区在线播放| 亚洲综合欧美日韩| 亚洲一区制服诱惑| 午夜精品影院| 久久精品国产第一区二区三区| 欧美一级电影久久| 久久精品最新地址| 久久琪琪电影院| 欧美成人dvd在线视频| 欧美激情一区二区三级高清视频| 欧美gay视频激情| 欧美欧美全黄| 国产精品第一区| 国产精品一区二区欧美| 国产一区白浆| 亚洲国产一区二区三区高清| 亚洲人成人一区二区在线观看| 日韩视频一区二区| 亚洲欧美日韩综合国产aⅴ| 亚洲欧美日韩国产一区| 久久国产精品一区二区| 久久中文久久字幕| 亚洲国产精品激情在线观看| 亚洲精品视频啊美女在线直播| 一区二区三区高清在线| 欧美一区二区三区在线免费观看| 久久九九99| 欧美日本一区二区视频在线观看 | 久久久久久久性| 欧美精品亚洲精品| 国产精品美女www爽爽爽视频| 国产一区二区三区四区hd| 亚洲国产综合91精品麻豆| 国产精品99久久久久久www| 久久国内精品视频| 亚洲福利免费| 小黄鸭视频精品导航| 欧美福利一区二区| 国产欧美日韩精品a在线观看| 亚洲高清在线视频| 亚洲综合视频在线| 欧美搞黄网站| 午夜精品久久久久久99热软件| 久久久综合激的五月天| 国产精品电影网站| 亚洲高清免费在线| 欧美在线短视频| 亚洲精品无人区| 久久久久网址| 国产女人18毛片水18精品| 亚洲乱码国产乱码精品精可以看 | 最新国产の精品合集bt伙计| 亚洲图片自拍偷拍| 欧美va亚洲va日韩∨a综合色| 欧美午夜精品一区| 亚洲精品一区二区三区不| 久久久久久久综合狠狠综合| 99视频超级精品| 欧美成人精品在线观看| 黄色成人av|