<commit_before>#include <glbinding/logging.h>

#include <atomic>
#include <condition_variable>
#include <fstream>
#include <mutex>
#include <sstream>
#include <thread>

#include "RingBuffer.h"

namespace
{
    const unsigned int LOG_BUFFER_SIZE = 1000000;

    std::atomic<bool> g_stop{false};
    std::atomic<bool> g_persisted{false};
    std::mutex g_lockfinish;
    std::condition_variable g_finishcheck;

    using FunctionCallBuffer = glbinding::RingBuffer<glbinding::logging::BufferType>;
    FunctionCallBuffer g_buffer{LOG_BUFFER_SIZE};
}

namespace glbinding
{

namespace logging
{

void start()
{
    auto now = std::chrono::system_clock::now();


    auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    auto ms = now_ms.count() % 1000;

    auto now_c = std::chrono::system_clock::to_time_t(now);
    char time_string[20];
    std::strftime(time_string, sizeof(time_string), "%Y-%m-%d_%H-%M-%S", std::localtime(&now_c));

    std::ostringstream ms_os;
    ms_os << std::setfill('0') << std::setw(3) << ms;

    std::ostringstream os;
    os << "logs/";
    os << time_string << "-" << ms_os.str();
    os << ".log";
    
    auto logname = os.str();

    start(logname);
}

void start(const std::string & filepath)
{
    addCallbackMask(CallbackMask::Logging);

    g_stop = false;
    g_persisted = false;

    std::thread writer([filepath]()
    {
        auto key = g_buffer.addTail();
        std::ofstream logfile;
        logfile.open (filepath, std::ios::out);

        while (!g_stop || (g_buffer.size(key) != 0))
        {
            auto i = g_buffer.cbegin(key);

            while (g_buffer.valid(key, i))
            {
                logfile << (*i)->toString();
                i = g_buffer.next(key, i);
            }

            logfile.flush();

            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }

        logfile.close();
        g_buffer.removeTail(key);
        g_persisted = true;
        g_finishcheck.notify_all();
    });

    writer.detach();
}

void stop()
{
    g_stop = true;
    std::unique_lock<std::mutex> locker(g_lockfinish);

    // Spurious wake-ups: http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
    while(!g_persisted)
    {
        g_finishcheck.wait(locker);
    }

    removeCallbackMask(CallbackMask::Logging);
}

void pause()
{
    removeCallbackMask(CallbackMask::Logging);
}

void resume()<commit_msg>Change position of removing Callback mask<commit_after>#include <glbinding/logging.h>

#include <atomic>
#include <condition_variable>
#include <fstream>
#include <mutex>
#include <sstream>
#include <thread>

#include "RingBuffer.h"

namespace
{
    const unsigned int LOG_BUFFER_SIZE = 1000000;

    std::atomic<bool> g_stop{false};
    std::atomic<bool> g_persisted{false};
    std::mutex g_lockfinish;
    std::condition_variable g_finishcheck;

    using FunctionCallBuffer = glbinding::RingBuffer<glbinding::logging::BufferType>;
    FunctionCallBuffer g_buffer{LOG_BUFFER_SIZE};
}

namespace glbinding
{

namespace logging
{

void start()
{
    auto now = std::chrono::system_clock::now();


    auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    auto ms = now_ms.count() % 1000;

    auto now_c = std::chrono::system_clock::to_time_t(now);
    char time_string[20];
    std::strftime(time_string, sizeof(time_string), "%Y-%m-%d_%H-%M-%S", std::localtime(&now_c));

    std::ostringstream ms_os;
    ms_os << std::setfill('0') << std::setw(3) << ms;

    std::ostringstream os;
    os << "logs/";
    os << time_string << "-" << ms_os.str();
    os << ".log";
    
    auto logname = os.str();

    start(logname);
}

void start(const std::string & filepath)
{
    addCallbackMask(CallbackMask::Logging);

    g_stop = false;
    g_persisted = false;

    std::thread writer([filepath]()
    {
        auto key = g_buffer.addTail();
        std::ofstream logfile;
        logfile.open (filepath, std::ios::out);

        while (!g_stop || (g_buffer.size(key) != 0))
        {
            auto i = g_buffer.cbegin(key);

            while (g_buffer.valid(key, i))
            {
                logfile << (*i)->toString();
                i = g_buffer.next(key, i);
            }

            logfile.flush();

            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }

        logfile.close();
        g_buffer.removeTail(key);
        g_persisted = true;
        g_finishcheck.notify_all();
    });

    writer.detach();
}

void stop()
{
    removeCallbackMask(CallbackMask::Logging);

    g_stop = true;
    std::unique_lock<std::mutex> locker(g_lockfinish);

    // Spurious wake-ups: http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
    while(!g_persisted)
    {
        g_finishcheck.wait(locker);
    }
}

void pause()
{
    removeCallbackMask(CallbackMask::Logging);
}

void resume()
{'fraction_non_alphanumeric': 0.15276663993584602, 'fraction_numerical': 0.009623095429029671, 'mean_word_length': 3.1575, 'pattern_counts': {'":': 0, '<': 63, '<?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': '5090411', 'n_tokens_mistral': 1745, 'n_tokens_neox': 1664, 'n_words': 280}