<commit_before>//
// Created by permal on 10/22/17.
//

#include <smooth/core/timer/TimerService.h>
#include <smooth/core/timer/Timer.h>
#include <smooth/core/task_priorities.h>

using namespace smooth::core::logging;
using namespace std::chrono;

namespace smooth
{
    namespace core
    {
        namespace timer
        {
            TimerService::TimerService()
                    : Task("TimerService",
                           2048,
                           TIMER_SERVICE_PRIO,
                           milliseconds(0)),
                      cmp([](SharedTimer left, SharedTimer right)
                          {
                              // We want the timer with the least time left to be first in the list
                              return left->expires_at() > right->expires_at();
                          }),
                      queue(cmp),
                      guard(),
                      processed()
            {
            }


            TimerService& TimerService::get()
            {
                static TimerService service;
                return service;
            }

            void TimerService::start_service()
            {
                get().start();
            }

            void TimerService::add_timer(SharedTimer timer)
            {
                std::lock_guard<std::mutex> lock(guard);
                timer->calculate_next_execution();
                queue.push(timer);
                cond.notify_one();
            }

            void TimerService::remove_timer(SharedTimer timer)
            {
                std::lock_guard<std::mutex> lock(guard);
                queue.remove_timer(timer);
                cond.notify_one();
            }

            void TimerService::tick()
            {
                std::unique_lock<std::mutex> lock(guard);
                processed.clear();

                if (queue.empty())
                {
                    // No timers, wait until one is added.
                    cond.wait_for(lock, seconds(1));
                }
                else
                {
                    // Get a fixed 'now'
                    auto now = steady_clock::now();

                    // Process any expired timers
                    while (!queue.empty() && now >= queue.top()->expires_at())
                    {
                        auto timer = queue.top();
                        timer->expired();

                        // Timer expired, remove from queue
                        queue.pop();

                        // Save timer to later add it, if repeating.
                        // Otherwise, simply forget about it.
                        if (timer->is_repeating())
                        {
                            processed.push_back(timer);
                        }
                    }

                    for (auto& t : processed)
                    {
                        t->calculate_next_execution();
                        queue.push(t);
                    }

                    if (!queue.empty())
                    {
                        // Get next timer to expire
                        auto timer = queue.top();
                        auto next_expire_time = timer->expires_at();

                        auto diff = next_expire_time - now;

                        // Wait for the timer to expire, or a timer to be removed or added.
                        auto current_queue_length = queue.size();

                        cond.wait_until(lock,
                                        next_expire_time,
                                        [current_queue_length, this]()
                                        {
                                            // Wake up if a timer has been added or removed.
                                            return current_queue_length != queue.size();
                                        });
                    }
                }<commit_msg>Remove debug artifacts.<commit_after>//
// Created by permal on 10/22/17.
//

#include <smooth/core/timer/TimerService.h>
#include <smooth/core/timer/Timer.h>
#include <smooth/core/task_priorities.h>

using namespace smooth::core::logging;
using namespace std::chrono;

namespace smooth
{
    namespace core
    {
        namespace timer
        {
            TimerService::TimerService()
                    : Task("TimerService",
                           2048,
                           TIMER_SERVICE_PRIO,
                           milliseconds(0)),
                      cmp([](SharedTimer left, SharedTimer right)
                          {
                              // We want the timer with the least time left to be first in the list
                              return left->expires_at() > right->expires_at();
                          }),
                      queue(cmp),
                      guard(),
                      processed()
            {
            }


            TimerService& TimerService::get()
            {
                static TimerService service;
                return service;
            }

            void TimerService::start_service()
            {
                get().start();
            }

            void TimerService::add_timer(SharedTimer timer)
            {
                std::lock_guard<std::mutex> lock(guard);
                timer->calculate_next_execution();
                queue.push(timer);
                cond.notify_one();
            }

            void TimerService::remove_timer(SharedTimer timer)
            {
                std::lock_guard<std::mutex> lock(guard);
                queue.remove_timer(timer);
                cond.notify_one();
            }

            void TimerService::tick()
            {
                std::unique_lock<std::mutex> lock(guard);
                processed.clear();

                if (queue.empty())
                {
                    // No timers, wait until one is added.
                    cond.wait_for(lock, seconds(1));
                }
                else
                {
                    // Get a fixed 'now'
                    auto now = steady_clock::now();

                    // Process any expired timers
                    while (!queue.empty() && now >= queue.top()->expires_at())
                    {
                        auto timer = queue.top();
                        timer->expired();

                        // Timer expired, remove from queue
                        queue.pop();

                        // Save timer to later add it, if repeating.
                        // Otherwise, simply forget about it.
                        if (timer->is_repeating())
                        {
                            processed.push_back(timer);
                        }
                    }

                    for (auto& t : processed)
                    {
                        t->calculate_next_execution();
                        queue.push(t);
                    }

                    if (!queue.empty())
                    {
                        // Get next timer to expire
                        auto timer = queue.top();

                        // Wait for the timer to expire, or a timer to be removed or added.
                        auto current_queue_length = queue.size();

                        cond.wait_until(lock,
                                        timer->expires_at(),
                                        [current_queue_length, this]()
                                        {
                                            // Wake up if a timer has been added or removed.
                                            return current_queue_length != queue.size();
                                        });
                    }
                }
{'fraction_non_alphanumeric': 0.08590054966125528, 'fraction_numerical': 0.00306787677361626, 'mean_word_length': 0.8487712665406427, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1433285', 'n_tokens_mistral': 1772, 'n_tokens_neox': 1574, 'n_words': 383}