小编ube*_*ben的帖子

Rust 什么时候保证尾递归?

C语言

在 C 编程语言中,很容易出现尾递归

int foo(...) {
    return foo(...);
}
Run Code Online (Sandbox Code Playgroud)

只需返回递归调用的返回值即可。当这种递归可能重复一千次甚至一百万次时,这一点尤其重要。它会在堆栈上使用大量内存

现在,我有一个 Rust 函数,它可以递归地调用自己一百万次:

fn read_all(input: &mut dyn std::io::Read) -> std::io::Result<()> {
    match input.read(&mut [0u8]) {
        Ok (  0) => Ok(()),
        Ok (  _) => read_all(input),
        Err(err) => Err(err),
    }
}
Run Code Online (Sandbox Code Playgroud)

(这是一个最小的例子,真正的例子更复杂,但它抓住了主要思想)

这里,递归调用的返回值按原样返回,但是:

它是否保证 Rust 编译器会应用尾递归?

例如,如果我们声明了一个像 a 这样需要销毁的变量,std::Vec它会在递归调用之前(允许尾递归)还是在递归调用返回之后(禁止尾递归)被销毁?

recursion tail-recursion rust

32
推荐指数
2
解决办法
6870
查看次数

如何在数据结构中使用 BufReader 和 BufWriter 存储 TcpStream

我想要a和 aTcpStream共享,我找到了一个解决方案:如果 BufReader 拥有流的所有权,我如何在其上读取和写入行?BufReaderBufWriter

现在我希望它有自己的数据结构,但我只得到了部分答案:
为什么我不能在同一结构中存储一个值和对该值的引用?

期望的实现违反了所有权规则。

use std::io::{BufReader, BufWriter};
use std::net::TcpStream;

pub struct BufTcpStream<'a> {
    _socket: TcpStream,
    input:  BufReader<&'a TcpStream>;
    output: BufWriter<&'a TcpStream>;
}

impl<'a> BufTcpStream<'a> {
    pub fn new(socket: TcpStream) -> Self {
        Self{
            input : BufReader::new(&socket),
            output: BufWriter::new(&socket),
            _socket: socket,//                 <-- MOVE OF BORROWED VALUE HERE
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我必须确保TcpStream引用在整个结构生命周期内保持有效,我使用了 aPin<Box<TcpStream>>来确保它。

但编译器仍然抱怨借用值的移动socket。为了消除这个障碍,我使用了std::meme::transmute().

现在,我想知道的是:

这个实现安全吗?

use std::io::{BufReader, BufWriter};
use std::net::TcpStream;
use std::pin::Pin;

pub struct BufTcpStream<'a> …
Run Code Online (Sandbox Code Playgroud)

rust

10
推荐指数
1
解决办法
6663
查看次数

Rust - 在线程之间不安全地共享没有互斥体的可变数据

如何在 Rust 中实现老式多线程(无包装互斥)?为什么这是未定义的行为?

我必须建立一个高度并发的物理模拟。我应该用 C 语言来做,但我选择了 Rust(我确实需要更高级别的功能)。

通过使用 Rust,我应该选择线程之间的安全通信,但是,我必须使用线程之间共享的可变缓冲区。(实际上,我必须实施不同的技术并对它们进行基准测试)

第一种方法

  1. 用于Arc<Data>共享非可变状态。

  2. 需要时用于transmute推广。&&mut

这很简单,但即使使用块,编译器也会阻止其编译unsafe。这是因为编译器可以应用优化,知道这些数据应该是不可变的(可能被缓存并且从未更新,不是这方面的专家)。

这种优化可以通过Cell包装器和其他方法来停止。

第二种方法

  1. 使用Arc<UnsafeCell<Data>>

  2. 然后data.get()访问数据。

这也不能编译。原因是UnsafeCell不是Send。解决方案是使用SyncUnsafeCell但目前不稳定的版本(1.66),程序将在只有稳定版本的机器上编译并投入生产。

第三种方法

  1. 使用Arc<Mutex<Data>>

  2. 在每个线程的开头:

    • 锁定互斥体。

    • *mut通过强制 a 来保留 a &mut

    • 释放互斥体。

  3. *mut需要时使用

我还没有尝试过这个,但即使它可以编译,它是否安全(不谈论数据竞争)SyncUnsafeCell

PS:同时变异的值只是f32,绝对没有内存分配或任何复杂的操作同时发生。最坏的情况,我已经打乱了一些f32

multithreading mutex unsafe rust

7
推荐指数
1
解决办法
1135
查看次数

如何在Linux上的C/C++中使用ipv6 udp socket进行组播?

(英语不是我的母语,如果有些句子很奇怪,不要担心;)).

我正在开发一个PONG游戏,顺便创建一些类来帮助我管理窗口,事件......和网络因为我在游戏中添加了局域网功能,但是目前你必须输入你想要的人的地址玩.并且解决方案是广播(用于播放器的扫描LAN).这很容易使用ipv4,只需使用地址255.255.255.255,但我们在2017年并提供仅适用于ipv4的功能...

然后我寻找一种用ipv6播放的方式,我学习了多播,但这部分让我迷失了.=(

在Linux上使用C++中的标准库,我发现了几个不能与我合作的多播的例子.我此时所做的最好的事情是从一个程序实例向同一台计算机上的另一个实例发送一个udp数据包.

如何在Linux上用C/C++在ipv6 udp socket上进行多播?

在互联网上找到的最好的代码(我重新安排它)几乎可以工作(有一个客户端和服务器,通过向argv添加1或0来做出选择):

int main(int argc, char const *argv[]) {

struct sockaddr_in6 groupSock;
int sd = -1;

char databuf[10];
int datalen = sizeof databuf;

/* Create a datagram socket on which to send/receive. */
if((sd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
    perror("Opening datagram socket error");
    return 1;
} else {
    cout << "Opening the datagram socket...OK." << endl;;
}

/* Enable SO_REUSEADDR to allow …
Run Code Online (Sandbox Code Playgroud)

c++ sockets linux multicast ipv6

6
推荐指数
1
解决办法
4016
查看次数

我可以通过在两个异步接收器上调用 select 来错过一个值吗?

是否有可能,如果一个任务发送到a另一个(同时)发送到b,通过取消剩余的未来来tokio::select!打开ab删除一个值?还是保证在下一次循环迭代时收到?

use tokio::sync::mpsc::Receiver;

async fn foo(mut a: Receiver<()>, mut b: Receiver<()>) {
    loop {
        tokio::select!{
            _ = a.recv() => {
                println!("A!");
            }
            _ = b.recv() => {
                println!("B!");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

async在那种情况下,我的思绪无法绕过魔法背后真正发生的事情。

rust async-await rust-tokio

6
推荐指数
1
解决办法
277
查看次数

宏如何匹配除逗号之外的任何标记树

macro_rules! foo {
    ( $( $( $tok:tt )* ,)* ) => {
        [ bar!( $( $tok )* ,)* ]
    }
}
Run Code Online (Sandbox Code Playgroud)

产生错误:local ambiguity when calling macro 'foo'. 因为逗号','的类型是:tt。我需要一种方法来匹配除逗号标记之外的所有标记树。

使用示例

foo!(
    add t0 zero zero,
    add t1 t0 a0,
    lb t1 0(t1),
)
Run Code Online (Sandbox Code Playgroud)

应产生:

[
    bar!(add t0 zero zero),
    bar!(add t1 t0 a0),
    bar!(lb t1 0(t1)),
]
Run Code Online (Sandbox Code Playgroud)

macros rust rust-macros

4
推荐指数
1
解决办法
398
查看次数

在 Elm 中,GET 请求不能有正文,是吗?

Http.requestbody该方法似乎忽略了GET

init : () -> ( Model, Cmd Msg )
init _ =
    ( Loading
    , Http.request
        { method = "GET"
        , headers = []
        , url = "http://127.0.0.1"
        , body = Http.stringBody "text/plain" "Hello World!"
        , expect = Http.expectWhatever Sent
        , timeout = Nothing
        , tracker = Nothing
        }
    )
Run Code Online (Sandbox Code Playgroud)

发送的请求没有正文(使用浏览器开发工具检查时)。

init : () -> ( Model, Cmd Msg )
init _ =
    ( Loading
    , Http.request
        { method = "POST" {- CHANGED TO POST -} …
Run Code Online (Sandbox Code Playgroud)

http-get http-post request payload elm

3
推荐指数
1
解决办法
108
查看次数