title: Merge queue of std::maps into one std::map in parallel
body: <p>I have such a problem. I have a self-implemented thread-safe queue. I filled it with <code>std::map&lt;std::string, int&gt;</code>s, of the following structure: word - number of its occurrences. So I want to merge these maps to get the map, which will represent total number of occurrences of these words. I want to do it in parallel, so I implemented the following function(merge), but I think, that it can be the case, when mapping will finish, while there still will be maps to merge. How can I fix it? Here is my code of self-implemented queue, merge function and example of running.</p>
  
  <pre><code>template&lt;class T&gt;
  class safeQueue {
      std::deque&lt;T&gt; que;
      mutable std::mutex m;
      std::condition_variable cvNotEmpty;
      std::condition_variable cvNotMax;
      size_t max_size = 10;
  
  public:
      safeQueue(){}
  
      void setMaxSize(size_t newMax) {
          std::lock_guard&lt;std::mutex&gt; lg{m};
          max_size = newMax;
      }
  
      auto size() const {
          std::lock_guard&lt;std::mutex&gt; lg{m};
          return que.size();
      }
  
  
  
      void pushFront(T item) {
          std::unique_lock&lt;std::mutex&gt; lg{m};
          cvNotMax.wait(lg, [this](){return max_size != que.size();});
  
          que.push_front(item);
          cvNotEmpty.notify_one();
      }
  
      void pushBack(T item) {
          std::unique_lock&lt;std::mutex&gt; lg{m};
          cvNotMax.wait(lg, [this](){return max_size != que.size();});
  
          que.push_back(item);
          cvNotEmpty.notify_one();
      }
  
  
  
      T popBack(){
          std::unique_lock&lt;std::mutex&gt; lg{m};
          cvNotEmpty.wait(lg, [this](){return que.size() != 0;});
          T result = que.back();
          que.pop_back();
          return result;
      }
  
      T popFront(){
          std::unique_lock&lt;std::mutex&gt; lg{m};
          cvNotEmpty.wait(lg, [this](){return que.size() != 0;});
          T result = que.front();
          que.pop_front();
          return result;
      }
  };
  </code></pre>
  
  <pre><code>void merge(safeQueue&lt;std::map&lt;std::string, int&gt;&gt;&amp; que) {
  
      while (que.size() &gt;= 2) {
  
          std::map&lt;std::string, int&gt; map1 = que.popFront();
          std::map&lt;std::string, int&gt; map2 = que.popFront();
          for (const auto &amp;element : map2) {
              map1[element.first] += element.second;
          }
  
          que.pushBack(map1);
      }
  
  }
  </code></pre>
  
  <pre><code>int main() {
      auto mergers = new std::vector&lt;std::thread&gt;;
  
      std::map&lt;std::string, int&gt; map1;
      std::map&lt;std::string, int&gt; map2;
      std::map&lt;std::string, int&gt; map3;
      std::map&lt;std::string, int&gt; map5;
  
      map1.insert(std::pair("a", 3));
      map1.insert(std::pair("b", 3));
      map1.insert(std::pair("c", 3));
      map1.insert(std::pair("d", 3));
      map1.insert(std::pair("e", 3));
      map1.insert(std::pair("f", 3));
  
      map2.insert(std::pair("a", 3));
      map2.insert(std::pair("b", 3));
      map2.insert(std::pair("c1", 3));
      map2.insert(std::pair("d", 3));
      map2.insert(std::pair("e1", 3));
      map2.insert(std::pair("f1", 3));
  
      map3.insert(std::pair("a", 3));
      map3.insert(std::pair("b", 3));
      map3.insert(std::pair("c2", 3));
      map3.insert(std::pair("d", 3));
      map3.insert(std::pair("e2", 3));
      map3.insert(std::pair("f2", 3));
  
      map5.insert(std::pair("a", 3));
      map5.insert(std::pair("b", 3));
      map5.insert(std::pair("c4", 3));
      map5.insert(std::pair("d", 3));
      map5.insert(std::pair("e4", 3));
      map5.insert(std::pair("f4", 3));
  
  
      safeQueue&lt;std::map&lt;std::string, int&gt;&gt; que;
      que.pushBack(map1);
      que.pushBack(map2);
      que.pushBack(map3);
      que.pushBack(map5);
  
      int num_mergers = 3;
  
      for (int i =0; i &lt; num_mergers; i++) {
          mergers-&gt;emplace_back(std::thread(merge, std::ref(que)));
      }
  
      for (int k=0; k &lt; num_mergers; k++) {
          mergers-&gt;at(k).join();
      }
  
      std::map&lt;std::string, int&gt; map_res = que.popBack();
  
      for (const auto&amp; c : map_res) {
          std:: cout &lt;&lt; c.first + " " &lt;&lt; c.second &lt;&lt; std::endl;
      }
  
      return 0;
  }
  </code></pre>