<commit_before>#if _WIN32
#define _WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif

#include <chrono>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <stdio.h>
#include "LogVisor/LogVisor.hpp"

/* ANSI sequences */
#define RED "\x1b[1;31m"
#define YELLOW "\x1b[1;33m"
#define GREEN "\x1b[1;32m"
#define MAGENTA "\x1b[1;35m"
#define CYAN "\x1b[1;36m"
#define BOLD "\x1b[1m"
#define NORMAL "\x1b[0m"

namespace LogVisor
{

static std::unordered_map<std::thread::id, const char*> ThreadMap;
void RegisterThreadName(const char* name)
{
    ThreadMap[std::this_thread::get_id()] = name;
#if __APPLE__
    pthread_setname_np(name);
#elif __linux__
    pthread_setname_np(pthread_self(), name);
#elif _MSC_VER
    struct
    {
        DWORD dwType; // Must be 0x1000.
        LPCSTR szName; // Pointer to name (in user addr space).
        DWORD dwThreadID; // Thread ID (-1=caller thread).
        DWORD dwFlags; // Reserved for future use, must be zero.
    } info = {0x1000, name, (DWORD)-1, 0};
    __try
    {
        RaiseException(0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
    }
#endif
}

std::vector<std::unique_ptr<ILogger>> MainLoggers;
static std::chrono::steady_clock MonoClock;
static std::chrono::steady_clock::time_point GlobalStart = MonoClock.now();
static inline std::chrono::steady_clock::duration CurrentUptime()
{return MonoClock.now() - GlobalStart;}
uint64_t FrameIndex = 0;

#if _WIN32
static HANDLE Term = 0;
#else
static const char* Term = nullptr;
#endif
static bool XtermColor = false;
struct ConsoleLogger : public ILogger
{
    std::mutex m;
    ConsoleLogger()
    {
#if _WIN32
        if (!Term)
            Term = GetStdHandle(STD_ERROR_HANDLE);
#else
        if (!Term)
        {
            Term = getenv("TERM");
            if (!strncmp(Term, "xterm", 5))
            {
                XtermColor = true;
                putenv((char*)"TERM=xterm-16color");
            }
        }
#endif
    }

    static void _reportHead(const char* modName, const char* sourceInfo, Level severity)
    {
        std::chrono::steady_clock::duration tm = CurrentUptime();
        double tmd = tm.count() *
            std::chrono::steady_clock::duration::period::num /
            (double)std::chrono::steady_clock::duration::period::den;
        std::thread::id thrId = std::this_thread::get_id();
        const char* thrName = nullptr;
        if (ThreadMap.find(thrId) != ThreadMap.end())
            thrName = ThreadMap[thrId];

#if _WIN32
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY);
        fprintf(stderr, "[");
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
        fprintf(stderr, "%5.4f ", tmd);
        if (FrameIndex)
            fprintf(stderr, "(%llu) ", FrameIndex);
        switch (severity)
        {
        case Info:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
            fprintf(stderr, "INFO");
            break;
        case Warning:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
            fprintf(stderr, "WARNING");
            break;
        case Error:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED);
            fprintf(stderr, "ERROR");
            break;
        case FatalError:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED);
            fprintf(stderr, "FATAL ERROR");
            break;
        default:
            break;
        };
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY);
        fprintf(stderr, " %s", modName);
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
        if (sourceInfo)
            fprintf(stderr, " {%s}", sourceInfo);
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
        if (thrName)
            fprintf(stderr, " (%s)", thrName);
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY);
        fprintf(stderr, "] ");
        SetConsoleTextAttribute(Term, 0);
#else
        if (XtermColor)
        {
            fprintf(stderr, BOLD "[");
            fprintf(stderr, GREEN "%5.4f ", tmd);
            if (FrameIndex)
                fprintf(stderr, "(%lu) ", FrameIndex);
            switch (severity)
            {
            case Info:
                fprintf(stderr, BOLD CYAN "INFO");
                break;
            case Warning:
                fprintf(stderr, BOLD YELLOW "WARNING");
                break;
            case Error:
                fprintf(stderr, RED BOLD "ERROR");
                break;
            case FatalError:
                fprintf(stderr, BOLD RED "FATAL ERROR");
                break;
            default:
                break;
            };
            fprintf(stderr, NORMAL BOLD " %s", modName);
            if (sourceInfo)
                fprintf(stderr, BOLD YELLOW " {%s}", sourceInfo);
            if (thrName)
                fprintf(stderr, BOLD MAGENTA " (%s)", thrName);
            fprintf(stderr, NORMAL BOLD "] " NORMAL);
        }
        else
        {
            fprintf(stderr, "[");
            fprintf(stderr, "%5.4f ", tmd);
            if (FrameIndex)
                fprintf(stderr, "(%lu) ", FrameIndex);
            switch (severity)
            {
            case Info:
                fprintf(stderr, "INFO");
                break;
            case Warning:
                fprintf(stderr, "WARNING");
                break;
            case Error:
                fprintf(stderr, "ERROR");
                break;
            case FatalError:
                fprintf(stderr, "FATAL ERROR");
                break;
            default:
                break;
            };
            fprintf(stderr, " %s", modName);
            if (sourceInfo)
                fprintf(stderr, " {%s}", sourceInfo);
            if (thrName)
                fprintf(stderr, " (%s)", thrName);
            fprintf(stderr, "] ");
        }
#endif
    }

    void report(const char* modName, Level severity,
                const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        _reportHead(modName, nullptr, severity);
        vfprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }

    void report(const char* modName, Level severity,
                const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        _reportHead(modName, nullptr, severity);
        vfwprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfwprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }
};

void RegisterConsoleLogger()
{
    /* Determine if console logger already added */
    for (auto& logger : MainLoggers)
    {
        if (typeid(logger.get()) == typeid(ConsoleLogger))
            return;
    }

    /* Otherwise construct new console logger */
    MainLoggers.emplace_back(new ConsoleLogger);
}

struct FileLogger : public ILogger
{
    FILE* fp;
    std::mutex m;
    virtual void openFile()=0;
    virtual void closeFile() {fclose(fp);}

    void _reportHead(const char* modName, const char* sourceInfo, Level severity)
    {
        std::chrono::steady_clock::duration tm = CurrentUptime();
        double tmd = tm.count() *
            std::chrono::steady_clock::duration::period::num /
            (double)std::chrono::steady_clock::duration::period::den;
        std::thread::id thrId = std::this_thread::get_id();
        const char* thrName = nullptr;
        if (ThreadMap.find(thrId) != ThreadMap.end())
            thrName = ThreadMap[thrId];

        fprintf(fp, "[");
        switch (severity)
        {
        case Info:
            fprintf(fp, "INFO");
            break;
        case Warning:
            fprintf(fp, "WARNING");
            break;
        case Error:
            fprintf(fp, "ERROR");
            break;
        case FatalError:
            fprintf(fp, "FATAL ERROR");
            break;
        default:
            break;
        };
        fprintf(fp, " %s", modName);
        if (sourceInfo)
            fprintf(stderr, " {%s}", sourceInfo);
        if (thrName)
            fprintf(fp, " (%s)", thrName);
        fprintf(fp, " %5.4f", tmd);
        if (FrameIndex)
            fprintf(fp, " (%lu)", FrameIndex);
        fprintf(fp, "] ");
    }

    void report(const char* modName, Level severity,
                const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        _reportHead(modName, nullptr, severity);
        vfprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }

    void report(const char* modName, Level severity,
                const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        _reportHead(modName, nullptr, severity);
        vfwprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfwprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }
};

struct FileLogger8 : public FileLogger
{
    const char* m_filepath;
    FileLogger8(const char* filepath) : m_filepath(filepath) {}
    void openFile() {fp = fopen(m_filepath, "a");}
};

void RegisterFileLogger(const char* filepath)
{
    /* Determine if file logger already added */
    for (auto& logger : MainLoggers)
    {
        FileLogger8* filelogger = dynamic_cast<FileLogger8*>(logger.get());
        if (filelogger)
        {
            if (!strcmp(filepath, filelogger->m_filepath))
                return;
        }
    }

    /* Otherwise construct new file logger */
    MainLoggers.emplace_back(new FileLogger8(filepath));
}

#if LOG_UCS2

struct FileLogger16 : public FileLogger
{
    const wchar_t* m_filepath;
    FileLogger16(const wchar_t* filepath) : m_filepath(filepath) {}
    void openFile() {fp = _wfopen(m_filepath, L"a");}
};

void RegisterFileLogger(const wchar_t* filepath)
{
    /* Determine if file logger already added */
    for (auto& logger : MainLoggers)
    {
        FileLogger16* filelogger = dynamic_cast<FileLogger16*>(logger.get());
        if (filelogger)
        {
            if (!wcscmp(filepath, filelogger->m_filepath))
                return;
        }
    }

    /* Otherwise construct new file logger */
    MainLoggers.emplace_back(new FileLogger16(filepath));
}

#endif

}
<commit_msg>Update LogVisor.cpp<commit_after>#if _WIN32
#define _WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif

#include <chrono>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <stdio.h>
#include "LogVisor/LogVisor.hpp"

/* ANSI sequences */
#define RED "\x1b[1;31m"
#define YELLOW "\x1b[1;33m"
#define GREEN "\x1b[1;32m"
#define MAGENTA "\x1b[1;35m"
#define CYAN "\x1b[1;36m"
#define BOLD "\x1b[1m"
#define NORMAL "\x1b[0m"

namespace LogVisor
{

static std::unordered_map<std::thread::id, const char*> ThreadMap;
void RegisterThreadName(const char* name)
{
    ThreadMap[std::this_thread::get_id()] = name;
#if __APPLE__
    pthread_setname_np(name);
#elif __linux__
    pthread_setname_np(pthread_self(), name);
#elif _MSC_VER
    struct
    {
        DWORD dwType; // Must be 0x1000.
        LPCSTR szName; // Pointer to name (in user addr space).
        DWORD dwThreadID; // Thread ID (-1=caller thread).
        DWORD dwFlags; // Reserved for future use, must be zero.
    } info = {0x1000, name, (DWORD)-1, 0};
    __try
    {
        RaiseException(0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
    }
#endif
}

std::vector<std::unique_ptr<ILogger>> MainLoggers;
static std::chrono::steady_clock MonoClock;
static std::chrono::steady_clock::time_point GlobalStart = MonoClock.now();
static inline std::chrono::steady_clock::duration CurrentUptime()
{return MonoClock.now() - GlobalStart;}
uint64_t FrameIndex = 0;

#if _WIN32
static HANDLE Term = 0;
#else
static const char* Term = nullptr;
#endif
static bool XtermColor = false;
struct ConsoleLogger : public ILogger
{
    std::mutex m;
    ConsoleLogger()
    {
#if _WIN32
        if (!Term)
            Term = GetStdHandle(STD_ERROR_HANDLE);
#else
        if (!Term)
        {
            Term = getenv("TERM");
            if (Term && !strncmp(Term, "xterm", 5))
            {
                XtermColor = true;
                putenv((char*)"TERM=xterm-16color");
            }
        }
#endif
    }

    static void _reportHead(const char* modName, const char* sourceInfo, Level severity)
    {
        std::chrono::steady_clock::duration tm = CurrentUptime();
        double tmd = tm.count() *
            std::chrono::steady_clock::duration::period::num /
            (double)std::chrono::steady_clock::duration::period::den;
        std::thread::id thrId = std::this_thread::get_id();
        const char* thrName = nullptr;
        if (ThreadMap.find(thrId) != ThreadMap.end())
            thrName = ThreadMap[thrId];

#if _WIN32
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY);
        fprintf(stderr, "[");
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
        fprintf(stderr, "%5.4f ", tmd);
        if (FrameIndex)
            fprintf(stderr, "(%llu) ", FrameIndex);
        switch (severity)
        {
        case Info:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
            fprintf(stderr, "INFO");
            break;
        case Warning:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
            fprintf(stderr, "WARNING");
            break;
        case Error:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED);
            fprintf(stderr, "ERROR");
            break;
        case FatalError:
            SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED);
            fprintf(stderr, "FATAL ERROR");
            break;
        default:
            break;
        };
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY);
        fprintf(stderr, " %s", modName);
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
        if (sourceInfo)
            fprintf(stderr, " {%s}", sourceInfo);
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
        if (thrName)
            fprintf(stderr, " (%s)", thrName);
        SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY);
        fprintf(stderr, "] ");
        SetConsoleTextAttribute(Term, 0);
#else
        if (XtermColor)
        {
            fprintf(stderr, BOLD "[");
            fprintf(stderr, GREEN "%5.4f ", tmd);
            if (FrameIndex)
                fprintf(stderr, "(%lu) ", FrameIndex);
            switch (severity)
            {
            case Info:
                fprintf(stderr, BOLD CYAN "INFO");
                break;
            case Warning:
                fprintf(stderr, BOLD YELLOW "WARNING");
                break;
            case Error:
                fprintf(stderr, RED BOLD "ERROR");
                break;
            case FatalError:
                fprintf(stderr, BOLD RED "FATAL ERROR");
                break;
            default:
                break;
            };
            fprintf(stderr, NORMAL BOLD " %s", modName);
            if (sourceInfo)
                fprintf(stderr, BOLD YELLOW " {%s}", sourceInfo);
            if (thrName)
                fprintf(stderr, BOLD MAGENTA " (%s)", thrName);
            fprintf(stderr, NORMAL BOLD "] " NORMAL);
        }
        else
        {
            fprintf(stderr, "[");
            fprintf(stderr, "%5.4f ", tmd);
            if (FrameIndex)
                fprintf(stderr, "(%lu) ", FrameIndex);
            switch (severity)
            {
            case Info:
                fprintf(stderr, "INFO");
                break;
            case Warning:
                fprintf(stderr, "WARNING");
                break;
            case Error:
                fprintf(stderr, "ERROR");
                break;
            case FatalError:
                fprintf(stderr, "FATAL ERROR");
                break;
            default:
                break;
            };
            fprintf(stderr, " %s", modName);
            if (sourceInfo)
                fprintf(stderr, " {%s}", sourceInfo);
            if (thrName)
                fprintf(stderr, " (%s)", thrName);
            fprintf(stderr, "] ");
        }
#endif
    }

    void report(const char* modName, Level severity,
                const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        _reportHead(modName, nullptr, severity);
        vfprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }

    void report(const char* modName, Level severity,
                const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        _reportHead(modName, nullptr, severity);
        vfwprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfwprintf(stderr, format, ap);
        fprintf(stderr, "\n");
    }
};

void RegisterConsoleLogger()
{
    /* Determine if console logger already added */
    for (auto& logger : MainLoggers)
    {
        if (typeid(logger.get()) == typeid(ConsoleLogger))
            return;
    }

    /* Otherwise construct new console logger */
    MainLoggers.emplace_back(new ConsoleLogger);
}

struct FileLogger : public ILogger
{
    FILE* fp;
    std::mutex m;
    virtual void openFile()=0;
    virtual void closeFile() {fclose(fp);}

    void _reportHead(const char* modName, const char* sourceInfo, Level severity)
    {
        std::chrono::steady_clock::duration tm = CurrentUptime();
        double tmd = tm.count() *
            std::chrono::steady_clock::duration::period::num /
            (double)std::chrono::steady_clock::duration::period::den;
        std::thread::id thrId = std::this_thread::get_id();
        const char* thrName = nullptr;
        if (ThreadMap.find(thrId) != ThreadMap.end())
            thrName = ThreadMap[thrId];

        fprintf(fp, "[");
        switch (severity)
        {
        case Info:
            fprintf(fp, "INFO");
            break;
        case Warning:
            fprintf(fp, "WARNING");
            break;
        case Error:
            fprintf(fp, "ERROR");
            break;
        case FatalError:
            fprintf(fp, "FATAL ERROR");
            break;
        default:
            break;
        };
        fprintf(fp, " %s", modName);
        if (sourceInfo)
            fprintf(stderr, " {%s}", sourceInfo);
        if (thrName)
            fprintf(fp, " (%s)", thrName);
        fprintf(fp, " %5.4f", tmd);
        if (FrameIndex)
            fprintf(fp, " (%lu)", FrameIndex);
        fprintf(fp, "] ");
    }

    void report(const char* modName, Level severity,
                const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        _reportHead(modName, nullptr, severity);
        vfprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }

    void report(const char* modName, Level severity,
                const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        _reportHead(modName, nullptr, severity);
        vfwprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const char* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }

    void reportSource(const char* modName, Level severity,
                      const char* file, unsigned linenum,
                      const wchar_t* format, va_list ap)
    {
        std::unique_lock<std::mutex> lk(m);
        openFile();
        char sourceInfo[128];
        snprintf(sourceInfo, 128, "%s:%u", file, linenum);
        _reportHead(modName, sourceInfo, severity);
        vfwprintf(fp, format, ap);
        fprintf(fp, "\n");
        closeFile();
    }
};

struct FileLogger8 : public FileLogger
{
    const char* m_filepath;
    FileLogger8(const char* filepath) : m_filepath(filepath) {}
    void openFile() {fp = fopen(m_filepath, "a");}
};

void RegisterFileLogger(const char* filepath)
{
    /* Determine if file logger already added */
    for (auto& logger : MainLoggers)
    {
        FileLogger8* filelogger = dynamic_cast<FileLogger8*>(logger.get());
        if (filelogger)
        {
            if (!strcmp(filepath, filelogger->m_filepath))
                return;
        }
    }

    /* Otherwise construct new file logger */
    MainLoggers.emplace_back(new FileLogger8(filepath));
}

#if LOG_UCS2

struct FileLogger16 : public FileLogger
{
    const wchar_t* m_filepath;
    FileLogger16(const wchar_t* filepath) : m_filepath(filepath) {}
    void openFile() {fp = _wfopen(m_filepath, L"a");}
};

void RegisterFileLogger(const wchar_t* filepath)
{
    /* Determine if file logger already added */
    for (auto& logger : MainLoggers)
    {
        FileLogger16* filelogger = dynamic_cast<FileLogger16*>(logger.get());
        if (filelogger)
        {
            if (!wcscmp(filepath, filelogger->m_filepath))
                return;
        }
    }

    /* Otherwise construct new file logger */
    MainLoggers.emplace_back(new FileLogger16(filepath));
}

#endif

}
<|endoftext|>


<commit_before>/*
 * Copyright 2008 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
// for implementing this test.

#include "vtkDoubleArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPCAStatistics.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkTestUtilities.h"

#include "vtksys/SystemTools.hxx"

//=============================================================================
int TestPCAStatistics( int argc, char* argv[] )
{
  char* normScheme = vtkTestUtilities::GetArgOrEnvOrDefault(
    "-normalize-covariance", argc, argv, "VTK_NORMALIZE_COVARIANCE", "None" );
  int testStatus = 0;

  /* */
  double mingledData[] =
    {
    46, 45,
    47, 49,
    46, 47,
    46, 46,
    47, 46,
    47, 49,
    49, 49,
    47, 45,
    50, 50,
    46, 46,
    51, 50,
    48, 48,
    52, 54,
    48, 47,
    52, 52,
    49, 49,
    53, 54,
    50, 50,
    53, 54,
    50, 52,
    53, 53,
    50, 51,
    54, 54,
    49, 49,
    52, 52,
    50, 51,
    52, 52,
    49, 47,
    48, 48,
    48, 50,
    46, 48,
    47, 47
    };
  int nVals = 32;

  const char m0Name[] = "M0";
  vtkDoubleArray* dataset1Arr = vtkDoubleArray::New();
  dataset1Arr->SetNumberOfComponents( 1 );
  dataset1Arr->SetName( m0Name );

  const char m1Name[] = "M1";
  vtkDoubleArray* dataset2Arr = vtkDoubleArray::New();
  dataset2Arr->SetNumberOfComponents( 1 );
  dataset2Arr->SetName( m1Name );

  const char m2Name[] = "M2";
  vtkDoubleArray* dataset3Arr = vtkDoubleArray::New();
  dataset3Arr->SetNumberOfComponents( 1 );
  dataset3Arr->SetName( m2Name );

  for ( int i = 0; i < nVals; ++ i )
    {
    int ti = i << 1;
    dataset1Arr->InsertNextValue( mingledData[ti] );
    dataset2Arr->InsertNextValue( mingledData[ti + 1] );
    dataset3Arr->InsertNextValue( i != 12 ? -1. : -1.001 );
    }

  vtkTable* datasetTable = vtkTable::New();
  datasetTable->AddColumn( dataset1Arr );
  dataset1Arr->Delete();
  datasetTable->AddColumn( dataset2Arr );
  dataset2Arr->Delete();
  datasetTable->AddColumn( dataset3Arr );
  dataset3Arr->Delete();

  vtkPCAStatistics* pcas = vtkPCAStatistics::New();
  pcas->SetInput( vtkStatisticsAlgorithm::INPUT_DATA, datasetTable );
  pcas->SetNormalizationSchemeByName( normScheme );
  pcas->SetBasisSchemeByName( "FixedBasisEnergy" );
  pcas->SetFixedBasisEnergy( 1. - 1e-8 );

  datasetTable->Delete();

  // -- Select Column Pairs of Interest ( Learn Mode ) --
  pcas->SetColumnStatus( m0Name, 1 );
  pcas->SetColumnStatus( m1Name, 1 );
  pcas->RequestSelectedColumns();
  pcas->ResetAllColumnStates();
  pcas->SetColumnStatus( m0Name, 1 );
  pcas->SetColumnStatus( m1Name, 1 );
  pcas->SetColumnStatus( m2Name, 1 );
  pcas->SetColumnStatus( m2Name, 0 );
  pcas->SetColumnStatus( m2Name, 1 );
  pcas->RequestSelectedColumns();
  pcas->RequestSelectedColumns(); // Try a duplicate entry. This should have no effect.
  pcas->SetColumnStatus( m0Name, 0 );
  pcas->SetColumnStatus( m2Name, 0 );
  pcas->SetColumnStatus( "Metric 3", 1 ); // An invalid name. This should result in a request for metric 1's self-correlation.
  // pcas->RequestSelectedColumns(); will get called in RequestData()

  // -- Test Learn Mode --
  pcas->SetLearnOption( true );
  pcas->SetDeriveOption( true );
  pcas->SetAssessOption( false );

  pcas->Update();
  vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( pcas->GetOutputDataObject( vtkStatisticsAlgorithm::OUTPUT_MODEL ) );
  for ( unsigned int b = 0; b < outputMetaDS->GetNumberOfBlocks(); ++ b )
    {
    vtkTable* outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( b ) );

    if ( b == 0 )
      {
      cout << "Raw sums\n";
      }
    else
      {
      cout << "Request " << ( b - 1 ) << "\n";
      }

    outputMeta->Dump();
    }

  // -- Test Assess Mode --
  vtkMultiBlockDataSet* paramsTables = vtkMultiBlockDataSet::New();
  paramsTables->ShallowCopy( outputMetaDS );

  pcas->SetInput( vtkStatisticsAlgorithm::INPUT_MODEL, paramsTables );
  paramsTables->Delete();

  // Test Assess only (Do not recalculate nor rederive a model)
  // Use SetParameter method
  pcas->SetParameter( "Learn", 0, false );
  pcas->SetParameter( "Derive", 0, false );
  pcas->SetParameter( "Assess", 0, true );
  pcas->Update();

  vtkTable* outputData = pcas->GetOutput();
  outputData->Dump();

  pcas->Delete();
  delete [] normScheme;

  return testStatus;
}
<commit_msg>ENH: added empty input test (good practice)<commit_after>/*
 * Copyright 2008 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
// for implementing this test.

#include "vtkDoubleArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPCAStatistics.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkTestUtilities.h"

#include "vtksys/SystemTools.hxx"

//=============================================================================
int TestPCAStatistics( int argc, char* argv[] )
{
  char* normScheme = vtkTestUtilities::GetArgOrEnvOrDefault(
    "-normalize-covariance", argc, argv, "VTK_NORMALIZE_COVARIANCE", "None" );
  int testStatus = 0;

  /* */
  double mingledData[] =
    {
    46, 45,
    47, 49,
    46, 47,
    46, 46,
    47, 46,
    47, 49,
    49, 49,
    47, 45,
    50, 50,
    46, 46,
    51, 50,
    48, 48,
    52, 54,
    48, 47,
    52, 52,
    49, 49,
    53, 54,
    50, 50,
    53, 54,
    50, 52,
    53, 53,
    50, 51,
    54, 54,
    49, 49,
    52, 52,
    50, 51,
    52, 52,
    49, 47,
    48, 48,
    48, 50,
    46, 48,
    47, 47
    };
  int nVals = 32;

  const char m0Name[] = "M0";
  vtkDoubleArray* dataset1Arr = vtkDoubleArray::New();
  dataset1Arr->SetNumberOfComponents( 1 );
  dataset1Arr->SetName( m0Name );

  const char m1Name[] = "M1";
  vtkDoubleArray* dataset2Arr = vtkDoubleArray::New();
  dataset2Arr->SetNumberOfComponents( 1 );
  dataset2Arr->SetName( m1Name );

  const char m2Name[] = "M2";
  vtkDoubleArray* dataset3Arr = vtkDoubleArray::New();
  dataset3Arr->SetNumberOfComponents( 1 );
  dataset3Arr->SetName( m2Name );

  for ( int i = 0; i < nVals; ++ i )
    {
    int ti = i << 1;
    dataset1Arr->InsertNextValue( mingledData[ti] );
    dataset2Arr->InsertNextValue( mingledData[ti + 1] );
    dataset3Arr->InsertNextValue( i != 12 ? -1. : -1.001 );
    }

  vtkTable* datasetTable = vtkTable::New();
  datasetTable->AddColumn( dataset1Arr );
  dataset1Arr->Delete();
  datasetTable->AddColumn( dataset2Arr );
  dataset2Arr->Delete();
  datasetTable->AddColumn( dataset3Arr );
  dataset3Arr->Delete();

  // Set PCA statistics algorithm and its input data port
  vtkPCAStatistics* pcas = vtkPCAStatistics::New();

  // First verify that absence of input does not cause trouble
  cout << "## Verifying that absence of input does not cause trouble... ";
  pcas->Update();
  cout << "done.\n";

  // Prepare first test with data
  pcas->SetInput( vtkStatisticsAlgorithm::INPUT_DATA, datasetTable );
  pcas->SetNormalizationSchemeByName( normScheme );
  pcas->SetBasisSchemeByName( "FixedBasisEnergy" );
  pcas->SetFixedBasisEnergy( 1. - 1e-8 );

  datasetTable->Delete();

  // -- Select Column Pairs of Interest ( Learn Mode ) --
  pcas->SetColumnStatus( m0Name, 1 );
  pcas->SetColumnStatus( m1Name, 1 );
  pcas->RequestSelectedColumns();
  pcas->ResetAllColumnStates();
  pcas->SetColumnStatus( m0Name, 1 );
  pcas->SetColumnStatus( m1Name, 1 );
  pcas->SetColumnStatus( m2Name, 1 );
  pcas->SetColumnStatus( m2Name, 0 );
  pcas->SetColumnStatus( m2Name, 1 );
  pcas->RequestSelectedColumns();
  pcas->RequestSelectedColumns(); // Try a duplicate entry. This should have no effect.
  pcas->SetColumnStatus( m0Name, 0 );
  pcas->SetColumnStatus( m2Name, 0 );
  pcas->SetColumnStatus( "Metric 3", 1 ); // An invalid name. This should result in a request for metric 1's self-correlation.
  // pcas->RequestSelectedColumns(); will get called in RequestData()

  // -- Test Learn Mode --
  pcas->SetLearnOption( true );
  pcas->SetDeriveOption( true );
  pcas->SetAssessOption( false );

  pcas->Update();
  vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( pcas->GetOutputDataObject( vtkStatisticsAlgorithm::OUTPUT_MODEL ) );
  for ( unsigned int b = 0; b < outputMetaDS->GetNumberOfBlocks(); ++ b )
    {
    vtkTable* outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( b ) );

    if ( b == 0 )
      {
      cout << "Raw sums\n";
      }
    else
      {
      cout << "Request " << ( b - 1 ) << "\n";
      }

    outputMeta->Dump();
    }

  // -- Test Assess Mode --
  vtkMultiBlockDataSet* paramsTables = vtkMultiBlockDataSet::New();
  paramsTables->ShallowCopy( outputMetaDS );

  pcas->SetInput( vtkStatisticsAlgorithm::INPUT_MODEL, paramsTables );
  paramsTables->Delete();

  // Test Assess only (Do not recalculate nor rederive a model)
  // Use SetParameter method
  pcas->SetParameter( "Learn", 0, false );
  pcas->SetParameter( "Derive", 0, false );
  pcas->SetParameter( "Assess", 0, true );
  pcas->Update();

  vtkTable* outputData = pcas->GetOutput();
  outputData->Dump();

  pcas->Delete();
  delete [] normScheme;

  return testStatus;
}
<|endoftext|>


<commit_before>// Copyright © 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.
//
// Author: Christian Kellner <kellner@bio.lmu.de>

#ifndef NIX_VALUE_H
#define NIX_VALUE_H

#include <string>
#include <cstdint>
#include <stdexcept>
#include <iostream>

#include <nix/DataType.hpp>
#include <nix/Platform.hpp>
#include <nix/None.hpp>

namespace nix {

class NIXAPI Value {
private:
    DataType dtype;

    union {
        bool        v_bool;
        double      v_double;
        uint32_t    v_uint32;
        int32_t     v_int32;
        uint64_t    v_uint64;
        int64_t     v_int64;
#ifndef _WIN32
        std::string v_string;
#endif
    };

#ifdef _WIN32
    std::string v_string;
#endif

public:
    double uncertainty = 0.0;

    std::string reference;
    std::string filename;
    std::string encoder;
    std::string checksum;

    Value() : dtype(DataType::Nothing), v_bool(false) { }

    Value(char *value) : dtype(DataType::Nothing) {
        set(std::string(value));
    }

    Value(const char *value) : dtype(DataType::Nothing) {
        set(std::string(value));
    }

    template<typename T>
    explicit Value(const T &value) : dtype(DataType::Nothing) {
        set(value);
    }

    template<size_t N>
    explicit Value(const char (&value)[N]) : dtype(DataType::Nothing) {
        set(std::string(value));
    }

    Value(const Value &other) : Value() {
        assign_variant_from(other);
    }

    Value(Value &&other) : Value() {
        swap(other);
    }

    Value &operator=(Value other) {
        swap(other);
        return *this;
    }

    ~Value() {
        maybe_deallocte_string();
    }

    void set(none_t);
    void set(bool   value);
    void set(int32_t value);
    void set(uint32_t value);
    void set(int64_t value);
    void set(uint64_t value);
    void set(double value);
    void set(const std::string &value);

    template<typename T>
    T get() const {
        T temp;
        get(temp);
        return temp;
    }

    void get(none_t &tag) const;
    void get(bool &out) const;
    void get(int32_t &value) const;
    void get(uint32_t &value) const;
    void get(int64_t &value) const;
    void get(uint64_t &value) const;
    void get(double &value) const;
    void get(std::string &value) const;

    DataType type() const {
        return dtype;
    }

    void swap(Value &other);

private:

    template<typename T>
    void swap_helper(Value &other) {
        T temp = get<T>();
        assign_variant_from(other);
        other.set(temp);
    }

    void assign_variant_from(const Value &other);
    void maybe_deallocte_string();

    inline void check_argument_type(DataType check) const {
        if (dtype != check) {
            throw std::invalid_argument("Incompatible DataType");
        }
    }
};

template<>
inline const char * Value::get<const char *>() const {
    check_argument_type(DataType::String);
    return v_string.c_str();
}

NIXAPI std::ostream& operator<<(std::ostream &out, const Value &value);
NIXAPI bool operator==(const Value &a, const Value &b);
inline bool operator!=(const Value &a, const Value &b) { return !(a == b); }
NIXAPI void swap(Value &a, Value &b);

} // namespace nix

#endif // NIX_VALUE_H
<commit_msg>Value: declare its move constructor noexcept<commit_after>// Copyright © 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.
//
// Author: Christian Kellner <kellner@bio.lmu.de>

#ifndef NIX_VALUE_H
#define NIX_VALUE_H

#include <string>
#include <cstdint>
#include <stdexcept>
#include <iostream>

#include <nix/DataType.hpp>
#include <nix/Platform.hpp>
#include <nix/None.hpp>

namespace nix {

class NIXAPI Value {
private:
    DataType dtype;

    union {
        bool        v_bool;
        double      v_double;
        uint32_t    v_uint32;
        int32_t     v_int32;
        uint64_t    v_uint64;
        int64_t     v_int64;
#ifndef _WIN32
        std::string v_string;
#endif
    };

#ifdef _WIN32
    std::string v_string;
#endif

public:
    double uncertainty = 0.0;

    std::string reference;
    std::string filename;
    std::string encoder;
    std::string checksum;

    Value() : dtype(DataType::Nothing), v_bool(false) { }

    Value(char *value) : dtype(DataType::Nothing) {
        set(std::string(value));
    }

    Value(const char *value) : dtype(DataType::Nothing) {
        set(std::string(value));
    }

    template<typename T>
    explicit Value(const T &value) : dtype(DataType::Nothing) {
        set(value);
    }

    template<size_t N>
    explicit Value(const char (&value)[N]) : dtype(DataType::Nothing) {
        set(std::string(value));
    }

    Value(const Value &other) : Value() {
        assign_variant_from(other);
    }

    Value(Value &&other) NOEXCEPT : Value() {
        swap(other);
    }

    Value &operator=(Value other) {
        swap(other);
        return *this;
    }

    ~Value() {
        maybe_deallocte_string();
    }

    void set(none_t);
    void set(bool   value);
    void set(int32_t value);
    void set(uint32_t value);
    void set(int64_t value);
    void set(uint64_t value);
    void set(double value);
    void set(const std::string &value);

    template<typename T>
    T get() const {
        T temp;
        get(temp);
        return temp;
    }

    void get(none_t &tag) const;
    void get(bool &out) const;
    void get(int32_t &value) const;
    void get(uint32_t &value) const;
    void get(int64_t &value) const;
    void get(uint64_t &value) const;
    void get(double &value) const;
    void get(std::string &value) const;

    DataType type() const {
        return dtype;
    }

    void swap(Value &other);

private:

    template<typename T>
    void swap_helper(Value &other) {
        T temp = get<T>();
        assign_variant_from(other);
        other.set(temp);
    }

    void assign_variant_from(const Value &other);
    void maybe_deallocte_string();

    inline void check_argument_type(DataType check) const {
        if (dtype != check) {
            throw std::invalid_argument("Incompatible DataType");
        }
    }
};

template<>
inline const char * Value::get<const char *>() const {
    check_argument_type(DataType::String);
    return v_string.c_str();
}

NIXAPI std::ostream& operator<<(std::ostream &out, const Value &value);
NIXAPI bool operator==(const Value &a, const Value &b);
inline bool operator!=(const Value &a, const Value &b) { return !(a == b); }
NIXAPI void swap(Value &a, Value &b);

} // namespace nix

#endif // NIX_VALUE_H
<|endoftext|>


<commit_before>/* Various utility definitions for libpqxx.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
 *
 * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_UTIL
#define PQXX_H_UTIL

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <cctype>
#include <cstdio>
#include <iterator>
#include <memory>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <typeinfo>
#include <vector>

#include "pqxx/except.hxx"
#include "pqxx/types.hxx"
#include "pqxx/version.hxx"

/// The home of all libpqxx classes, functions, templates, etc.
namespace pqxx
{}

#include <pqxx/internal/libpq-forward.hxx>

namespace pqxx
{
/// Suppress compiler warning about an unused item.
template<typename T> inline void ignore_unused(T &&) {}

/// Cast a numeric value to another type, or throw if it underflows/overflows.
/** Both types must be arithmetic types, and they must either be both integral
 * or both floating-point types.
 */
template<typename TO, typename FROM>
inline TO check_cast(FROM value, const char description[])
{
  static_assert(std::is_arithmetic_v<FROM>);
  static_assert(std::is_arithmetic_v<TO>);
  static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);

  // The rest of this code won't quite work for bool, but bool is trivially
  // convertible to other arithmetic types as far as I can see.
  if constexpr (std::is_same_v<FROM, bool>)
    return static_cast<TO>(value);

  // Depending on our "if constexpr" conditions, this parameter may not be
  // needed.  Some compilers will warn.
  ignore_unused(description);

  using from_limits = std::numeric_limits<decltype(value)>;
  using to_limits = std::numeric_limits<TO>;
  if constexpr (std::is_signed_v<FROM>)
  {
    if constexpr (std::is_signed_v<TO>)
    {
      if (value < (to_limits::min)())
        throw range_error(std::string{"Cast underflow: "} + description);
    }
    else
    {
      // FROM is signed, but TO is not.  Treat this as a special case, because
      // there may not be a good broader type in which the compiler can even
      // perform our check.
      if (value < 0)
        throw range_error(
          std::string{"Casting negative value to unsigned type: "} +
          description);
    }
  }
  else
  {
    // No need to check: the value is unsigned so can't fall below the range
    // of the TO type.
  }

  if constexpr (std::is_integral_v<FROM>)
  {
    using unsigned_from = std::make_unsigned_t<FROM>;
    using unsigned_to = std::make_unsigned_t<TO>;
    constexpr auto from_max = static_cast<unsigned_from>((from_limits::max)());
    constexpr auto to_max = static_cast<unsigned_to>((to_limits::max)());
    if constexpr (from_max > to_max)
    {
      if (static_cast<unsigned_from>(value) > to_max)
        throw range_error(std::string{"Cast overflow: "} + description);
    }
  }
  else if constexpr ((from_limits::max)() > (to_limits::max)())
  {
    if (value > (to_limits::max)())
      throw range_error(std::string{"Cast overflow: "} + description);
  }

  return static_cast<TO>(value);
}

/** Check library version at link time.
 *
 * Ensures a failure when linking an application against a radically
 * different libpqxx version than the one against which it was compiled.
 *
 * Sometimes application builds fail in unclear ways because they compile
 * using headers from libpqxx version X, but then link against libpqxx
 * binary version Y.  A typical scenario would be one where you're building
 * against a libpqxx which you have built yourself, but a different version
 * is installed on the system.
 *
 * The check_library_version template is declared for any library version,
 * but only actually defined for the version of the libpqxx binary against
 * which the code is linked.
 *
 * If the library binary is a different version than the one declared in
 * these headers, then this call will fail to link: there will be no
 * definition for the function with these exact template parameter values.
 * There will be a definition, but the version in the parameter values will
 * be different.
 */
inline PQXX_PRIVATE void check_version()
{
  // There is no particular reason to do this here in @c connection, except
  // to ensure that every meaningful libpqxx client will execute it.  The call
  // must be in the execution path somewhere or the compiler won't try to link
  // it.  We can't use it to initialise a global or class-static variable,
  // because a smart compiler might resolve it at compile time.
  //
  // On the other hand, we don't want to make a useless function call too
  // often for performance reasons.  A local static variable is initialised
  // only on the definition's first execution.  Compilers will be well
  // optimised for this behaviour, so there's a minimal one-time cost.
  static const auto version_ok = internal::PQXX_VERSION_CHECK();
  ignore_unused(version_ok);
}

/// Descriptor of library's thread-safety model.
/** This describes what the library knows about various risks to thread-safety.
 */
struct PQXX_LIBEXPORT thread_safety_model
{
  /// Is the underlying libpq build thread-safe?
  bool safe_libpq;

  /// Is Kerberos thread-safe?
  /** @warning Is currently always @c false.
   *
   * If your application uses Kerberos, all accesses to libpqxx or Kerberos
   * must be serialized.  Confine their use to a single thread, or protect it
   * with a global lock.
   */
  bool safe_kerberos;

  /// A human-readable description of any thread-safety issues.
  std::string description;
};

/// Describe thread safety available in this build.
PQXX_LIBEXPORT thread_safety_model describe_thread_safety();

/// The "null" oid.
constexpr oid oid_none = 0;
} // namespace pqxx

/// Private namespace for libpqxx's internal use; do not access.
/** This namespace hides definitions internal to libpqxx.  These are not
 * supposed to be used by client programs, and they may change at any time
 * without notice.
 *
 * Conversely, if you find something in this namespace tremendously useful, by
 * all means do lodge a request for its publication.
 *
 * @warning Here be dragons!
 */
namespace pqxx::internal
{
PQXX_LIBEXPORT void freepqmem(const void *) noexcept;
template<typename P> inline void freepqmem_templated(P *p) noexcept
{
  freepqmem(p);
}

PQXX_LIBEXPORT void freemallocmem(const void *) noexcept;
template<typename P> inline void freemallocmem_templated(P *p) noexcept
{
  freemallocmem(p);
}

/// Helper base class: object descriptions for error messages and such.
/**
 * Classes derived from namedclass have a class name (such as "transaction"),
 * an optional object name (such as "delete-old-logs"), and a description
 * generated from the two names (such as "transaction delete-old-logs").
 *
 * The class name is dynamic here, in order to support inheritance hierarchies
 * where the exact class name may not be known statically.
 *
 * In inheritance hierarchies, make namedclass a virtual base class so that
 * each class in the hierarchy can specify its own class name in its
 * constructors.
 */
class PQXX_LIBEXPORT namedclass
{
public:
  explicit namedclass(std::string_view Classname) : m_classname{Classname} {}

  namedclass(std::string_view Classname, std::string_view Name) :
          m_classname{Classname},
          m_name{Name}
  {}

  namedclass(std::string_view Classname, const char Name[]) :
          m_classname{Classname},
          m_name{Name}
  {}

  namedclass(std::string_view Classname, std::string &&Name) :
          m_classname{Classname},
          m_name{std::move(Name)}
  {}

  /// Object name, or the empty string if no name was given.
  const std::string &name() const noexcept { return m_name; }

  /// Class name.
  const std::string &classname() const noexcept { return m_classname; }

  /// Combination of class name and object name; or just class name.
  std::string description() const;

private:
  std::string m_classname, m_name;
};

PQXX_PRIVATE void check_unique_registration(
  const namedclass *new_ptr, const namedclass *old_ptr);
PQXX_PRIVATE void check_unique_unregistration(
  const namedclass *new_ptr, const namedclass *old_ptr);

/// Ensure proper opening/closing of GUEST objects related to a "host" object
/** Only a single GUEST may exist for a single host at any given time.  GUEST
 * must be derived from namedclass.
 */
template<typename GUEST> class unique
{
public:
  constexpr unique() = default;
  constexpr unique(const unique &) = delete;
  constexpr unique(unique &&rhs) : m_guest(rhs.m_guest)
  {
    rhs.m_guest = nullptr;
  }
  constexpr unique &operator=(const unique &) = delete;
  constexpr unique &operator=(unique &&rhs)
  {
    m_guest = rhs.m_guest;
    rhs.m_guest = nullptr;
    return *this;
  }

  constexpr GUEST *get() const noexcept { return m_guest; }

  constexpr void register_guest(GUEST *G)
  {
    check_unique_registration(G, m_guest);
    m_guest = G;
  }

  constexpr void unregister_guest(GUEST *G)
  {
    check_unique_unregistration(G, m_guest);
    m_guest = nullptr;
  }

private:
  GUEST *m_guest = nullptr;
};

/// Sleep for the given number of seconds
/** May return early, e.g. when interrupted by a signal.  Completes instantly
 * if a zero or negative sleep time is requested.
 */
PQXX_LIBEXPORT void sleep_seconds(int);
} // namespace pqxx::internal

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<commit_msg>More initialisers.<commit_after>/* Various utility definitions for libpqxx.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
 *
 * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_UTIL
#define PQXX_H_UTIL

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <cctype>
#include <cstdio>
#include <iterator>
#include <memory>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <typeinfo>
#include <vector>

#include "pqxx/except.hxx"
#include "pqxx/types.hxx"
#include "pqxx/version.hxx"

/// The home of all libpqxx classes, functions, templates, etc.
namespace pqxx
{}

#include <pqxx/internal/libpq-forward.hxx>

namespace pqxx
{
/// Suppress compiler warning about an unused item.
template<typename T> inline void ignore_unused(T &&) {}

/// Cast a numeric value to another type, or throw if it underflows/overflows.
/** Both types must be arithmetic types, and they must either be both integral
 * or both floating-point types.
 */
template<typename TO, typename FROM>
inline TO check_cast(FROM value, const char description[])
{
  static_assert(std::is_arithmetic_v<FROM>);
  static_assert(std::is_arithmetic_v<TO>);
  static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);

  // The rest of this code won't quite work for bool, but bool is trivially
  // convertible to other arithmetic types as far as I can see.
  if constexpr (std::is_same_v<FROM, bool>)
    return static_cast<TO>(value);

  // Depending on our "if constexpr" conditions, this parameter may not be
  // needed.  Some compilers will warn.
  ignore_unused(description);

  using from_limits = std::numeric_limits<decltype(value)>;
  using to_limits = std::numeric_limits<TO>;
  if constexpr (std::is_signed_v<FROM>)
  {
    if constexpr (std::is_signed_v<TO>)
    {
      if (value < (to_limits::min)())
        throw range_error(std::string{"Cast underflow: "} + description);
    }
    else
    {
      // FROM is signed, but TO is not.  Treat this as a special case, because
      // there may not be a good broader type in which the compiler can even
      // perform our check.
      if (value < 0)
        throw range_error(
          std::string{"Casting negative value to unsigned type: "} +
          description);
    }
  }
  else
  {
    // No need to check: the value is unsigned so can't fall below the range
    // of the TO type.
  }

  if constexpr (std::is_integral_v<FROM>)
  {
    using unsigned_from = std::make_unsigned_t<FROM>;
    using unsigned_to = std::make_unsigned_t<TO>;
    constexpr auto from_max = static_cast<unsigned_from>((from_limits::max)());
    constexpr auto to_max = static_cast<unsigned_to>((to_limits::max)());
    if constexpr (from_max > to_max)
    {
      if (static_cast<unsigned_from>(value) > to_max)
        throw range_error(std::string{"Cast overflow: "} + description);
    }
  }
  else if constexpr ((from_limits::max)() > (to_limits::max)())
  {
    if (value > (to_limits::max)())
      throw range_error(std::string{"Cast overflow: "} + description);
  }

  return static_cast<TO>(value);
}

/** Check library version at link time.
 *
 * Ensures a failure when linking an application against a radically
 * different libpqxx version than the one against which it was compiled.
 *
 * Sometimes application builds fail in unclear ways because they compile
 * using headers from libpqxx version X, but then link against libpqxx
 * binary version Y.  A typical scenario would be one where you're building
 * against a libpqxx which you have built yourself, but a different version
 * is installed on the system.
 *
 * The check_library_version template is declared for any library version,
 * but only actually defined for the version of the libpqxx binary against
 * which the code is linked.
 *
 * If the library binary is a different version than the one declared in
 * these headers, then this call will fail to link: there will be no
 * definition for the function with these exact template parameter values.
 * There will be a definition, but the version in the parameter values will
 * be different.
 */
inline PQXX_PRIVATE void check_version()
{
  // There is no particular reason to do this here in @c connection, except
  // to ensure that every meaningful libpqxx client will execute it.  The call
  // must be in the execution path somewhere or the compiler won't try to link
  // it.  We can't use it to initialise a global or class-static variable,
  // because a smart compiler might resolve it at compile time.
  //
  // On the other hand, we don't want to make a useless function call too
  // often for performance reasons.  A local static variable is initialised
  // only on the definition's first execution.  Compilers will be well
  // optimised for this behaviour, so there's a minimal one-time cost.
  static const auto version_ok = internal::PQXX_VERSION_CHECK();
  ignore_unused(version_ok);
}

/// Descriptor of library's thread-safety model.
/** This describes what the library knows about various risks to thread-safety.
 */
struct PQXX_LIBEXPORT thread_safety_model
{
  /// Is the underlying libpq build thread-safe?
  bool safe_libpq = false;

  /// Is Kerberos thread-safe?
  /** @warning Is currently always @c false.
   *
   * If your application uses Kerberos, all accesses to libpqxx or Kerberos
   * must be serialized.  Confine their use to a single thread, or protect it
   * with a global lock.
   */
  bool safe_kerberos = false;

  /// A human-readable description of any thread-safety issues.
  std::string description;
};

/// Describe thread safety available in this build.
PQXX_LIBEXPORT thread_safety_model describe_thread_safety();

/// The "null" oid.
constexpr oid oid_none = 0;
} // namespace pqxx

/// Private namespace for libpqxx's internal use; do not access.
/** This namespace hides definitions internal to libpqxx.  These are not
 * supposed to be used by client programs, and they may change at any time
 * without notice.
 *
 * Conversely, if you find something in this namespace tremendously useful, by
 * all means do lodge a request for its publication.
 *
 * @warning Here be dragons!
 */
namespace pqxx::internal
{
PQXX_LIBEXPORT void freepqmem(const void *) noexcept;
template<typename P> inline void freepqmem_templated(P *p) noexcept
{
  freepqmem(p);
}

PQXX_LIBEXPORT void freemallocmem(const void *) noexcept;
template<typename P> inline void freemallocmem_templated(P *p) noexcept
{
  freemallocmem(p);
}

/// Helper base class: object descriptions for error messages and such.
/**
 * Classes derived from namedclass have a class name (such as "transaction"),
 * an optional object name (such as "delete-old-logs"), and a description
 * generated from the two names (such as "transaction delete-old-logs").
 *
 * The class name is dynamic here, in order to support inheritance hierarchies
 * where the exact class name may not be known statically.
 *
 * In inheritance hierarchies, make namedclass a virtual base class so that
 * each class in the hierarchy can specify its own class name in its
 * constructors.
 */
class PQXX_LIBEXPORT namedclass
{
public:
  explicit namedclass(std::string_view Classname) : m_classname{Classname} {}

  namedclass(std::string_view Classname, std::string_view Name) :
          m_classname{Classname},
          m_name{Name}
  {}

  namedclass(std::string_view Classname, const char Name[]) :
          m_classname{Classname},
          m_name{Name}
  {}

  namedclass(std::string_view Classname, std::string &&Name) :
          m_classname{Classname},
          m_name{std::move(Name)}
  {}

  /// Object name, or the empty string if no name was given.
  const std::string &name() const noexcept { return m_name; }

  /// Class name.
  const std::string &classname() const noexcept { return m_classname; }

  /// Combination of class name and object name; or just class name.
  std::string description() const;

private:
  std::string m_classname, m_name;
};

PQXX_PRIVATE void check_unique_registration(
  const namedclass *new_ptr, const namedclass *old_ptr);
PQXX_PRIVATE void check_unique_unregistration(
  const namedclass *new_ptr, const namedclass *old_ptr);

/// Ensure proper opening/closing of GUEST objects related to a "host" object
/** Only a single GUEST may exist for a single host at any given time.  GUEST
 * must be derived from namedclass.
 */
template<typename GUEST> class unique
{
public:
  constexpr unique() = default;
  constexpr unique(const unique &) = delete;
  constexpr unique(unique &&rhs) : m_guest(rhs.m_guest)
  {
    rhs.m_guest = nullptr;
  }
  constexpr unique &operator=(const unique &) = delete;
  constexpr unique &operator=(unique &&rhs)
  {
    m_guest = rhs.m_guest;
    rhs.m_guest = nullptr;
    return *this;
  }

  constexpr GUEST *get() const noexcept { return m_guest; }

  constexpr void register_guest(GUEST *G)
  {
    check_unique_registration(G, m_guest);
    m_guest = G;
  }

  constexpr void unregister_guest(GUEST *G)
  {
    check_unique_unregistration(G, m_guest);
    m_guest = nullptr;
  }

private:
  GUEST *m_guest = nullptr;
};

/// Sleep for the given number of seconds
/** May return early, e.g. when interrupted by a signal.  Completes instantly
 * if a zero or negative sleep time is requested.
 */
PQXX_LIBEXPORT void sleep_seconds(int);
} // namespace pqxx::internal

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<|endoftext|>


<commit_before>#pragma once

#include <type_traits>
#include <utility>

#ifdef STX_DEBUG
#	include "assert.hpp"
#endif

namespace stx {

template<typename T>
class list_element {
public:
	using Tself = list_element<T>;
private:
	T* m_next;
	T* m_last;

	void update_next_last() noexcept;

protected:
	constexpr
	list_element();
	~list_element() noexcept;

	// -- Move --------------------------------------------------------------
	constexpr
	list_element(Tself&& e);
	constexpr
	Tself& operator=(Tself&& e) noexcept;

	// -- Copy --------------------------------------------------------------
	list_element(Tself const&)     = delete;
	Tself& operator=(Tself const&) = delete;

public:

	// -- Functionality -----------------------------------------------------
	void remove() noexcept;

	void push_front(T* p) noexcept;
	void push_back(T* p) noexcept;

	void insert_as_last(T* p) noexcept;

	void insert_as_next(T* p) noexcept;

	// -- Getters / Setters -------------------------------------------------
	      T* next()       noexcept { return m_next; }
	      T* last()       noexcept { return m_last; }
	const T* next() const noexcept { return m_next; }
	const T* last() const noexcept { return m_last; }

	      T* tail()       noexcept;
	const T* tail() const noexcept;

	      T* head()       noexcept;
	const T* head() const noexcept;
};

template<typename T, typename TParent>
class child_element;

template<typename T, typename TChild>
class parent_element {
	using Tself  = parent_element<T, TChild>;

	TChild* m_children;

	friend T;
	friend class child_element<TChild, T>;

protected:
	using parent_element_t = parent_element<T, TChild>;
	using child_element_t  = child_element<TChild, T>;

	parent_element();
	~parent_element() noexcept;

public:
	// -- Move --------------------------------------------------------------
	parent_element(Tself&& e);
	Tself& operator=(Tself&& other) noexcept;

	// -- Copy --------------------------------------------------------------
	parent_element(Tself const&) = delete;
	Tself& operator=(Tself const&) = delete;

	// -- Functionality -----------------------------------------------------
	void push_back(TChild* c) noexcept;
	void push_front(TChild* c) noexcept;

	// -- Getters / Setters -------------------------------------------------
	      TChild* children()       noexcept { return m_children; }
	const TChild* children() const noexcept { return m_children; }
};

template<typename T, typename TParent>
class child_element : public list_element<T> {
	TParent* m_parent;

	friend class parent_element<TParent, T>;
protected:
	using parent_element_t = parent_element<TParent, T>;
	using child_element_t  = child_element<T, TParent>;

	constexpr
	child_element();
	~child_element() noexcept;

public:
	// -- Move --------------------------------------------------------------
	constexpr
	child_element(child_element<T, TParent>&& other);
	constexpr
	child_element<T, TParent>& operator=(child_element<T, TParent>&& other) noexcept;

	// -- Functionality -----------------------------------------------------
	void push_front(T* t) noexcept;
	void push_back(T* t) noexcept;

	void remove() noexcept;

	// -- Getters / Setters -------------------------------------------------
	      TParent* parent()       noexcept { return m_parent; }
	const TParent* parent() const noexcept { return m_parent; }
};

#ifdef STX_WIP

template<typename T>
class tree_node :
	public parent_element<T, T>,
	public child_element <T, T>
{
	// should need nothing but constructor & destructor
};

#endif // STX_WIP

} // namespace stx

#include "graph.inl"
<commit_msg>list_element<Telement, Tparent>::parent() is now const<commit_after>#pragma once

#include <type_traits>
#include <utility>

#ifdef STX_DEBUG
#	include "assert.hpp"
#endif

namespace stx {

template<typename T>
class list_element {
public:
	using Tself = list_element<T>;
private:
	T* m_next;
	T* m_last;

	void update_next_last() noexcept;

protected:
	constexpr
	list_element();
	~list_element() noexcept;

	// -- Move --------------------------------------------------------------
	constexpr
	list_element(Tself&& e);
	constexpr
	Tself& operator=(Tself&& e) noexcept;

	// -- Copy --------------------------------------------------------------
	list_element(Tself const&)     = delete;
	Tself& operator=(Tself const&) = delete;

public:

	// -- Functionality -----------------------------------------------------
	void remove() noexcept;

	void push_front(T* p) noexcept;
	void push_back(T* p) noexcept;

	void insert_as_last(T* p) noexcept;

	void insert_as_next(T* p) noexcept;

	// -- Getters / Setters -------------------------------------------------
	      T* next()       noexcept { return m_next; }
	      T* last()       noexcept { return m_last; }
	const T* next() const noexcept { return m_next; }
	const T* last() const noexcept { return m_last; }

	      T* tail()       noexcept;
	const T* tail() const noexcept;

	      T* head()       noexcept;
	const T* head() const noexcept;
};

template<typename T, typename TParent>
class child_element;

template<typename T, typename TChild>
class parent_element {
	using Tself  = parent_element<T, TChild>;

	TChild* m_children;

	friend T;
	friend class child_element<TChild, T>;

protected:
	using parent_element_t = parent_element<T, TChild>;
	using child_element_t  = child_element<TChild, T>;

	parent_element();
	~parent_element() noexcept;

public:
	// -- Move --------------------------------------------------------------
	parent_element(Tself&& e);
	Tself& operator=(Tself&& other) noexcept;

	// -- Copy --------------------------------------------------------------
	parent_element(Tself const&) = delete;
	Tself& operator=(Tself const&) = delete;

	// -- Functionality -----------------------------------------------------
	void push_back(TChild* c) noexcept;
	void push_front(TChild* c) noexcept;

	// -- Getters / Setters -------------------------------------------------
	      TChild* children()       noexcept { return m_children; }
	const TChild* children() const noexcept { return m_children; }
};

template<typename T, typename TParent>
class child_element : public list_element<T> {
	mutable TParent* m_parent;

	friend class parent_element<TParent, T>;
protected:
	using parent_element_t = parent_element<TParent, T>;
	using child_element_t  = child_element<T, TParent>;

	constexpr
	child_element();
	~child_element() noexcept;

public:
	// -- Move --------------------------------------------------------------
	constexpr
	child_element(child_element<T, TParent>&& other);
	constexpr
	child_element<T, TParent>& operator=(child_element<T, TParent>&& other) noexcept;

	// -- Functionality -----------------------------------------------------
	void push_front(T* t) noexcept;
	void push_back(T* t) noexcept;

	void remove() noexcept;

	// -- Getters / Setters -------------------------------------------------
	TParent* parent() const noexcept { return m_parent; }
};

#ifdef STX_WIP

template<typename T>
class tree_node :
	public parent_element<T, T>,
	public child_element <T, T>
{
	// should need nothing but constructor & destructor
};

#endif // STX_WIP

} // namespace stx

#include "graph.inl"
<|endoftext|>


<commit_before>#if !defined(DOUBLETAKE_THREADINFO_H)
#define DOUBLETAKE_THREADINFO_H

/*
 * @file   threadinfo.h
 * @brief  Manageing the information about threads.
 * @author Tongping Liu <http://www.cs.umass.edu/~tonyliu>
 */

#include <assert.h>
#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <new>

#include "globalinfo.hh"
#include "internalheap.hh"
#include "list.hh"
#include "mm.hh"
#include "real.hh"
#include "sysrecord.hh"
#include "recordentries.hh"
#include "threadmap.hh"
#include "threadstruct.hh"
#include "xcontext.hh"
#include "xdefines.hh"

typedef enum e_syncVariable {
  E_SYNCVAR_THREAD = 0,
  E_SYNCVAR_COND,
  E_SYNCVAR_MUTEX,
  E_SYNCVAR_BARRIER
} syncVariableType;

// Each synchronization variable will have a corresponding list.
struct deferSyncVariable {
  list_t list;
  syncVariableType syncVarType;
  void* variable;
};

/// @class threadinfo
class threadinfo {
public:
  explicit threadinfo()
    : _aliveThreads(0), _reapableThreads(0), _totalThreads(0), _threadIndex(0),
      _deferSyncs() {
    memset(_threads, 0, sizeof(_threads[0]) * xdefines::MAX_ALIVE_THREADS);
  }

  void initialize() {
    _aliveThreads = 0;
    _reapableThreads = 0;
    _threadIndex = 0;

    _totalThreads = xdefines::MAX_ALIVE_THREADS;

    // Shared the threads information.
    memset(&_threads, 0, sizeof(_threads));

    // Initialize the backup stacking information.
    size_t perStackSize = __max_stack_size;

    unsigned long totalStackSize = perStackSize * xdefines::MAX_ALIVE_THREADS;
    unsigned long perQbufSize = xdefines::QUARANTINE_BUF_SIZE * sizeof(freeObject);
    unsigned long qbufSize = perQbufSize * xdefines::MAX_ALIVE_THREADS * 2;

    char* stackStart = (char*)MM::mmapAllocatePrivate(totalStackSize + qbufSize);
    char* qbufStart = (char*)((intptr_t)stackStart + totalStackSize);

    // Initialize all mutex.
    thread_t* tinfo;

    for(int i = 0; i < xdefines::MAX_ALIVE_THREADS; i++) {
      tinfo = &_threads[i];

			// Those information that are only initialized once.
     	tinfo->available = true;
      tinfo->context.setupBackup(&stackStart[perStackSize * i]);
      tinfo->qlist.initialize(&qbufStart[perQbufSize * i * 2], perQbufSize);
    }

    // Initialize the total event list.
    listInit(&_deferSyncs);
  }

  void finalize() {}

	// Everytime, when a corresponding threadstruct is re-utilized by a different
	// thread, we will re-initilize this. Thus, it is perfect to put this into
	// allocThreadIndex();

	void threadInitialize(thread_t * thread) {
      // Initialize the system call entries.
      thread->syscalls.initialize(xdefines::MAX_SYSCALL_ENTRIES);

			// Initilize the list of system calls.
			for(int i = 0; i < E_SYS_MAX; i++) {
				listInit(&thread->syslist[i]);
			}

      // Initialize this syncevents.
      thread->syncevents.initialize(xdefines::MAX_SYNCEVENT_ENTRIES);

      // Starting
      Real::pthread_mutex_init(&thread->mutex, NULL);
      Real::pthread_cond_init(&thread->cond, NULL);
	}

  /// @ internal function: allocation a thread index when spawning.
  /// Since we guarantee that only one thread can be in spawning phase,
  /// there is no need to acqurie the lock here.
  int allocThreadIndex() {
    int index = -1;

		// Return a failure if the number of alive threads is larger than
    if(_aliveThreads >= _totalThreads) {
      return index;
    }

    int origindex = _threadIndex;
    thread_t* thread;
    while(true) {
      thread = getThreadInfo(_threadIndex);
      if(thread->available) {
        thread->available = false;
        index = _threadIndex;

        // A thread is counted as alive when its structure is allocated.
        _aliveThreads++;

        _threadIndex = (_threadIndex + 1) % _totalThreads;
				threadInitialize(thread);
        break;
      } else {
        _threadIndex = (_threadIndex + 1) % _totalThreads;
      }

      // It is impossible that we search the whole array and we can't find
      // an available slot.
      assert(_threadIndex != origindex);
    }
    return index;
  }

  inline thread_t* getThreadInfo(int index) { return &_threads[index]; }

  inline thread_t* getThread(pthread_t thread) {
    return threadmap::getInstance().getThreadInfo(thread);
  }

  inline char* getThreadBuffer(int index) {
    thread_t* thread = getThreadInfo(index);

    return thread->outputBuf;
  }

	// Everytime, a pthread_join call will put the joinee into the queue of deadthreads.
  inline int incrementReapableThreads() {
    _reapableThreads++;
    return _reapableThreads;
  }

  inline bool hasReapableThreads() {
    // fprintf(stderr, "_reapableThreads %d\n", _reapableThreads);
    return (_reapableThreads != 0);
  }

  // Insert a synchronization variable into the global list, which
  // are reaped later at commit points.
  inline bool deferSync(void* ptr, syncVariableType type) {
    struct deferSyncVariable* syncVar = NULL;
		bool toReapThreads = false;

    syncVar = (struct deferSyncVariable*)InternalHeap::getInstance().malloc(
        sizeof(struct deferSyncVariable));

    if(syncVar == NULL) {
      fprintf(stderr, "No enough private memory, syncVar %p\n", (void *)syncVar);
      return toReapThreads;
    }

    listInit(&syncVar->list);
    syncVar->syncVarType = type;
    syncVar->variable = ptr;

    global_lock();

    listInsertTail(&syncVar->list, &_deferSyncs);
    if(type == E_SYNCVAR_THREAD) {
      int reapThreads = incrementReapableThreads();

			if((reapThreads >= xdefines::MAX_REAPABLE_THREADS) && (_aliveThreads - reapThreads) == 1) {
				toReapThreads = true;
			}
    }

    global_unlock();

		return toReapThreads;
  }

  void cancelAliveThread(pthread_t thread) {
    thread_t* deadThread = getThread(thread);

    global_lock();

    threadmap::getInstance().removeAliveThread(deadThread);
    _aliveThreads--;
    _reapableThreads--;
    global_unlock();
  }

  // We actually get those parameter about new created thread
  /*
      E_SYNCVAR_THREAD = 0,
      E_SYNCVAR_COND,
      E_SYNCVAR_MUTEX,
      E_SYNCVAR_BARRIER
  */
  void runDeferredSyncs() {
    list_t* entry;
    global_lock();

    // Get all entries from _deferSyncs.
    while((entry = listRetrieveItem(&_deferSyncs)) != NULL) {
      struct deferSyncVariable* syncvar = (struct deferSyncVariable*)entry;
      fprintf(stderr, "runDeferredSyncs with type %d variable %p\n", syncvar->syncVarType, (void *)syncvar->variable);

      switch(syncvar->syncVarType) {

      case E_SYNCVAR_THREAD: {
				//fprintf(stderr, "runDeferredSyncs with type %d variable %p\n", syncvar->syncVarType, (thread_t*)syncvar->variable);
        threadmap::getInstance().removeAliveThread((thread_t*)syncvar->variable);
        _aliveThreads--;
        _reapableThreads--;
        break;
      }

      case E_SYNCVAR_COND: {
        Real::pthread_cond_destroy((pthread_cond_t*)syncvar->variable);
        break;
      }

      case E_SYNCVAR_MUTEX: {
        Real::pthread_mutex_destroy((pthread_mutex_t*)syncvar->variable);
        break;
      }

      case E_SYNCVAR_BARRIER: {
        break;
      }

      default:
        assert(0);
        break;
      }

			// We should deallocate the actual synchronization variable.
			if(syncvar->syncVarType != E_SYNCVAR_THREAD) {
				void** ptr = (void**)syncvar->variable;
				InternalHeap::getInstance().free(*ptr);
			}

      // Free this entry.
      InternalHeap::getInstance().free((void*)entry);
    }

    listInit(&_deferSyncs);
		global_unlock();
  }

private:
  int _aliveThreads;    // a. How many alive threads totally.
  int _reapableThreads; // a. How many alive threads totally.
  int _totalThreads;    // b. How many alive threads we can hold
  int _threadIndex;     // b. What is the current thread index.
                        // list_t  _aliveList;    // List of alive threads.
                        // list_t  _deadList;     // List of dead threads.
  list_t _deferSyncs;   // deferred synchronizations.
                        // pthread_mutex_t _mutex; // Mutex to protect these list.
  thread_t _threads[xdefines::MAX_ALIVE_THREADS];
  /*
    char * position;     // c. What is the global heap metadata.
    size_t remainingsize; //
    h. User thread mapping address.
    i. Maybe the application text start and text end.
    j. Those mapping address
  */
};

#endif
<commit_msg>threadinfo: allocate memory for quarantine indepentently of stack<commit_after>#if !defined(DOUBLETAKE_THREADINFO_H)
#define DOUBLETAKE_THREADINFO_H

/*
 * @file   threadinfo.h
 * @brief  Manageing the information about threads.
 * @author Tongping Liu <http://www.cs.umass.edu/~tonyliu>
 */

#include <assert.h>
#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <new>

#include "globalinfo.hh"
#include "internalheap.hh"
#include "list.hh"
#include "mm.hh"
#include "real.hh"
#include "sysrecord.hh"
#include "recordentries.hh"
#include "threadmap.hh"
#include "threadstruct.hh"
#include "xcontext.hh"
#include "xdefines.hh"

typedef enum e_syncVariable {
  E_SYNCVAR_THREAD = 0,
  E_SYNCVAR_COND,
  E_SYNCVAR_MUTEX,
  E_SYNCVAR_BARRIER
} syncVariableType;

// Each synchronization variable will have a corresponding list.
struct deferSyncVariable {
  list_t list;
  syncVariableType syncVarType;
  void* variable;
};

/// @class threadinfo
class threadinfo {
public:
  explicit threadinfo()
    : _aliveThreads(0), _reapableThreads(0), _totalThreads(0), _threadIndex(0),
      _deferSyncs() {
    memset(_threads, 0, sizeof(_threads[0]) * xdefines::MAX_ALIVE_THREADS);
  }

  void initialize() {
    _aliveThreads = 0;
    _reapableThreads = 0;
    _threadIndex = 0;

    _totalThreads = xdefines::MAX_ALIVE_THREADS;

    // Shared the threads information.
    memset(&_threads, 0, sizeof(_threads));

    // Initialize the backup stacking information.
    size_t perStackSize = __max_stack_size;

    unsigned long totalStackSize = perStackSize * xdefines::MAX_ALIVE_THREADS;
    unsigned long perQbufSize = xdefines::QUARANTINE_BUF_SIZE * sizeof(freeObject);
    unsigned long qbufSize = perQbufSize * xdefines::MAX_ALIVE_THREADS * 2;

    char* stackStart = (char*)MM::mmapAllocatePrivate(totalStackSize);
    char* qbufStart = (char*)MM::mmapAllocatePrivate(qbufSize);

    // Initialize all mutex.
    thread_t* tinfo;

    for(int i = 0; i < xdefines::MAX_ALIVE_THREADS; i++) {
      tinfo = &_threads[i];

			// Those information that are only initialized once.
     	tinfo->available = true;
      tinfo->context.setupBackup(&stackStart[perStackSize * i]);
      tinfo->qlist.initialize(&qbufStart[perQbufSize * i * 2], perQbufSize);
    }

    // Initialize the total event list.
    listInit(&_deferSyncs);
  }

  void finalize() {}

	// Everytime, when a corresponding threadstruct is re-utilized by a different
	// thread, we will re-initilize this. Thus, it is perfect to put this into
	// allocThreadIndex();

	void threadInitialize(thread_t * thread) {
      // Initialize the system call entries.
      thread->syscalls.initialize(xdefines::MAX_SYSCALL_ENTRIES);

			// Initilize the list of system calls.
			for(int i = 0; i < E_SYS_MAX; i++) {
				listInit(&thread->syslist[i]);
			}

      // Initialize this syncevents.
      thread->syncevents.initialize(xdefines::MAX_SYNCEVENT_ENTRIES);

      // Starting
      Real::pthread_mutex_init(&thread->mutex, NULL);
      Real::pthread_cond_init(&thread->cond, NULL);
	}

  /// @ internal function: allocation a thread index when spawning.
  /// Since we guarantee that only one thread can be in spawning phase,
  /// there is no need to acqurie the lock here.
  int allocThreadIndex() {
    int index = -1;

		// Return a failure if the number of alive threads is larger than
    if(_aliveThreads >= _totalThreads) {
      return index;
    }

    int origindex = _threadIndex;
    thread_t* thread;
    while(true) {
      thread = getThreadInfo(_threadIndex);
      if(thread->available) {
        thread->available = false;
        index = _threadIndex;

        // A thread is counted as alive when its structure is allocated.
        _aliveThreads++;

        _threadIndex = (_threadIndex + 1) % _totalThreads;
				threadInitialize(thread);
        break;
      } else {
        _threadIndex = (_threadIndex + 1) % _totalThreads;
      }

      // It is impossible that we search the whole array and we can't find
      // an available slot.
      assert(_threadIndex != origindex);
    }
    return index;
  }

  inline thread_t* getThreadInfo(int index) { return &_threads[index]; }

  inline thread_t* getThread(pthread_t thread) {
    return threadmap::getInstance().getThreadInfo(thread);
  }

  inline char* getThreadBuffer(int index) {
    thread_t* thread = getThreadInfo(index);

    return thread->outputBuf;
  }

	// Everytime, a pthread_join call will put the joinee into the queue of deadthreads.
  inline int incrementReapableThreads() {
    _reapableThreads++;
    return _reapableThreads;
  }

  inline bool hasReapableThreads() {
    // fprintf(stderr, "_reapableThreads %d\n", _reapableThreads);
    return (_reapableThreads != 0);
  }

  // Insert a synchronization variable into the global list, which
  // are reaped later at commit points.
  inline bool deferSync(void* ptr, syncVariableType type) {
    struct deferSyncVariable* syncVar = NULL;
		bool toReapThreads = false;

    syncVar = (struct deferSyncVariable*)InternalHeap::getInstance().malloc(
        sizeof(struct deferSyncVariable));

    if(syncVar == NULL) {
      fprintf(stderr, "No enough private memory, syncVar %p\n", (void *)syncVar);
      return toReapThreads;
    }

    listInit(&syncVar->list);
    syncVar->syncVarType = type;
    syncVar->variable = ptr;

    global_lock();

    listInsertTail(&syncVar->list, &_deferSyncs);
    if(type == E_SYNCVAR_THREAD) {
      int reapThreads = incrementReapableThreads();

			if((reapThreads >= xdefines::MAX_REAPABLE_THREADS) && (_aliveThreads - reapThreads) == 1) {
				toReapThreads = true;
			}
    }

    global_unlock();

		return toReapThreads;
  }

  void cancelAliveThread(pthread_t thread) {
    thread_t* deadThread = getThread(thread);

    global_lock();

    threadmap::getInstance().removeAliveThread(deadThread);
    _aliveThreads--;
    _reapableThreads--;
    global_unlock();
  }

  // We actually get those parameter about new created thread
  /*
      E_SYNCVAR_THREAD = 0,
      E_SYNCVAR_COND,
      E_SYNCVAR_MUTEX,
      E_SYNCVAR_BARRIER
  */
  void runDeferredSyncs() {
    list_t* entry;
    global_lock();

    // Get all entries from _deferSyncs.
    while((entry = listRetrieveItem(&_deferSyncs)) != NULL) {
      struct deferSyncVariable* syncvar = (struct deferSyncVariable*)entry;
      fprintf(stderr, "runDeferredSyncs with type %d variable %p\n", syncvar->syncVarType, (void *)syncvar->variable);

      switch(syncvar->syncVarType) {

      case E_SYNCVAR_THREAD: {
				//fprintf(stderr, "runDeferredSyncs with type %d variable %p\n", syncvar->syncVarType, (thread_t*)syncvar->variable);
        threadmap::getInstance().removeAliveThread((thread_t*)syncvar->variable);
        _aliveThreads--;
        _reapableThreads--;
        break;
      }

      case E_SYNCVAR_COND: {
        Real::pthread_cond_destroy((pthread_cond_t*)syncvar->variable);
        break;
      }

      case E_SYNCVAR_MUTEX: {
        Real::pthread_mutex_destroy((pthread_mutex_t*)syncvar->variable);
        break;
      }

      case E_SYNCVAR_BARRIER: {
        break;
      }

      default:
        assert(0);
        break;
      }

			// We should deallocate the actual synchronization variable.
			if(syncvar->syncVarType != E_SYNCVAR_THREAD) {
				void** ptr = (void**)syncvar->variable;
				InternalHeap::getInstance().free(*ptr);
			}

      // Free this entry.
      InternalHeap::getInstance().free((void*)entry);
    }

    listInit(&_deferSyncs);
		global_unlock();
  }

private:
  int _aliveThreads;    // a. How many alive threads totally.
  int _reapableThreads; // a. How many alive threads totally.
  int _totalThreads;    // b. How many alive threads we can hold
  int _threadIndex;     // b. What is the current thread index.
                        // list_t  _aliveList;    // List of alive threads.
                        // list_t  _deadList;     // List of dead threads.
  list_t _deferSyncs;   // deferred synchronizations.
                        // pthread_mutex_t _mutex; // Mutex to protect these list.
  thread_t _threads[xdefines::MAX_ALIVE_THREADS];
  /*
    char * position;     // c. What is the global heap metadata.
    size_t remainingsize; //
    h. User thread mapping address.
    i. Maybe the application text start and text end.
    j. Those mapping address
  */
};

#endif
<|endoftext|>


<commit_before>// ffmpeg_acoustid.cpp
// part of MusicPlayer, https://github.com/albertz/music-player
// Copyright (c) 2012, Albert Zeyer, www.az2000.de
// All rights reserved.
// This code is under the 2-clause BSD license, see License.txt in the root directory of this project.

#include "ffmpeg.h"
#include <chromaprint.h>

PyObject *
pyCalcAcoustIdFingerprint(PyObject* self, PyObject* args) {
	PyObject* songObj = NULL;
	if(!PyArg_ParseTuple(args, "O:calcAcoustIdFingerprint", &songObj))
		return NULL;

	PyObject* returnObj = NULL;
	PlayerObject* player = NULL;
	ChromaprintContext *chromaprint_ctx = NULL;
	unsigned long totalFrameCount = 0;

	player = (PlayerObject*) pyCreatePlayer(NULL);
	if(!player) goto final;
	player->lock.enabled = false;
	player->nextSongOnEof = false;
	player->skipPyExceptions = false;
	player->playing = true; // otherwise audio_decode_frame() wont read
	player->volumeAdjustEnabled = false; // avoid volume adjustments
	Py_INCREF(songObj);
	player->curSong = songObj;
	if(!player->openInStream()) goto final;
	if(PyErr_Occurred()) goto final;
	if(player->inStream == NULL) goto final;

	// fpcalc source for reference:
	// https://github.com/lalinsky/chromaprint/blob/master/examples/fpcalc.c

	chromaprint_ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT);
	chromaprint_start(chromaprint_ctx, player->outSamplerate, player->outNumChannels);

	// Note that we don't have any max_length handling yet.
	// fpcalc uses a default of 120 seconds.
	// This function right now doesn't rely on any external song duration
	// source, so it is a perfect reliable way to calculate also the
	// song duration.
	// I'm not sure how expensive audio_decode_frame is compared to
	// chromaprint_feed, so if we just decode everything to calculate
	// a reliable song duration, it might make sense to just feed
	// everything to chromaprint.
	// Maybe we can optimize audio_decode_frame though to just return the
	// len and don't do any decoding if we just want to calculate the len.
	// This is all open for future hacking ... But it works good enough now.

	while(player->processInStream()) {
		if(PyErr_Occurred()) goto final;
		for(auto& it : player->inStreamBuffer()->chunks) {
			totalFrameCount += it.size() / player->outNumChannels / OUTSAMPLEBYTELEN;

			int16_t pcmBuffer[BUFFER_CHUNK_SIZE/OUTSAMPLEBYTELEN];
			uint16_t len = it.size() / OUTSAMPLEBYTELEN;
			for(uint16_t i = 0; i < len; ++i)
				pcmBuffer[i] = FloatToPCM16(((OUTSAMPLE_t*)it.pt())[i]);

			if (!chromaprint_feed(chromaprint_ctx, it.pt(), len)) {
				PyErr_SetString(PyExc_RuntimeError, "fingerprint feed calculation failed");
				goto final;
			}
		}
		player->inStreamBuffer()->clear();
	}
	// If we have too less data -> fail. chromaprint_finish will print a warning/error but wont fail.
	// 16 seems like a good lower limit. It is also the limit of the default Chromaprint Fingerprint algorithm.
	if(totalFrameCount < 16) {
		PyErr_SetString(PyExc_RuntimeError, "too less data for fingerprint");
		goto final;
	}
	{
		double songDuration = (double)totalFrameCount / player->outSamplerate;
		char* fingerprint = NULL;

		if (!chromaprint_finish(chromaprint_ctx)) {
			PyErr_SetString(PyExc_RuntimeError, "fingerprint finish calculation failed");
			goto final;
		}

		if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) {
			PyErr_SetString(PyExc_RuntimeError, "unable to calculate fingerprint, get_fingerprint failed");
			goto final;
		}

		returnObj = PyTuple_New(2);
		PyTuple_SetItem(returnObj, 0, PyFloat_FromDouble(songDuration));
		PyTuple_SetItem(returnObj, 1, PyString_FromString(fingerprint));

		chromaprint_dealloc(fingerprint);
	}

final:
	if(chromaprint_ctx)
		chromaprint_free(chromaprint_ctx);
	if(!PyErr_Occurred() && !returnObj) {
		returnObj = Py_None;
		Py_INCREF(returnObj);
	}
	Py_XDECREF(player);
	return returnObj;
}
<commit_msg>stupid fix<commit_after>// ffmpeg_acoustid.cpp
// part of MusicPlayer, https://github.com/albertz/music-player
// Copyright (c) 2012, Albert Zeyer, www.az2000.de
// All rights reserved.
// This code is under the 2-clause BSD license, see License.txt in the root directory of this project.

#include "ffmpeg.h"
#include <chromaprint.h>

PyObject *
pyCalcAcoustIdFingerprint(PyObject* self, PyObject* args) {
	PyObject* songObj = NULL;
	if(!PyArg_ParseTuple(args, "O:calcAcoustIdFingerprint", &songObj))
		return NULL;

	PyObject* returnObj = NULL;
	PlayerObject* player = NULL;
	ChromaprintContext *chromaprint_ctx = NULL;
	unsigned long totalFrameCount = 0;

	player = (PlayerObject*) pyCreatePlayer(NULL);
	if(!player) goto final;
	player->lock.enabled = false;
	player->nextSongOnEof = false;
	player->skipPyExceptions = false;
	player->playing = true; // otherwise audio_decode_frame() wont read
	player->volumeAdjustEnabled = false; // avoid volume adjustments
	Py_INCREF(songObj);
	player->curSong = songObj;
	if(!player->openInStream()) goto final;
	if(PyErr_Occurred()) goto final;
	if(player->inStream == NULL) goto final;

	// fpcalc source for reference:
	// https://github.com/lalinsky/chromaprint/blob/master/examples/fpcalc.c

	chromaprint_ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT);
	chromaprint_start(chromaprint_ctx, player->outSamplerate, player->outNumChannels);

	// Note that we don't have any max_length handling yet.
	// fpcalc uses a default of 120 seconds.
	// This function right now doesn't rely on any external song duration
	// source, so it is a perfect reliable way to calculate also the
	// song duration.
	// I'm not sure how expensive audio_decode_frame is compared to
	// chromaprint_feed, so if we just decode everything to calculate
	// a reliable song duration, it might make sense to just feed
	// everything to chromaprint.
	// Maybe we can optimize audio_decode_frame though to just return the
	// len and don't do any decoding if we just want to calculate the len.
	// This is all open for future hacking ... But it works good enough now.

	while(player->processInStream()) {
		if(PyErr_Occurred()) goto final;
		for(auto& it : player->inStreamBuffer()->chunks) {
			totalFrameCount += it.size() / player->outNumChannels / OUTSAMPLEBYTELEN;

			// chromaprint expects sint16 sample format.
			int16_t pcmBuffer[BUFFER_CHUNK_SIZE/OUTSAMPLEBYTELEN];
			uint16_t len = it.size() / OUTSAMPLEBYTELEN;
			for(uint16_t i = 0; i < len; ++i) {
				OUTSAMPLE_t s = ((OUTSAMPLE_t*)it.pt())[i];
				pcmBuffer[i] = FloatToPCM16(OutSampleAsFloat(s));
			}

			if (!chromaprint_feed(chromaprint_ctx, pcmBuffer, len)) {
				PyErr_SetString(PyExc_RuntimeError, "fingerprint feed calculation failed");
				goto final;
			}
		}
		player->inStreamBuffer()->clear();
	}
	// If we have too less data -> fail. chromaprint_finish will print a warning/error but wont fail.
	// 16 seems like a good lower limit. It is also the limit of the default Chromaprint Fingerprint algorithm.
	if(totalFrameCount < 16) {
		PyErr_SetString(PyExc_RuntimeError, "too less data for fingerprint");
		goto final;
	}
	{
		double songDuration = (double)totalFrameCount / player->outSamplerate;
		char* fingerprint = NULL;

		if (!chromaprint_finish(chromaprint_ctx)) {
			PyErr_SetString(PyExc_RuntimeError, "fingerprint finish calculation failed");
			goto final;
		}

		if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) {
			PyErr_SetString(PyExc_RuntimeError, "unable to calculate fingerprint, get_fingerprint failed");
			goto final;
		}

		returnObj = PyTuple_New(2);
		PyTuple_SetItem(returnObj, 0, PyFloat_FromDouble(songDuration));
		PyTuple_SetItem(returnObj, 1, PyString_FromString(fingerprint));

		chromaprint_dealloc(fingerprint);
	}

final:
	if(chromaprint_ctx)
		chromaprint_free(chromaprint_ctx);
	if(!PyErr_Occurred() && !returnObj) {
		returnObj = Py_None;
		Py_INCREF(returnObj);
	}
	Py_XDECREF(player);
	return returnObj;
}
<|endoftext|>


<commit_before>{
   GeFiCa::Sphere1D *sphere1d=new GeFiCa::Sphere1D(101);
   sphere1d->V1=0*GeFiCa::volt;
   sphere1d->V0=2000*GeFiCa::volt;
   sphere1d->InnerRadius=0.5*GeFiCa::cm;
   sphere1d->OuterRadius=2.5*GeFiCa::cm;
   sphere1d->SetAverageImpurity(1e10/GeFiCa::cm3);
   sphere1d->CalculatePotential(GeFiCa::kAnalytic);
   sphere1d->SaveField("sphere1dTrue.root");

   GeFiCa::Sphere *sphere3d=new GeFiCa::Sphere(101,10,10);
   sphere3d->MaxIterations=1e5;
   sphere3d->Csor=1.96;
   sphere3d->V1=0*GeFiCa::volt;
   sphere3d->V0=2000*GeFiCa::volt;
   sphere3d->InnerRadius=0.5*GeFiCa::cm;
   sphere3d->OuterRadius=2.5*GeFiCa::cm;
   sphere3d->SetAverageImpurity(1e10/GeFiCa::cm3);
   sphere3d->CalculatePotential(GeFiCa::kSOR2);
   sphere3d->SaveField("sphere3dSOR2.root");

   // generate graphics
   TChain *tn = new TChain("t");
   tn->Add("sphere3dSOR2.root");
   tn->Draw("p:c1");
   TGraph *gn = new TGraph(tn->GetSelectedRows(), tn->GetV2(), tn->GetV1());

   TChain *ta = new TChain("t");
   ta->Add("sphere1dTrue.root");
   ta->Draw("p:c1");
   TGraph *ga = new TGraph(ta->GetSelectedRows(), ta->GetV2(), ta->GetV1());

   // make final plot
   gn->SetMarkerColor(kBlue);
   gn->SetMarkerStyle(6);
   gn->SetMarkerSize(0.8);
   ga->SetLineColor(kRed);
   gn->SetTitle(";Thickness [cm];Potential [V]");
   gn->Draw("ap");
   ga->Draw("l");
}
<commit_msg>macro updated<commit_after>// compare numerical result to analytic calculation for 3D sphere detector
{
   GeFiCa::Sphere *sphere3d=new GeFiCa::Sphere(101,10,10);
   sphere3d->MaxIterations=1e5;
   sphere3d->Csor=1.96;
   sphere3d->V1=0*GeFiCa::volt;
   sphere3d->V0=2000*GeFiCa::volt;
   sphere3d->InnerRadius=0.5*GeFiCa::cm;
   sphere3d->OuterRadius=2.5*GeFiCa::cm;
   sphere3d->SetAverageImpurity(1e10/GeFiCa::cm3);
   sphere3d->Dump();
   cout<<"press any key to continue"<<endl;
   cin.get();

   //use analytic method from 1D sphere
   GeFiCa::Sphere1D *sphere1d=new GeFiCa::Sphere1D(101);
   sphere1d->V1=0*GeFiCa::volt;
   sphere1d->V0=2000*GeFiCa::volt;
   sphere1d->InnerRadius=0.5*GeFiCa::cm;
   sphere1d->OuterRadius=2.5*GeFiCa::cm;
   sphere1d->SetAverageImpurity(1e10/GeFiCa::cm3);

   // calculate fields with two different methods
   sphere1d->CalculatePotential(GeFiCa::kAnalytic);
   sphere1d->SaveField("sphere1dTrue.root");
   sphere3d->CalculatePotential(GeFiCa::kSOR2);
   sphere3d->SaveField("sphere3dSOR2.root");

   // prepare drawing style
   gROOT->SetStyle("Plain"); // pick up a good drawing style to modify
   gStyle->SetLegendBorderSize(0);
   gStyle->SetLegendFont(132);
   gStyle->SetLabelFont(132,"XY");
   gStyle->SetTitleFont(132,"XY");
   gStyle->SetLabelSize(0.05,"XY");
   gStyle->SetTitleSize(0.05,"XY");
   gStyle->SetPadRightMargin(0.01);
   gStyle->SetPadLeftMargin(0.12);
   gStyle->SetPadTopMargin(0.02);

   // generate graphics
   TChain *tn = new TChain("t");
   tn->Add("sphere3dSOR2.root");
   tn->Draw("p:c1");
   TGraph *gn = new TGraph(tn->GetSelectedRows(), tn->GetV2(), tn->GetV1());

   TChain *ta = new TChain("t");
   ta->Add("sphere1dTrue.root");
   ta->Draw("p:c1");
   TGraph *ga = new TGraph(ta->GetSelectedRows(), ta->GetV2(), ta->GetV1());

   // make final plot
   gn->SetMarkerColor(kBlue);
   gn->SetMarkerStyle(kCircle);
   gn->SetMarkerSize(0.8);
   ga->SetLineColor(kRed);
   gn->SetTitle(";Thickness [cm];Potential [V]");
   gn->Draw("ap");
   ga->Draw("l");

   TLegend *l = new TLegend(0.7,0.6,0.9,0.8);
   l->AddEntry(ga,"Analytic","l");
   l->AddEntry(gn,"SOR2","p");
   l->Draw();

   gPad->Print("sphere3d.png");
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary verbiage.<commit_after><|endoftext|>


<commit_before>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/fml/thread_local.h"

#if FML_THREAD_LOCAL_PTHREADS

#include "flutter/fml/logging.h"

namespace fml {
namespace internal {

ThreadLocalPointer::ThreadLocalPointer(void (*destroy)(void*)) {
  FML_CHECK(pthread_key_create(&key_, destroy) == 0);
}

ThreadLocalPointer::~ThreadLocalPointer() {
  FML_CHECK(pthread_key_delete(key_) == 0);
}

void* ThreadLocalPointer::get() const {
  return pthread_getspecific(key_);
}

void* ThreadLocalPointer::swap(void* ptr) {
  void* old_ptr = get();
  FML_CHECK(pthread_setspecific(key_, ptr) == 0);
  return old_ptr;
}

}  // namespace internal
}  // namespace fml

#endif  // FML_THREAD_LOCAL_PTHREADS
<commit_msg>Better logging pthread_setspecific (#26460)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/fml/thread_local.h"

#if FML_THREAD_LOCAL_PTHREADS

#include "flutter/fml/logging.h"

namespace fml {
namespace internal {

ThreadLocalPointer::ThreadLocalPointer(void (*destroy)(void*)) {
  FML_CHECK(pthread_key_create(&key_, destroy) == 0);
}

ThreadLocalPointer::~ThreadLocalPointer() {
  FML_CHECK(pthread_key_delete(key_) == 0);
}

void* ThreadLocalPointer::get() const {
  return pthread_getspecific(key_);
}

void* ThreadLocalPointer::swap(void* ptr) {
  void* old_ptr = get();
  int err = pthread_setspecific(key_, ptr);
  if (err) {
    FML_CHECK(false) << "pthread_setspecific failed (" << err
                     << "): " << strerror(err);
  }
  return old_ptr;
}

}  // namespace internal
}  // namespace fml

#endif  // FML_THREAD_LOCAL_PTHREADS
<|endoftext|>