先看LockedQueue.h
template <class T, typename StorageType = std::deque<T> >
class LockedQueue{......}
一个带锁的多线程可安全访问的类,容器默认使用std::deque
常规代码 push进T类型的元素 pop出T类型的元素
使用锁定 保证线程安全
相比C++11之前的繁琐做法 现在加锁可以使用 std::lock_guard
当使用std::lock_guard<std::mutex> lock(_lock)后 代码进入加锁模式
脱出lock的变量生存周期时候 自动解锁
代码如下
1 /* 2 * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> 3 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef LOCKEDQUEUE_H 20 #define LOCKEDQUEUE_H 21 22 #include <deque> 23 #include <mutex> 24 25 template <class T, typename StorageType = std::deque<T> > 26 class LockedQueue 27 { 28 //! Lock access to the queue. 29 std::mutex _lock; 30 31 //! Storage backing the queue. 32 StorageType _queue; 33 34 //! Cancellation flag. 35 volatile bool _canceled; 36 37 public: 38 39 //! Create a LockedQueue. 40 LockedQueue() 41 : _canceled(false) 42 { 43 } 44 45 //! Destroy a LockedQueue. 46 virtual ~LockedQueue() 47 { 48 } 49 50 //! Adds an item to the queue. 51 void add(const T& item) 52 { 53 lock(); 54 55 _queue.push_back(item); 56 57 unlock(); 58 } 59 60 //! Adds items back to front of the queue 61 template<class Iterator> 62 void readd(Iterator begin, Iterator end) 63 { 64 std::lock_guard<std::mutex> lock(_lock); 65 _queue.insert(_queue.begin(), begin, end); 66 } 67 68 //! Gets the next result in the queue, if any. 69 bool next(T& result) 70 { 71 std::lock_guard<std::mutex> lock(_lock); 72 73 if (_queue.empty()) 74 return false; 75 76 result = _queue.front(); 77 _queue.pop_front(); 78 79 return true; 80 } 81 82 template<class Checker> 83 bool next(T& result, Checker& check) 84 { 85 std::lock_guard<std::mutex> lock(_lock); 86 87 if (_queue.empty()) 88 return false; 89 90 result = _queue.front(); 91 if (!check.Process(result)) 92 return false; 93 94 _queue.pop_front(); 95 return true; 96 } 97 98 //! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false. 99 T& peek(bool autoUnlock = false) 100 { 101 lock(); 102 103 T& result = _queue.front(); 104 105 if (autoUnlock) 106 unlock(); 107 108 return result; 109 } 110 111 //! Cancels the queue. 112 void cancel() 113 { 114 std::lock_guard<std::mutex> lock(_lock); 115 116 _canceled = true; 117 } 118 119 //! Checks if the queue is cancelled. 120 bool cancelled() 121 { 122 std::lock_guard<std::mutex> lock(_lock); 123 return _canceled; 124 } 125 126 //! Locks the queue for access. 127 void lock() 128 { 129 this->_lock.lock(); 130 } 131 132 //! Unlocks the queue. 133 void unlock() 134 { 135 this->_lock.unlock(); 136 } 137 138 ///! Calls pop_front of the queue 139 void pop_front() 140 { 141 std::lock_guard<std::mutex> lock(_lock); 142 _queue.pop_front(); 143 } 144 145 ///! Checks if we're empty or not with locks held 146 bool empty() 147 { 148 std::lock_guard<std::mutex> lock(_lock); 149 return _queue.empty(); 150 } 151 }; 152 #endif