您如何可变地将单个结构实例共享给多个消费者(如服务)?

How do you mutablely share a single struct instance to multiple consumers (like a service)?

假设您有一个 HTTP API 作为计数器的接口。计数器状态存在于一个名为 CounterService 的对象中,您可以 increment() 计数器状态。

一个简单的 TypeScript 示例如下所示:

class CounterService {
   public value: number = 0

   public increment(): void {
      this.value = this.value + 1
   }

   public decrement(): void {
      this.value = this.value - 1
   }
}

void function main() {
   const api = express()
   const counterService = new CounterService()

   api.get('/value', getValueHandler(counterService))
   api.post('/increment', incrementHandler(counterService))
   api.post('/decrement', decrementHandler(counterService))

   api.listen(3000)
}()

function getValueHandler(counterService: CounterService): express.Handler {
   return function(req: express.Request, res: express.Response) {
      res.send(counterService.value)
   }
}

function incrementHandler(counterService: CounterService): express.Handler  {
   return function(req: express.Request, res: express.Response) {
      counterService.increment()
      res.sendStatus(204)
   }
}

// ...

在上面的代码中,我将 counterService 对象共享给三个函数。一个需要只读访问权限,但其他两个都需要对其进行变异。

现在我明白这不是线程安全的,因为状态应该被锁定在互斥锁后面,所以我认为这是难题的一部分。不过,从广义上讲,有人如何在 rust 中实现与此类似的东西?

struct CounterService {
   value: i32
}

impl CounterService {
  fn increment(&mut self) {
    self.value = self.value + 1
  }

  fn decrement(&mut self) {
    self.value = self.value - 1
  }
}

fn main {
//not sure how to make the equiv http server indicating callbacks, yet
}


好吧,你自己回答了 - 用 Mutex 包裹起来。它将为持有锁的人提供可变访问权限。

use std::sync::Mutex;

fn main() {
    let svc = CounterService { value: 0 };
    let data = Mutex::new(svc);

    // .lock() does NOT require mut!
    // Yet it gives you mutable access
    let mut guard = data.lock().unwrap();
    guard.increment();

    drop(guard); // unlock the lock, so we can print the non-mut variable
    println!("{:?}", data);
}

#[derive(Debug)]
struct CounterService {
    value: i32,
}

impl CounterService {
    fn increment(&mut self) {
        self.value = self.value + 1
    }

    fn decrement(&mut self) {
        self.value = self.value - 1
    }
}

如果您想将它共享给多个处理程序,只需将 Mutex 包装在一个 Arc 中,这是一个线程安全的引用计数智能指针:

fn main() {
    let svc = CounterService { value: 0 };
    let shared = Arc::new(Mutex::new(svc));

    handler_a(shared.clone());
    handler_b(shared.clone());
    handler_c(shared.clone());
}