title: How to wait for tokio tasks to finish?
body: <p>I am trying to write to a <code>HashMap</code> using the <code>Arc&lt;Mutex&lt;T&gt;&gt;</code> pattern as part of a website scraping exercise inspired from <a href="https://rust-lang-nursery.github.io/rust-cookbook/web/scraping.html" rel="nofollow noreferrer">the Rust cookbook</a>.</p>
  <p>This first part uses <code>tokio</code> runtime. I cannot get past the tasks being completed and returning the <code>HashMap</code> as it just hangs.</p>
  <pre class="lang-rust prettyprint-override"><code>type Db = Arc&lt;Mutex&lt;HashMap&lt;String, bool&gt;&gt;&gt;;
  
  pub async fn handle_async_tasks(db: Db) -&gt; BoxResult&lt;HashMap&lt;String, bool&gt;&gt; {
      let links = NodeUrl::new(&quot;https://www.inverness-courier.co.uk/&quot;)
          .await
          .unwrap();
  
      let arc = db.clone();
  
      let mut handles = Vec::new();
  
      for link in links.links_with_paths {
          let x = arc.clone();
          handles.push(tokio::spawn(async move {
              process(x, link).await;
          }));
      }
  
      //  for handle in handles {
      //     handle.await.expect(&quot;Task panicked!&quot;);
      //  } &lt; I tried this as well&gt;
  
      futures::future::join_all(handles).await;
  
      let readables = arc.lock().await;
  
      for (key, value) in readables.clone().into_iter() {
          println!(&quot;Checking db: k, v ==&gt;{} / {}&quot;, key, value);
      }
  
      let clone_db = readables.clone();
  
      return Ok(clone_db);
  }
  
  async fn process(db: Db, url: Url) {
      let mut db = db.lock().await;
      println!(&quot;checking {}&quot;, url);
  
      if check_link(&amp;url).await.is_ok() {
          db.insert(url.to_string(), true);
      } else {
          db.insert(url.to_string(), false);
      }
  }
  
  async fn check_link(url: &amp;Url) -&gt; BoxResult&lt;bool&gt; {
      let res = reqwest::get(url.as_ref()).await?;
      Ok(res.status() != StatusCode::NOT_FOUND)
  }
  
  pub struct NodeUrl {
      domain: String,
      pub links_with_paths: Vec&lt;Url&gt;,
  }
  
  #[tokio::main]
  async fn main() {
      let db: Db = Arc::new(Mutex::new(HashMap::new()));
  
      let db = futures::executor::block_on(task::handle_async_tasks(db));
  }
  </code></pre>
  <p>I would like to return the <code>HashMap</code> to <code>main()</code> where the main thread is blocked. How can I wait for all async threaded processes to be complete and return the <code>HashMap</code>?</p>