Init commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 这是一个线程不安全(单线程)版的event,不可以用于多线程
|
||||
*/
|
||||
#ifndef ZCPPWIN_EVENT_HPP
|
||||
#define ZCPPWIN_EVENT_HPP
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
namespace Z {
|
||||
template<typename... Args>
|
||||
class Event {
|
||||
public:
|
||||
using Callback = std::function<void(Args...)>;
|
||||
private: //region Event::private
|
||||
struct Handle {
|
||||
uint64_t id{};
|
||||
std::weak_ptr<void> guard;
|
||||
Callback cb;
|
||||
};
|
||||
struct State {
|
||||
uint64_t nextID{1};
|
||||
};
|
||||
void Disconn_(uint64_t id) {
|
||||
m_handles.erase(id);
|
||||
}
|
||||
static bool IsAlive(Handle &h) {
|
||||
// guard为null->活
|
||||
if (!h.guard.owner_before(std::weak_ptr<void>{}) &&
|
||||
!std::weak_ptr<void>{}.owner_before(h.guard)) {
|
||||
return true;
|
||||
}
|
||||
// guard非null且已死->死
|
||||
if (h.guard.expired())return false;
|
||||
// guard非null且活->活
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<State> m_state;
|
||||
std::unordered_map<uint64_t, Handle> m_handles;
|
||||
public:
|
||||
class Connection { //region class Connection
|
||||
public:
|
||||
Connection() = default;
|
||||
Connection(const Connection &) = delete;
|
||||
Connection &operator=(const Connection &) = delete;
|
||||
|
||||
Connection(Connection &&other) noexcept { MoveFrom(std::move(other)); }
|
||||
Connection &operator=(Connection &&other) noexcept {
|
||||
if (this != &other) {
|
||||
Disconnect();
|
||||
MoveFrom(std::move(other));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Connection() { Disconnect(); }
|
||||
private:
|
||||
friend class Event;
|
||||
Connection(uint64_t id, Event *owner, std::weak_ptr<State> wp) :
|
||||
m_id(id), m_owner(owner), guard_state(wp) {}
|
||||
void Disconnect() {
|
||||
if (m_id == 0 || guard_state.expired()) { return; }
|
||||
m_owner->Disconn_(m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
void MoveFrom(Connection &&other) noexcept {
|
||||
m_owner = other.m_owner;
|
||||
m_id = other.m_id;
|
||||
other.m_owner = nullptr;
|
||||
other.m_id = 0;
|
||||
}
|
||||
private:
|
||||
uint64_t m_id;
|
||||
Event *m_owner;
|
||||
const std::weak_ptr<State> guard_state;
|
||||
}; //Class Connection
|
||||
|
||||
Event() {
|
||||
m_state = std::make_shared<State>();
|
||||
}
|
||||
Connection Subscribe(Callback cb) {
|
||||
|
||||
Handle h{m_state->nextID++, {}, std::move(cb)};
|
||||
m_handles.emplace(h.id, std::move(h));
|
||||
return {h.id, this, std::weak_ptr{m_state}};
|
||||
}
|
||||
void EmitEvent(Args... args) {
|
||||
std::vector<uint64_t> cleanIds{};
|
||||
for (auto &kv: m_handles) {
|
||||
if (!IsAlive(kv.second)) {
|
||||
cleanIds.push_back(kv.first);
|
||||
} else {
|
||||
kv.second.cb(args...);
|
||||
}
|
||||
}
|
||||
if (!cleanIds.empty()) {
|
||||
for (auto &id: cleanIds) {
|
||||
m_handles.erase(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //ZCPPWIN_EVENT_HPP
|
||||
Reference in New Issue
Block a user