title: Start a thread in one web service request and stop it in another request
body: <p>I would like to start a thread which records sensor values thanks to a web service request using Hyper.rs. Then, with another request, I would like to stop the thread and take all recorded data.</p>
  
  <p>I know if a thread is already running thanks to <code>Mutex</code>, so I tried to put <code>Sender&lt;T&gt;</code> into a <code>Mutex</code>, but I can't use values of this <code>Mutex</code> because of "cannot move out of borrowed content". </p>
  
  <p>This is my code:</p>
  
  <pre><code>extern crate futures;
  extern crate hyper;
  
  use futures::future::Future;
  use hyper::{Method, StatusCode};
  use hyper::server::{Http, Request, Response, Service};
  use std::sync::Mutex;
  use std::sync::mpsc::{channel, Sender};
  use std::thread;
  use std::thread::ThreadId;
  
  fn main() {
      let addr = "127.0.0.1:3000".parse().unwrap();
      let server = Http::new().bind(&amp;addr, || Ok(Sensor::new())).unwrap();
      server.run().unwrap();
  }
  
  struct Sensor {
      current_thread: Mutex&lt;Option&lt;ThreadId&gt;&gt;,
      current_tx: Mutex&lt;Option&lt;Sender&lt;String&gt;&gt;&gt;,
  }
  
  impl Sensor {
      pub fn new() -&gt; Sensor {
          Sensor {
              current_thread: Mutex::new(None),
              current_tx: Mutex::new(None),
          }
      }
  
      fn start_sensors(&amp;self) -&gt; &lt;Sensor as Service&gt;::Future {
          let mut current_thread = self.current_thread.lock().unwrap();
          match *current_thread {
              Some(id) =&gt; {
                  self.response_with_body(format!("thread with id {:?} is already running", id))
              }
              None =&gt; {
                  let (tx, rx) = channel();
                  let builder = thread::Builder::new();
                  let join_handle = builder
                      .spawn(|| {
                          for received in rx {
                              println!("Got: {}", received);
                              if received == "stop" {
                                  break;
                              }
                          }
                      })
                      .unwrap();
                  let thread = join_handle.thread();
  
                  let mut current_tx = self.current_tx.lock().unwrap();
                  *current_tx = Some(tx);
  
                  let message = format!("thread id: {:?}", &amp;thread.id());
                  *current_thread = Some(thread.id());
  
                  self.response_with_body(message)
              }
          }
      }
  
      fn stop_sensors(&amp;self) -&gt; &lt;Sensor as Service&gt;::Future {
          let mut current_tx = self.current_tx.lock().unwrap();
          match *current_tx {
              Some(tx) =&gt; {
                  let mut current_thread = self.current_thread.lock().unwrap();
  
                  // just to trying to communicate with the thread
                  let vals = vec![String::from("hi"), String::from("stop")];
  
                  for val in vals {
                      tx.send(val).unwrap();
                  }
  
                  *current_tx = None;
                  *current_thread = None;
                  Box::new(futures::future::ok(Response::new()))
              }
              None =&gt; self.response_with_body(format!("No thread running")),
          }
      }
  
      fn response_with_body(&amp;self, body: String) -&gt; &lt;Sensor as Service&gt;::Future {
          Box::new(futures::future::ok(Response::new().with_body(body)))
      }
  }
  
  impl Service for Sensor {
      type Request = Request;
      type Response = Response;
      type Error = hyper::Error;
      type Future = Box&lt;Future&lt;Item = Self::Response, Error = Self::Error&gt;&gt;;
  
      fn call(&amp;self, req: Request) -&gt; Self::Future {
          //let mut current_thread: Option&lt;ThreadId&gt; = None;
          match (req.method(), req.path()) {
              (&amp;Method::Get, "/sensors/start") =&gt; self.start_sensors(),
              (&amp;Method::Get, "/sensors/stop") =&gt; self.stop_sensors(),
              _ =&gt; Box::new(futures::future::ok(
                  Response::new().with_status(StatusCode::NotFound),
              )),
          }
      }
  }
  </code></pre>
  
  <pre class="lang-none prettyprint-override"><code>error[E0507]: cannot move out of borrowed content
    --&gt; src/main.rs:65:15
     |
  65 |         match *current_tx {
     |               ^^^^^^^^^^^ cannot move out of borrowed content
  66 |             Some(tx) =&gt; {
     |                  -- hint: to prevent move, use `ref tx` or `ref mut tx`
  </code></pre>
  
  <p>How should I do this? </p>