Skip to content

Commit

Permalink
Data handling (#11)
Browse files Browse the repository at this point in the history
* move data into shared_ptr

* v2.0.2

* remove default constructor

* fix move constructor

* reset when observing new event
  • Loading branch information
TheLartians authored Apr 22, 2019
1 parent d3fbd8a commit 5f92c76
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 48 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
# ---- Project ----

project(LarsEvent
VERSION 2.0.1
VERSION 2.0.2
LANGUAGES CXX
)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ With [CPM](https://github.com/TheLartians/CPM), lars::Event can be added to your
```cmake
CPMAddPackage(
NAME LarsEvent
VERSION 2.0.1
VERSION 2.0.2
GIT_REPOSITORY https://github.com/TheLartians/Event.git
)
Expand Down
80 changes: 34 additions & 46 deletions include/lars/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,35 +49,29 @@ namespace lars{
};

using HandlerList = std::vector<StoredHandler>;
using EventPointer = std::shared_ptr<const Event *>;
using WeakEventPointer = std::weak_ptr<const Event *>;

mutable HandlerID IDCounter = 0;
mutable HandlerList observers;
mutable std::mutex observerMutex;
EventPointer self;
struct Data {
HandlerID IDCounter = 0;
HandlerList observers;
std::mutex observerMutex;
};

std::shared_ptr<Data> data;

HandlerID addHandler(Handler h)const{
std::lock_guard<std::mutex> lock(observerMutex);
observers.emplace_back(StoredHandler{IDCounter,h});
return IDCounter++;
}

void eraseHandler(const HandlerID &id)const{
std::lock_guard<std::mutex> lock(observerMutex);
auto it = std::find_if(observers.begin(), observers.end(), [&](auto &o){ return o.id == id; });
if (it != observers.end()) { observers.erase(it); }
std::lock_guard<std::mutex> lock(data->observerMutex);
data->observers.emplace_back(StoredHandler{data->IDCounter,h});
return data->IDCounter++;
}

public:

struct Observer:public lars::Observer::Base{
WeakEventPointer parent;
std::weak_ptr<Data> data;
HandlerID id;

Observer(){}
Observer(const EventPointer & _parent, HandlerID _id):parent(_parent), id(_id){
}
Observer(const std::weak_ptr<Data> &_data, HandlerID _id):data(_data), id(_id){}

Observer(Observer &&other) = default;
Observer(const Observer &other) = delete;
Expand All @@ -86,64 +80,58 @@ namespace lars{
Observer & operator=(Observer &&other)=default;

void observe(const Event &event, const Handler &handler){
reset();
*this = event.createObserver(handler);
}

void reset(){
if(auto p = parent.lock()){
(*p)->eraseHandler(id);
if(auto d = data.lock()){
std::lock_guard<std::mutex> lock(d->observerMutex);
auto it = std::find_if(d->observers.begin(), d->observers.end(), [&](auto &o){ return o.id == id; });
if (it != d->observers.end()) { d->observers.erase(it); }
}
parent.reset();
data.reset();
}

~Observer(){ reset(); }
};

Event():self(std::make_shared<const Event *>(this)){

Event():data(std::make_shared<Data>()){
}

Event(const Event &) = delete;

Event(Event &&other){
*this = std::move(other);
}

Event & operator=(const Event &) = delete;

Event & operator=(Event &&other){
self = std::move(other.self);
*self = this;
observers = std::move(other.observers);
IDCounter = other.IDCounter;
Event(const Event &) = delete;
Event(Event &&other):Event(){ *this = std::move(other); }
Event &operator=(const Event &) = delete;
Event &operator=(Event &&other){
std::swap(data, other.data);
return *this;
}

void emit(Args ... args) const {
observerMutex.lock();
auto tmpObservers = observers;
observerMutex.unlock();
data->observerMutex.lock();
auto tmpObservers = data->observers;
data->observerMutex.unlock();
for(auto &observer: tmpObservers){
observer.callback(args...);
}
}

Observer createObserver(const Handler &h)const{
return Observer(self, addHandler(h));
return Observer(data, addHandler(h));
}

void connect(const Handler &h)const{
addHandler(h);
}

void clearObservers(){
std::lock_guard<std::mutex> lock(observerMutex);
observers.clear();
std::lock_guard<std::mutex> lock(data->observerMutex);
data->observers.clear();
}

size_t observerCount() const {
std::lock_guard<std::mutex> lock(observerMutex);
return observers.size();
std::lock_guard<std::mutex> lock(data->observerMutex);
return data->observers.size();
}

};
Expand Down

0 comments on commit 5f92c76

Please sign in to comment.