Thread-safe vector implementation
<p>I'm working on a thread-safe std::vector implementation and the following is a completed preliminary attempt:</p>

<pre><code>    #ifndef THREADSAFEVECTOR_H
    #define THREADSAFEVECTOR_H
    #include &lt;iostream&gt;
    #include &lt;vector&gt;
    #include &lt;mutex&gt;
    #include &lt;cstdlib&gt;
    #include &lt;memory&gt;
    #include &lt;iterator&gt;
    #include &lt;algorithm&gt;
    #include &lt;initializer_list&gt;
    #include &lt;functional&gt;
    template &lt;class T, class Alloc=std::allocator&lt;T&gt;&gt;
    class ThreadSafeVector
    {
        private:
            std::vector&lt;T&gt; threadSafeVector;
            std::mutex vectorMutex;

        public:
            /*need to use typename here because std::allocator&lt;T&gt;::size_type, std::allocator&lt;T&gt;::value_type, std::vector&lt;T&gt;::iterator, 
            and std::vector&lt;T&gt;::const_reverse_iterator are 'dependent names' in that because we are working with a templated class, 
            these expressions may depend on types of type template parameters and values of non-template parameters*/

            typedef typename std::vector&lt;T&gt;::size_type size_type;

            typedef typename std::vector&lt;T&gt;::value_type value_type;

            typedef typename std::vector&lt;T&gt;::iterator iterator;

            typedef typename std::vector&lt;T&gt;::const_iterator const_iterator;

            typedef typename std::vector&lt;T&gt;::reverse_iterator reverse_iterator;

            typedef typename std::vector&lt;T&gt;::const_reverse_iterator const_reverse_iterator;

            typedef typename std::vector&lt;T&gt;::reference reference;

            typedef typename std::vector&lt;T&gt;::const_reference const_reference;

            /*wrappers for three different at() functions*/
            template &lt;class InputIterator&gt;
            void assign(InputIterator first, InputIterator last)
            {
                //using a local lock_guard to lock mutex guarantees that the mutex will be unlocked on destruction and in the case of an exception being thrown
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.assign(first, last);
            }

            void assign(size_type n, const value_type&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.assign(n, val);
            }

            void assign(std::initializer_list&lt;value_type&gt; il)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.assign(il.begin(), il.end());
            }

            /*wrappers for at() functions*/
            reference at(size_type n)
            {
                return threadSafeVector.at(n);
            }

            const_reference at(size_type n) const
            {
                return threadSafeVector.at(n);
            }   

            /*wrappers for back() functions*/
            reference back()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.back();
            }

            const reference back() const
            {
                return threadSafeVector.back();
            }

            /*wrappers for begin() functions*/
            iterator begin()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.begin();
            }

            const iterator begin() const noexcept
            {
                return threadSafeVector.begin();
            }

            /*wrapper for capacity() fucntion*/
            size_type capacity() const noexcept
            {
                return threadSafeVector.capacity();
            }

            /*wrapper for cbegin() function*/
            const iterator cbegin()
            {
                return threadSafeVector.cbegin();
            }

            /*wrapper for cend() function*/
            const iterator cend()
            {
                return threadSafeVector.cend();
            }

            /*wrapper for clear() function*/
            void clear()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.clear();
            }

            /*wrapper for crbegin() function*/
            const_reverse_iterator crbegin() const noexcept
            {
                return threadSafeVector.crbegin();
            }

            /*wrapper for crend() function*/
            const_reverse_iterator crend() const noexcept
            {
                return threadSafeVector.crend();
            }

            /*wrappers for data() functions*/
            value_type* data()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.data();
            }

            const value_type* data() const noexcept
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.data();
            }

            /*wrapper for emplace() function*/
            template &lt;class... Args&gt;
            void emplace(const iterator position, Args&amp;&amp;... args)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.emplace(position, args...);
            }

            /*wrapper for emplace_back() function*/
            template &lt;class... Args&gt;
            void emplace_back(Args&amp;&amp;... args)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.emplace_back(args...);
            }

            /*wrapper for empty() function*/
            bool empty() const noexcept
            {
                return threadSafeVector.empty();
            }

            /*wrappers for end() functions*/
            iterator end()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.end();
            }

            const iterator end() const noexcept
            {
                return threadSafeVector.end();
            }

            /*wrapper functions for erase()*/
            iterator erase(const_iterator position)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.erase(position);
            }

            iterator erase(const_iterator first, const_iterator last)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.erase(first, last);
            }

            /*wrapper functions for front()*/
            reference front()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.front();
            }

            const reference front() const
            {
                return threadSafeVector.front();
            }

            /*wrapper function for get_allocator()*/
            value_type get_allocator() const noexcept
            {
                return threadSafeVector.get_allocator();
            }

            /*wrapper functions for insert*/
            iterator insert(const_iterator position, const value_type&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.insert(position, val); 
            }

            iterator insert(const_iterator position, size_type n, const value_type&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.insert(position, n, val);
            }

            template &lt;class InputIterator&gt;
            iterator insert(const_iterator position, InputIterator first, InputIterator last)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.insert(position, first, last);
            }

            iterator insert(const_iterator position, value_type&amp;&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.insert(position, val);
            }

            iterator insert(const_iterator position, std::initializer_list&lt;value_type&gt; il)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.insert(position, il.begin(), il.end());
            }

            /*wrapper function for max_size*/
            size_type max_size() const noexcept
            {
                return threadSafeVector.max_size();
            }

            /*wrapper functions for operator =*/
            std::vector&lt;T&gt;&amp; operator= (const std::vector&lt;T&gt;&amp; x)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.swap(x);
            }

            std::vector&lt;T&gt;&amp; operator= (std::vector&lt;T&gt;&amp;&amp; x)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector=std::move(x);
            }

            std::vector&lt;T&gt;&amp; operator= (std::initializer_list&lt;value_type&gt; il)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.assign(il.begin(), il.end());

                return *this; //is this safe to do?
            }

            /*wrapper functions for operator []*/
            reference operator[] (size_type n)
            {
                return std::ref(n);
            }

            const_reference operator[] (size_type n) const
            {
                return std::cref(n);
            }

            /*wrapper function for pop_back()*/
            void pop_back()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.pop_back();
            }

            /*wrapper functions for push_back*/
            void push_back(const value_type&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.push_back(val);
            }

            void push_back(value_type&amp;&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.push_back(val);
            }

            /*wrapper functions for rbegin()*/
            reverse_iterator rbegin() noexcept
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.rbegin();
            }

            const_reverse_iterator rbegin() const noexcept
            {
                return threadSafeVector.rbegin();
            }

            /*wrapper functions for rend()*/
            reverse_iterator rend() noexcept
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                return threadSafeVector.rend();
            }

            const_reverse_iterator rend() const noexcept
            {
                return threadSafeVector.rend();
            }

            /*wrapper function for reserve()*/
            void reserve(size_type n)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.reserve(n);
            }

            /*wrapper functions for resize()*/      
            void resize(size_type n)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.resize(n);
            }

            void resize(size_type n, const value_type&amp; val)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.resize(n, val);
            }

            void shrink_to_fit()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.shrink_to_fit();
            }

            //add function for size
            size_type size() const noexcept
            {
                return threadSafeVector.size();
            }

            /*wrapper function for swap()*/
            void swap(std::vector&lt;T&gt;&amp; x)
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                threadSafeVector.swap(x);
            }

            void print()
            {
                std::lock_guard&lt;std::mutex&gt; vectorLockGuard(vectorMutex);

                for(const auto &amp; element : threadSafeVector)
                {
                    std::cout &lt;&lt; element &lt;&lt; std::endl;
                }

                std::cout &lt;&lt; std::endl;
            }
    };
    #endif
</code></pre>

<p>I have based my implementation on the description of the vector class and its member functions found on <a href="http://www.cplusplus.com/reference/vector/vector/" rel="nofollow">cplusplus.com</a> and with help from <a href="http://llvm.org/svn/llvm-project/libcxx/trunk/include/vector" rel="nofollow">the implementation of the vector class from the STL</a>. Now, a few questions I have about the code I've written so far:</p>

<ol>
<li><p>When returning iterators, I wasn't sure if I should lock the mutex and then   return the iterator because of the possibility that the validity of the iterator(s) might change due to multiple threads trying to access it, so I went ahead and locked the mutex for all non-const iterators. Is this the right approach?</p></li>
<li><p>It is my understanding that one should not return pointers from functions when dealing with multithreaded code since this provides a "backdoor" (for lack of a better term) for user code to preform some potentially questionable activity. So, for the implementation of the <a href="http://www.cplusplus.com/reference/vector/vector/operator=/" rel="nofollow">assignment operator</a>, is there another way to write these functions so that it doesn't return *this?</p></li>
<li><p>I opted to use all local instances of lock_guard instead of having one as a private data member. Would it be better if I had one as a private data member instead?</p></li>
</ol>

<p>Many thanks in advance :-)</p>