<commit_before>/******************************************************************************/
/* Copyright (c) 2013 VectorChief (at github, bitbucket, sourceforge)         */
/* Distributed under the MIT software license, see the accompanying           */
/* file COPYING or http://www.opensource.org/licenses/mit-license.php         */
/******************************************************************************/

#include "RooT.h"

/******************************************************************************/
/****************************   PLATFORM - WIN32   ****************************/
/******************************************************************************/

#include <malloc.h>
#include <windows.h>

HINSTANCE   hInst;
HWND        hWnd;
HDC         hWndDC;

HBITMAP     hFrm;
HDC         hFrmDC;
BITMAPINFO  DIBinfo = 
{
    sizeof(BITMAPINFOHEADER),           /* biSize */
   +x_res,                              /* biWidth */
   -y_res,                              /* biHeight */
    1,                                  /* biPlanes */
    32,                                 /* biBitCount */
    BI_RGB,                             /* biCompression */
    x_res * y_res * sizeof(rt_word),    /* biSizeImage */
    0,                                  /* biXPelsPerMeter */
    0,                                  /* biYPelsPerMeter */
    0,                                  /* biClrUsed */
    0                                   /* biClrImportant */
};

/******************************************************************************/
/**********************************   MAIN   **********************************/
/******************************************************************************/

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    MSG msg;
    hInst = hInstance;

    TCHAR wnd_class[] = "RooT";

    WNDCLASSEX wcex;

    wcex.cbSize         = sizeof(WNDCLASSEX); 
    wcex.lpszClassName  = wnd_class;
    wcex.style          = CS_OWNDC;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.hInstance      = hInst;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = NULL;
    wcex.lpszMenuName   = NULL;
    wcex.hIconSm        = NULL;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;

    if (!RegisterClassEx(&wcex))
    {
        RT_LOGE("Couldn't register class\n");
        return FALSE;
    }


    RECT wRect, cRect;

    hWnd = CreateWindow(wnd_class, title,
                WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
                CW_USEDEFAULT, CW_USEDEFAULT, x_res, y_res,
                NULL, NULL, hInst, NULL);

    if (!hWnd)
    {
        RT_LOGE("Couldn't create window\n");
        return FALSE;
    }

    GetWindowRect(hWnd, &wRect);
    GetClientRect(hWnd, &cRect);
    MoveWindow(hWnd, 100, 50, 2 * x_res - cRect.right,
                              2 * y_res - cRect.bottom, FALSE);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

/******************************************************************************/
/********************************   RENDERING   *******************************/
/******************************************************************************/

rt_cell main_init()
{
    try
    {
        scene = new rt_Scene(&sc_root,
                            x_res, y_res, x_row, frame,
                            malloc, free);
    }
    catch (rt_Exception e)
    {
        RT_LOGE("Exception: %s\n", e.err);

        return 0;
    }

    return 1;
}

/* performance variables */
static LARGE_INTEGER tm;
static LARGE_INTEGER fr;

/* time counter varibales */
static rt_long init_time = 0;
static rt_long last_time = 0;
static rt_long cur_time = 0;
static rt_word fps = 0;
static rt_word cnt = 0;

/* virtual keys array */
#define KEY_MASK    0x00FF
static rt_byte h_keys[KEY_MASK + 1];
static rt_byte t_keys[KEY_MASK + 1];
static rt_byte r_keys[KEY_MASK + 1];
<commit_msg>add multi-threading implementation for Win32 platform<commit_after>/******************************************************************************/
/* Copyright (c) 2013 VectorChief (at github, bitbucket, sourceforge)         */
/* Distributed under the MIT software license, see the accompanying           */
/* file COPYING or http://www.opensource.org/licenses/mit-license.php         */
/******************************************************************************/

#include "RooT.h"

/******************************************************************************/
/****************************   PLATFORM - WIN32   ****************************/
/******************************************************************************/

#include <malloc.h>
#include <windows.h>

HINSTANCE   hInst;
HWND        hWnd;
HDC         hWndDC;

HBITMAP     hFrm;
HDC         hFrmDC;
BITMAPINFO  DIBinfo = 
{
    sizeof(BITMAPINFOHEADER),           /* biSize */
   +x_res,                              /* biWidth */
   -y_res,                              /* biHeight */
    1,                                  /* biPlanes */
    32,                                 /* biBitCount */
    BI_RGB,                             /* biCompression */
    x_res * y_res * sizeof(rt_word),    /* biSizeImage */
    0,                                  /* biXPelsPerMeter */
    0,                                  /* biYPelsPerMeter */
    0,                                  /* biClrUsed */
    0                                   /* biClrImportant */
};

/******************************************************************************/
/**********************************   MAIN   **********************************/
/******************************************************************************/

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    MSG msg;
    hInst = hInstance;

    TCHAR wnd_class[] = "RooT";

    WNDCLASSEX wcex;

    wcex.cbSize         = sizeof(WNDCLASSEX); 
    wcex.lpszClassName  = wnd_class;
    wcex.style          = CS_OWNDC;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.hInstance      = hInst;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = NULL;
    wcex.lpszMenuName   = NULL;
    wcex.hIconSm        = NULL;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;

    if (!RegisterClassEx(&wcex))
    {
        RT_LOGE("Couldn't register class\n");
        return FALSE;
    }


    RECT wRect, cRect;

    hWnd = CreateWindow(wnd_class, title,
                WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
                CW_USEDEFAULT, CW_USEDEFAULT, x_res, y_res,
                NULL, NULL, hInst, NULL);

    if (!hWnd)
    {
        RT_LOGE("Couldn't create window\n");
        return FALSE;
    }

    GetWindowRect(hWnd, &wRect);
    GetClientRect(hWnd, &cRect);
    MoveWindow(hWnd, 100, 50, 2 * x_res - cRect.right,
                              2 * y_res - cRect.bottom, FALSE);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

/******************************************************************************/
/********************************   THREADING   *******************************/
/******************************************************************************/

struct rt_THREAD
{
    rt_cell    *cmd;
    rt_cell     index;
    rt_Scene   *scene;
    HANDLE      pevent;
    HANDLE     *cevent;
    HANDLE      pthr;
};

DWORD WINAPI worker_thread(void *p)
{
    rt_THREAD *thread = (rt_THREAD *)p;
    rt_cell i = 0;

    while (1)
    {
        WaitForSingleObject(thread->cevent[i], INFINITE);

        if (!thread->scene)
        {
            break;
        }

        switch (thread->cmd[0])
        {
            case 1:
            thread->scene->update_slice(thread->index);
            break;

            case 2:
            thread->scene->render_slice(thread->index);
            break;

            default:
            break;
        };

        SetEvent(thread->pevent);
        i = 1 - i;
    }

    SetEvent(thread->pevent);
    return 1;
}

struct rt_THREAD_POOL
{
    rt_Scene   *scene;
    rt_THREAD  *thread;
    HANDLE     *edata;
    HANDLE      cevent[2];
    rt_cell     cindex;
    rt_cell     cmd;
    rt_cell     thnum;
};

rt_pntr init_threads(rt_cell thnum, rt_Scene *scn)
{
    DWORD  pam, sam;
    HANDLE process = GetCurrentProcess();
    GetProcessAffinityMask(process, &pam, &sam);

    rt_cell i, a;
    rt_THREAD_POOL *tpool = (rt_THREAD_POOL *)malloc(sizeof(rt_THREAD_POOL));

    tpool->scene = scn;
    tpool->thread = (rt_THREAD *)malloc(sizeof(rt_THREAD) * thnum);
    tpool->edata = (HANDLE *)malloc(sizeof(HANDLE) * thnum);

    tpool->cevent[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
    tpool->cevent[1] = CreateEvent(NULL, TRUE, FALSE, NULL);

    tpool->cindex = 0;
    tpool->cmd = 0;
    tpool->thnum = thnum;

    for (i = 0, a = 0; i < thnum; i++, a++)
    {
        rt_THREAD *thread = tpool->thread;

        thread[i].cmd    = &tpool->cmd;
        thread[i].index  = i;
        thread[i].scene  = scn;
        thread[i].pevent = CreateEvent(NULL, FALSE, FALSE, NULL);
        thread[i].cevent = tpool->cevent;
        thread[i].pthr = CreateThread(NULL, 0, worker_thread,
                                &thread[i], 0, NULL);

        tpool->edata[i] = thread[i].pevent;

        while (((pam & (1 << a)) == 0))
        {
            a++;
            if (a == 32) a = 0;
        }
        SetThreadAffinityMask(thread[i].pthr, 1 << a);
    }

    return tpool;
}

rt_void term_threads(rt_pntr tdata, rt_cell thnum)
{
    rt_cell i;
    rt_THREAD_POOL *tpool = (rt_THREAD_POOL *)tdata;

    for (i = 0; i < tpool->thnum; i++)
    {
        rt_THREAD *thread = tpool->thread;

        thread[i].scene = NULL;
    }

    SetEvent(tpool->cevent[tpool->cindex]);
    WaitForMultipleObjects(tpool->thnum, tpool->edata, TRUE, INFINITE);

    for (i = 0; i < tpool->thnum; i++)
    {
        rt_THREAD *thread = tpool->thread;

        CloseHandle(thread[i].pthr);
        CloseHandle(thread[i].pevent);
    }

    CloseHandle(tpool->cevent[0]);
    CloseHandle(tpool->cevent[1]);

    free(tpool->thread);
    free(tpool->edata);
    free(tpool);
}

rt_void update_scene(rt_pntr tdata, rt_cell thnum)
{
    rt_THREAD_POOL *tpool = (rt_THREAD_POOL *)tdata;

    tpool->cmd = 1;
    SetEvent(tpool->cevent[tpool->cindex]);
    WaitForMultipleObjects(tpool->thnum, tpool->edata, TRUE, INFINITE);
    ResetEvent(tpool->cevent[tpool->cindex]);
    tpool->cindex = 1 - tpool->cindex;
}

rt_void render_scene(rt_pntr tdata, rt_cell thnum)
{
    rt_THREAD_POOL *tpool = (rt_THREAD_POOL *)tdata;

    tpool->cmd = 2;
    SetEvent(tpool->cevent[tpool->cindex]);
    WaitForMultipleObjects(tpool->thnum, tpool->edata, TRUE, INFINITE);
    ResetEvent(tpool->cevent[tpool->cindex]);
    tpool->cindex = 1 - tpool->cindex;
}

/******************************************************************************/
/********************************   RENDERING   *******************************/
/******************************************************************************/

rt_cell main_init()
{
    try
    {
        scene = new rt_Scene(&sc_root,
                            x_res, y_res, x_row, frame,
                            malloc, free,
                            init_threads, term_threads,
                            update_scene, render_scene);
    }
    catch (rt_Exception e)
    {
        RT_LOGE("Exception: %s\n", e.err);

        return 0;
    }

    return 1;
}

/* performance variables */
static LARGE_INTEGER tm;
static LARGE_INTEGER fr;

/* time counter varibales */
static rt_long init_time = 0;
static rt_long last_time = 0;
static rt_long cur_time = 0;
static rt_word fps = 0;
static rt_word cnt = 0;

/* virtual keys array */
#define KEY_MASK    0x00FF
static rt_byte h_keys[KEY_MASK + 1];
static rt_byte t_keys[KEY_MASK + 1];
static rt_byte r_keys[KEY_MASK + 1];

{'fraction_non_alphanumeric': 0.24824729126832376, 'fraction_numerical': 0.008444869343530911, 'mean_word_length': 2.1933350292546425, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '861874', 'n_tokens_mistral': 4050, 'n_tokens_neox': 3764, 'n_words': 749}