Search code examples
c++c++11stdmovedeque

Move an element from std::deque in C++11


We know that std::deque::front() return a reference to a first element of deque. I would to know if this code is always safe:

//deque of lambdas
deque<function<void(void)>> funs;

// then is some other place:
// take a lock
m.lock();
auto f = move(funs.front()); // move the first lambda in f
funs.pop_front(); // remove the element from deque //now the value is hold by f
m_.unlock(); // unlock the resorce
f(); //execute f

I've tried this code using gcc-4.9 and works but I don't know if we can consider this code safe!


Solution

  • The std::function move constructor is not guaranteed to not throw exceptions, so you have an exception safety issue. Since you are not using an RAII lock for m, it will remain locked if auto f = move(funs.front()); throws. You can correct the problem with std::unique_lock:

    std::unique_lock<decltype(m)> lock{m};
    if (!funs.empty()) {
      auto f = move(funs.front()); // move the first lambda in f
      funs.pop_front(); // remove the element from deque //now the value is hold by f
      lock.unlock(); // unlock the resorce
      f(); //execute f
    }
    

    or std::lock_guard:

    function<void()> f;
    {
      std::lock_guard<decltype(m)> lock{m};
      if (!funs.empty()) {
        f = move(funs.front()); // move the first lambda in f
        funs.pop_front(); // remove the element from deque //now the value is hold by f
      }
    }
    if (f) f(); //execute f