TrinityCore 项目简介:
TrinityCore 是一个开源项目,旨在提供一个高性能的 MMO 游戏服务器(例如《魔兽世界》)的框架。该项目实现了游戏的服务器端逻辑,支持多种协议和客户端版本,能够模拟游戏世界、玩家行为、战斗系统等核心功能。
TrinityCore 的主要特点包括:
- 高性能:通过高效的数据库结构和多线程支持,TrinityCore 能够在大规模玩家环境下保持良好的性能。
- 可扩展性:支持插件和自定义脚本,允许开发者扩展功能或修改游戏行为。
- 跨平台:支持 Windows 和 Linux 系统。
- 开源:通过 GitHub 上的开源代码库,任何人都可以查看、修改和贡献代码。
TrinityCore 包含多个模块,如:
- 世界服务器:处理游戏逻辑、玩家交互等。
- 数据库服务:管理游戏数据,如角色信息、物品、任务等。
- 登录服务器:处理玩家的登录请求并进行身份验证。
- 脚本系统:允许开发者编写 Lua 或 C++ 脚本来扩展服务器功能。
克隆 TrinityCore 仓库
git clone https://github.com/TrinityCore/TrinityCore.git
LockedQueue.h
有锁队列操作:
LockedQueue.h
文件通常定义了一个线程安全的队列(锁定队列),通常用于在多线程环境下安全地进行数据传递和处理。此文件包含了与互斥量、条件变量等同步原语相关的实现,以保证在多个线程之间共享队列时,数据的一致性和安全性。
在 TrinityCore 中,LockedQueue
是一个常用的数据结构,它通常用于任务队列、网络消息队列等场景。该队列保证在多线程环境下对队列的操作是线程安全的,防止出现竞争条件。
LockedQueue.h
文件的位置 : 在 TrinityCore 项目中,LockedQueue.h
文件一般位于以下路径:
TrinityCore/src/server/shared/LockedQueue.h
该文件实现了一个模板类 LockedQueue
,允许存储任意类型的元素,并在多线程环境下提供基本的队列操作(如插入、删除、查询等)同时保证线程安全。
LockedQueue.h
cpp
#ifndef MARK_LOCKEDQUEUE_H
#define MARK_LOCKEDQUEUE_H
#include <deque>
#include <mutex>
template <class T, typename StorageType = std::deque<T> >
class LockedQueue
{
//! Lock access to the queue.
std::mutex _lock;
//! Storage backing the queue.
StorageType _queue;
//! Cancellation flag.
volatile bool _canceled;
public:
//! Create a LockedQueue.
LockedQueue()
: _canceled(false)
{
}
//! Destroy a LockedQueue.
virtual ~LockedQueue()
{
}
//! Adds an item to the queue.
void add(const T& item)
{
lock();
_queue.push_back(item);
unlock();
}
//! Adds items back to front of the queue
template<class Iterator>
void readd(Iterator begin, Iterator end)
{
std::lock_guard<std::mutex> lock(_lock);
_queue.insert(_queue.begin(), begin, end);
}
//! Gets the next result in the queue, if any.
bool next(T& result)
{
std::lock_guard<std::mutex> lock(_lock);
if (_queue.empty())
return false;
result = _queue.front();
_queue.pop_front();
return true;
}
template<class Checker>
bool next(T& result, Checker& check)
{
std::lock_guard<std::mutex> lock(_lock);
if (_queue.empty())
return false;
result = _queue.front();
if (!check.Process(result))
return false;
_queue.pop_front();
return true;
}
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
T& peek(bool autoUnlock = false)
{
lock();
T& result = _queue.front();
if (autoUnlock)
unlock();
return result;
}
//! Cancels the queue.
void cancel()
{
std::lock_guard<std::mutex> lock(_lock);
_canceled = true;
}
//! Checks if the queue is cancelled.
bool cancelled()
{
std::lock_guard<std::mutex> lock(_lock);
return _canceled;
}
//! Locks the queue for access.
void lock()
{
this->_lock.lock();
}
//! Unlocks the queue.
void unlock()
{
this->_lock.unlock();
}
///! Calls pop_front of the queue
void pop_front()
{
std::lock_guard<std::mutex> lock(_lock);
_queue.pop_front();
}
///! Checks if we're empty or not with locks held
bool empty()
{
std::lock_guard<std::mutex> lock(_lock);
return _queue.empty();
}
};
#endif
test.cpp
cpp
#include "LockedQueue.h"
#include <iostream>
class MyData {
public:
int id;
std::string name;
MyData() {}
MyData(int i, const std::string &n) : id(i), name(n) {}
void print() const {
std::cout << "ID:" << id << ", name:" << name << std::endl;
}
};
int main() {
LockedQueue <MyData>queue;
queue.add(MyData(5, "Item 1"));
queue.add(MyData(15, "Item 2"));
queue.add(MyData(20, "Item 3"));
MyData tmp;
if (queue.next(tmp)) {
tmp.print();
}
// 使用 readd 方法将多个元素重新放回队列前端
std::deque<MyData> items = {MyData(30, "Item 4"), MyData(35, "Item 5")};
queue.readd(items.begin(), items.end());
if (queue.next(tmp)) {
tmp.print();
}
// 查看队列中的第一个元素,但不移除它
MyData& peekItem = queue.peek();
std::cout << "Peek: ";
peekItem.print();
// 检查队列是否为空
std::cout << "Queue empty: " << std::boolalpha << queue.empty() << std::endl;
// 获取并打印队列中剩余的所有元素
while (queue.next(tmp))
{
tmp.print();
}
// 将队列标记为已取消
queue.cancel();
std::cout << "Queue canceled: " << std::boolalpha << queue.cancelled() << std::endl;
}