<commit_before>/*
 This file is part of MMOServer. For more information, visit http://swganh.com
 
 Copyright (c) 2006 - 2010 The SWG:ANH Team

 MMOServer is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 MMOServer is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with MMOServer.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "anh/event_dispatcher/event_dispatcher.h"

#include <cassert>
#include <algorithm>

#include <boost/date_time/posix_time/posix_time.hpp>

using namespace anh::event_dispatcher;
using namespace boost::posix_time;
using namespace std;

EventDispatcher::EventDispatcher()
    : event_queues_(NUM_QUEUES)
    , active_queue_(0)
{
    next_event_listener_id_.fetch_and_store(1);
}

EventDispatcher::~EventDispatcher() {
    active_queue_ = 0;
}


uint64_t EventDispatcher::subscribe(const EventType& event_type, EventListenerCallback listener) {
    if (!validateEventType_(event_type)) {
        throw anh::event_dispatcher::InvalidEventType(
            "Invalid event type specified");
    }
    
    registerEventType(event_type);

    EventListenerMap::accessor a;

    if (!event_listeners_.find(a, event_type)) {
        // Check if there was an insertion failure
        if (!event_listeners_.insert(a,event_type)) {
            throw std::runtime_error("Insertion failure");
        }

        a->second = EventListenerList();
    }

    EventListenerList& listener_list = a->second;    

    uint64_t next_listener_id = next_event_listener_id_.fetch_and_increment();
    listener_list.push_back(make_pair(next_listener_id, listener));

    return next_listener_id;
}

bool EventDispatcher::hasListeners(const EventType& event_type) const {
    EventListenerMap::accessor a;
    if (!event_listeners_.find(a, event_type)) {
        return false;
    }

    const EventListenerList& listener_list = a->second;

    return !listener_list.empty();
}

bool EventDispatcher::hasRegisteredEventType(const EventType& event_type) {   
    boost::lock_guard<boost::recursive_mutex> lk(event_set_mutex_);

    if (registered_event_types_.find(event_type) != registered_event_types_.end()) {
        return true;
    }

    return false;
}

bool EventDispatcher::hasEvents() const {
    return !event_queues_[active_queue_].empty();
}

void EventDispatcher::registerEventType(EventType event_type) {   
    boost::lock_guard<boost::recursive_mutex> lk(event_set_mutex_);

    if (hasRegisteredEventType(event_type)) {
        return;
    }
    
    registered_event_types_.insert(std::move(event_type));
}

EventTypeSet EventDispatcher::registered_event_types() const {
    return registered_event_types_;
}


void EventDispatcher::unsubscribe(const EventType& event_type, uint64_t listener_id) {
    EventListenerMap::accessor a;
    if (event_listeners_.find(a, event_type)) {
        return;
    }

    EventListenerList& listener_list = a->second;

    EventListenerList tmp;
    for_each(listener_list.begin(), listener_list.end(), [&tmp, &listener_id] (EventListener& list_listener) {
        if (list_listener.first == listener_id) {
            tmp.push_back(list_listener);
        }
    });
    
    listener_list.swap(tmp);
}

void EventDispatcher::unsubscribe(const EventType& event_type) {
    EventListenerMap::accessor a;
    if (event_listeners_.find(a, event_type)) {
        return;
    }

    a->second.clear();
}

bool EventDispatcher::trigger(std::shared_ptr<EventInterface> incoming_event) {
    const EventType& event_type = incoming_event->type();<commit_msg>Regression fix from last commit.<commit_after>/*
 This file is part of MMOServer. For more information, visit http://swganh.com
 
 Copyright (c) 2006 - 2010 The SWG:ANH Team

 MMOServer is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 MMOServer is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with MMOServer.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "anh/event_dispatcher/event_dispatcher.h"

#include <cassert>
#include <algorithm>

#include <boost/date_time/posix_time/posix_time.hpp>

using namespace anh::event_dispatcher;
using namespace boost::posix_time;
using namespace std;

EventDispatcher::EventDispatcher()
    : event_queues_(NUM_QUEUES)
    , active_queue_(0)
{
    next_event_listener_id_.fetch_and_store(1);
}

EventDispatcher::~EventDispatcher() {
    active_queue_ = 0;
}


uint64_t EventDispatcher::subscribe(const EventType& event_type, EventListenerCallback listener) {
    if (!validateEventType_(event_type)) {
        throw anh::event_dispatcher::InvalidEventType(
            "Invalid event type specified");
    }
    
    registerEventType(event_type);

    EventListenerMap::accessor a;

    if (!event_listeners_.find(a, event_type)) {
        // Check if there was an insertion failure
        if (!event_listeners_.insert(a,event_type)) {
            throw std::runtime_error("Insertion failure");
        }

        a->second = EventListenerList();
    }

    EventListenerList& listener_list = a->second;    

    uint64_t next_listener_id = next_event_listener_id_.fetch_and_increment();
    listener_list.push_back(make_pair(next_listener_id, listener));

    return next_listener_id;
}

bool EventDispatcher::hasListeners(const EventType& event_type) const {
    EventListenerMap::accessor a;
    if (!event_listeners_.find(a, event_type)) {
        return false;
    }

    const EventListenerList& listener_list = a->second;

    return !listener_list.empty();
}

bool EventDispatcher::hasRegisteredEventType(const EventType& event_type) {   
    boost::lock_guard<boost::recursive_mutex> lk(event_set_mutex_);

    if (registered_event_types_.find(event_type) != registered_event_types_.end()) {
        return true;
    }

    return false;
}

bool EventDispatcher::hasEvents() const {
    return !event_queues_[active_queue_].empty();
}

void EventDispatcher::registerEventType(EventType event_type) {   
    boost::lock_guard<boost::recursive_mutex> lk(event_set_mutex_);

    if (hasRegisteredEventType(event_type)) {
        return;
    }
    
    registered_event_types_.insert(std::move(event_type));
}

EventTypeSet EventDispatcher::registered_event_types() const {
    return registered_event_types_;
}


void EventDispatcher::unsubscribe(const EventType& event_type, uint64_t listener_id) {
    EventListenerMap::accessor a;
    if (!event_listeners_.find(a, event_type)) {
        return;
    }

    EventListenerList& listener_list = a->second;

    EventListenerList tmp;
    for_each(listener_list.begin(), listener_list.end(), [&tmp, &listener_id] (EventListener& list_listener) {
        if (list_listener.first != listener_id) {
            tmp.push_back(list_listener);
        }
    });
    
    listener_list.swap(tmp);
}

void EventDispatcher::unsubscribe(const EventType& event_type) {
    EventListenerMap::accessor a;
    if (!event_listeners_.find(a, event_type)) {
        return;
    }

    a->second.clear();
}

bool EventDispatcher::trigger(std::shared_ptr<EventInterface> incoming_event) {
    const EventType& event_type = incoming_event->type();
{'fraction_non_alphanumeric': 0.09768734993049412, 'fraction_numerical': 0.0045494755465689376, 'mean_word_length': 4.179319371727749, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3007895', 'n_tokens_mistral': 2420, 'n_tokens_neox': 2303, 'n_words': 561}