Thread-safe C++ stack

后端 未结 6 1363
余生分开走
余生分开走 2021-01-30 18:56

I\'m new to C++ and am writing a multi-threaded app whereby different writers will be pushing objects onto a stack and readers pulling them off the stack (or at least pushing th

6条回答
  •  说谎
    说谎 (楼主)
    2021-01-30 19:27

    Yep: Boost.Thread is great, and should fit your needs very well. (These days, many people say that you could almost count Boost as built-in functionality.)

    There is still no class that you could use out-of-the-box, but once you have the synchronization primitives at hand, it really is quite simple to implement your own thread-safe wrapper around, for example, std::stack. It could look something like this (not implementing every method...):

    template  class MyThreadSafeStack {
      public:
        void push(const T& item) {
          boost::mutex::scoped_lock lock(m_mutex);
          m_stack.push(item);
        }
        void pop() {
          boost::mutex::scoped_lock lock(m_mutex);
          m_stack.pop();
        }
        T top() const { // note that we shouldn't return a reference,
                        // because another thread might pop() this
                        // object in the meanwhile
          boost::mutex::scoped_lock lock(m_mutex);
          return m_stack.top();
        }
    
      private:
        mutable boost::mutex m_mutex;
        std::stack m_stack;
    }    
    

    If you are new to C++, please learn about RAII. Relevant to this case, Boost.Thread has the "scoped lock" classes to make it difficult to shoot yourself in the leg by forgetting to release a lock.

    If you ever find yourself writing code like this:

    void doStuff() {
      myLock.lock();
      if (!condition) {
        reportError();
        myLock.unlock();
        return;
      }
      try {
        doStuffThatMayThrow();
      }
      catch (std::exception& e) {
        myLock.unlock();
        throw e;
      }
      doMoreStuff();
      myLock.unlock();
    }
    

    , then you should just say no, and go RAII instead (syntax not directly from Boost):

    void doStuff() {
      scoped_lock lock;
      if (!condition) {
        reportError();
        return;
      }
      doStuffThatMayThrow();
      doMoreStuff();
    }
    

    The point is that when the scoped_lock object goes out of scope, its destructor releases the resource -- in this case, the lock. This will always happen, no matter whether you exit the scope by throwing an exception, or by executing the odd return statement that your colleague sneakily added in the middle of your function, or simply by reaching the end of the function.

提交回复
热议问题