锘??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧美国产毛片在线,国产精品亚发布,国内精品视频在线播放http://m.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://m.shnenglu.com/jinq0123/archive/2022/10/02/229436.html閲戝簡閲戝簡Sun, 02 Oct 2022 08:38:00 GMThttp://m.shnenglu.com/jinq0123/archive/2022/10/02/229436.htmlhttp://m.shnenglu.com/jinq0123/comments/229436.htmlhttp://m.shnenglu.com/jinq0123/archive/2022/10/02/229436.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/229436.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2022/04/29/229301.html閲戝簡閲戝簡Fri, 29 Apr 2022 02:14:00 GMThttp://m.shnenglu.com/jinq0123/archive/2022/04/29/229301.htmlhttp://m.shnenglu.com/jinq0123/comments/229301.htmlhttp://m.shnenglu.com/jinq0123/archive/2022/04/29/229301.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/229301.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2022/04/24/229295.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:09:00 GMThttp://m.shnenglu.com/jinq0123/archive/2022/04/24/229295.htmlhttp://m.shnenglu.com/jinq0123/comments/229295.htmlhttp://m.shnenglu.com/jinq0123/archive/2022/04/24/229295.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/229295.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2022/04/24/229294.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:06:00 GMThttp://m.shnenglu.com/jinq0123/archive/2022/04/24/229294.htmlhttp://m.shnenglu.com/jinq0123/comments/229294.htmlhttp://m.shnenglu.com/jinq0123/archive/2022/04/24/229294.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/229294.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2022/04/24/229293.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:04:00 GMThttp://m.shnenglu.com/jinq0123/archive/2022/04/24/229293.htmlhttp://m.shnenglu.com/jinq0123/comments/229293.htmlhttp://m.shnenglu.com/jinq0123/archive/2022/04/24/229293.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/229293.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2022/01/02/218556.html閲戝簡閲戝簡Sun, 02 Jan 2022 04:38:00 GMThttp://m.shnenglu.com/jinq0123/archive/2022/01/02/218556.htmlhttp://m.shnenglu.com/jinq0123/comments/218556.htmlhttp://m.shnenglu.com/jinq0123/archive/2022/01/02/218556.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/218556.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/12/21/217886.html閲戝簡閲戝簡Tue, 21 Dec 2021 07:09:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/12/21/217886.htmlhttp://m.shnenglu.com/jinq0123/comments/217886.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/12/21/217886.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217886.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/11/24/217865.html閲戝簡閲戝簡Wed, 24 Nov 2021 10:18:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/11/24/217865.htmlhttp://m.shnenglu.com/jinq0123/comments/217865.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/11/24/217865.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217865.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/11/18/217862.html閲戝簡閲戝簡Thu, 18 Nov 2021 05:14:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/11/18/217862.htmlhttp://m.shnenglu.com/jinq0123/comments/217862.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/11/18/217862.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217862.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/11/18/217861.html閲戝簡閲戝簡Thu, 18 Nov 2021 04:51:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/11/18/217861.htmlhttp://m.shnenglu.com/jinq0123/comments/217861.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/11/18/217861.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217861.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/11/05/217853.html閲戝簡閲戝簡Fri, 05 Nov 2021 01:42:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/11/05/217853.htmlhttp://m.shnenglu.com/jinq0123/comments/217853.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/11/05/217853.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217853.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/09/02/217805.html閲戝簡閲戝簡Thu, 02 Sep 2021 03:24:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/09/02/217805.htmlhttp://m.shnenglu.com/jinq0123/comments/217805.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/09/02/217805.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217805.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/09/01/217804.html閲戝簡閲戝簡Wed, 01 Sep 2021 02:55:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/09/01/217804.htmlhttp://m.shnenglu.com/jinq0123/comments/217804.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/09/01/217804.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217804.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/08/25/217794.html閲戝簡閲戝簡Wed, 25 Aug 2021 05:32:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/08/25/217794.htmlhttp://m.shnenglu.com/jinq0123/comments/217794.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/08/25/217794.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217794.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/08/24/217793.html閲戝簡閲戝簡Tue, 24 Aug 2021 02:19:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/08/24/217793.htmlhttp://m.shnenglu.com/jinq0123/comments/217793.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/08/24/217793.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217793.htmlhttp://m.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://m.shnenglu.com/jinq0123/archive/2021/08/22/217787.html閲戝簡閲戝簡Sun, 22 Aug 2021 09:25:00 GMThttp://m.shnenglu.com/jinq0123/archive/2021/08/22/217787.htmlhttp://m.shnenglu.com/jinq0123/comments/217787.htmlhttp://m.shnenglu.com/jinq0123/archive/2021/08/22/217787.html#Feedback0http://m.shnenglu.com/jinq0123/comments/commentRss/217787.htmlhttp://m.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>
              久久亚洲综合色一区二区三区| 久久久久久自在自线| 欧美一级精品大片| 蜜桃av综合| 亚洲自拍偷拍福利| 欧美韩日高清| 国内成人精品视频| 欧美激情91| 亚洲大胆av| 国产一区自拍视频| 亚洲精品社区| 亚洲国产黄色| 欧美日韩a区| 亚洲毛片播放| 亚洲欧洲日本mm| 欧美日韩1区2区3区| 亚洲精品少妇| 亚洲高清123| 免费观看成人网| 亚洲美女av电影| 欧美在线播放一区二区| 欧美高清成人| 国产欧美一区二区三区在线老狼| 一区二区三区无毛| 小黄鸭精品密入口导航| 亚洲第一在线综合在线| 亚洲欧美日韩网| 国产精品私拍pans大尺度在线| 国产日韩av一区二区| 亚洲高清久久久| 久久国产精品久久久久久| 亚洲人成精品久久久久| 免费成人av在线看| 韩国成人福利片在线播放| 欧美在线视频观看| 亚洲网站啪啪| 欧美精品aa| 国产香蕉久久精品综合网| 久久综合国产精品台湾中文娱乐网| 久久伊伊香蕉| 欧美一区二区视频97| 久热精品在线| 久久久高清一区二区三区| 蜜臀a∨国产成人精品| 国产欧美在线视频| 亚洲系列中文字幕| 亚洲美女色禁图| 欧美日精品一区视频| 亚洲网站在线看| 香蕉尹人综合在线观看| 伊人久久综合97精品| 美女任你摸久久| 欧美成人精品高清在线播放| 亚洲成色777777在线观看影院| 久久国产天堂福利天堂| 欧美一区午夜视频在线观看| 亚洲国产成人精品女人久久久| 免播放器亚洲一区| 在线电影国产精品| 欧美激情精品久久久久久变态| 久久综合久久综合这里只有精品| 狠狠入ady亚洲精品经典电影| 久久婷婷亚洲| 欧美高清在线视频| 亚洲免费视频成人| 每日更新成人在线视频| 制服丝袜亚洲播放| 欧美一区网站| 中文国产一区| 久久久久免费视频| 久久精品国产第一区二区三区最新章节 | 午夜精品免费| 亚洲精品国产欧美| 亚洲尤物在线| 亚洲作爱视频| 久久午夜精品一区二区| 一区二区三区不卡视频在线观看| 亚洲精品美女久久久久| 黑人巨大精品欧美黑白配亚洲| 欧美顶级大胆免费视频| 国产精品免费观看在线| 亚洲人线精品午夜| 亚洲第一页中文字幕| 亚洲香蕉成视频在线观看| 亚洲黄页一区| 久久亚洲风情| 激情欧美日韩| 欧美sm极限捆绑bd| 在线精品国精品国产尤物884a| 亚洲综合首页| 久久精品亚洲一区二区| 国产精品美女久久久久av超清 | 国产精品激情| 一区二区三区www| 西西人体一区二区| 国产精品主播| 亚洲欧美激情一区二区| 久久久久成人网| 韩国av一区二区三区| 久久一区国产| 国产精品99久久99久久久二8| 中文日韩电影网站| 国产伦精品一区二区三区| 久久精品国产精品亚洲精品| 国产欧美一区二区白浆黑人| 性欧美精品高清| 亚洲欧洲在线看| 久久久久国内| 亚洲免费婷婷| 黑人一区二区三区四区五区| 久久综合九色欧美综合狠狠| 亚洲欧洲综合另类在线| 午夜视频在线观看一区| 伊人色综合久久天天五月婷| 欧美日韩理论| 亚洲午夜女主播在线直播| 欧美国产一区二区| 久久亚洲一区| 久久精品一区二区国产| 亚洲深夜福利视频| 在线观看日韩专区| 一区久久精品| 激情校园亚洲| 黄色成人精品网站| 国产嫩草影院久久久久| 欧美午夜不卡视频| 欧美日韩在线精品| 国产精品久久久久久久电影| 欧美视频在线观看一区二区| 免费h精品视频在线播放| 久久影院午夜论| 欧美久久久久中文字幕| 欧美午夜一区二区| 国产精品久久久久免费a∨大胸| 亚洲小视频在线| 在线视频日本亚洲性| 亚洲天堂av图片| 欧美一区二区观看视频| 久久免费少妇高潮久久精品99| 久久嫩草精品久久久精品一| 麻豆免费精品视频| 国产精品久久99| 亚洲成色999久久网站| 嫩草国产精品入口| 欧美欧美全黄| 国产欧美日韩一级| 亚洲日本电影| 亚洲精品一区二区网址| 国产丝袜美腿一区二区三区| 亚洲毛片一区| 欧美午夜不卡在线观看免费| 国产精品日韩欧美| 亚洲高清毛片| 亚洲四色影视在线观看| 久久永久免费| 亚洲欧美在线免费观看| 欧美激情在线| 亚洲黄色高清| 亚洲第一二三四五区| 亚洲女爱视频在线| 国产视频在线观看一区二区三区| 亚洲精品在线观看视频| 亚洲精选久久| 日韩亚洲欧美成人| 欧美电影在线播放| 小处雏高清一区二区三区| 久久国内精品自在自线400部| 欧美日韩天天操| 在线视频精品| 亚洲私人影院| 99在线热播精品免费| 欧美高清不卡| 中国成人在线视频| 亚洲综合色丁香婷婷六月图片| 欧美88av| 日韩一级欧洲| 亚洲人精品午夜在线观看| 美女成人午夜| 国产一区二区三区成人欧美日韩在线观看 | 午夜影院日韩| 国产精品制服诱惑| 欧美日韩在线一区二区| 国产精品色网| 欧美1区视频| 久久综合九色综合欧美狠狠| 亚洲视频一区在线观看| 日韩写真视频在线观看| 久久久久久久网站| aa亚洲婷婷| 欧美日韩在线观看一区二区三区| 国产精品视频xxx| 亚洲国产精品久久久久婷婷884| 亚洲毛片在线观看| 国产视频综合在线| 久久综合狠狠| 午夜一级久久| 欧美一区二区精美| 亚洲综合国产| 久久久久国内| 久久午夜精品|