/*
  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely.
*/

/* Simple test of the SDL semaphore code */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#include "SDL.h"

#define NUM_THREADS 10
/* This value should be smaller than the maximum count of the */
/* semaphore implementation: */
#define NUM_OVERHEAD_OPS 10000
#define NUM_OVERHEAD_OPS_MULT 10

static SDL_sem *sem;
int alive;

typedef struct Thread_State {
    SDL_Thread * thread;
    int number;
    SDL_bool flag;
    int loop_count;
    int content_count;
} Thread_State;

static void
killed(int sig)
{
    alive = 0;
}

static int SDLCALL
ThreadFuncRealWorld(void *data)
{
    Thread_State *state = (Thread_State *) data;
    while (alive) {
        SDL_SemWait(sem);
        SDL_Log("Thread number %d has got the semaphore (value = %" SDL_PRIu32 ")!\n",
                state->number, SDL_SemValue(sem));
        SDL_Delay(200);
        SDL_SemPost(sem);
        SDL_Log("Thread number %d has released the semaphore (value = %" SDL_PRIu32 ")!\n",
                state->number, SDL_SemValue(sem));
        ++state->loop_count;
        SDL_Delay(1);           /* For the scheduler */
    }
    SDL_Log("Thread number %d exiting.\n", state->number);
    return 0;
}

static void
TestRealWorld(int init_sem) {
    Thread_State thread_states[NUM_THREADS] = { {0} };
    int i;
    int loop_count;

    sem = SDL_CreateSemaphore(init_sem);

    SDL_Log("Running %d threads, semaphore value = %d\n", NUM_THREADS,
           init_sem);
    alive = 1;
    /* Create all the threads */
    for (i = 0; i < NUM_THREADS; ++i) {
        char name[64];
        SDL_snprintf(name, sizeof (name), "Thread%u", (unsigned int) i);
        thread_states[i].number = i;
        thread_states[i].thread = SDL_CreateThread(ThreadFuncRealWorld, name, (void *) &thread_states[i]);
    }

    /* Wait 10 seconds */
    SDL_Delay(10 * 1000);

    /* Wait for all threads to finish */
    SDL_Log("Waiting for threads to finish\n");
    alive = 0;
    loop_count = 0;
    for (i = 0; i < NUM_THREADS; ++i) {
        SDL_WaitThread(thread_states[i].thread, NULL);
        loop_count += thread_states[i].loop_count;
    }
    SDL_Log("Finished waiting for threads, ran %d loops in total\n\n", loop_count);

    SDL_DestroySemaphore(sem);
}

static void
TestWaitTimeout(void)
{
    Uint32 start_ticks;
    Uint32 end_ticks;
    Uint32 duration;
    int retval;

    sem = SDL_CreateSemaphore(0);
    SDL_Log("Waiting 2 seconds on semaphore\n");

    start_ticks = SDL_GetTicks();
    retval = SDL_SemWaitTimeout(sem, 2000);
    end_ticks = SDL_GetTicks();

    duration = end_ticks - start_ticks;

    /* Accept a little offset in the effective wait */
    SDL_assert(duration > 1900 && duration < 2050);
    SDL_Log("Wait took %" SDL_PRIu32 " milliseconds\n\n", duration);

    /* Check to make sure the return value indicates timed out */
    if (retval != SDL_MUTEX_TIMEDOUT)
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_SemWaitTimeout returned: %d; expected: %d\n\n", retval, SDL_MUTEX_TIMEDOUT);

    SDL_DestroySemaphore(sem);
}

static void
TestOverheadUncontended(void)
{
    Uint32 start_ticks;
    Uint32 end_ticks;
    Uint32 duration;
    int i, j;

    sem = SDL_CreateSemaphore(0);
    SDL_Log("Doing %d uncontended Post/Wait operations on semaphore\n", NUM_OVERHEAD_OPS * NUM_OVERHEAD_OPS_MULT);

    start_ticks = SDL_GetTicks();
    for (i = 0; i < NUM_OVERHEAD_OPS_MULT; i++){
        for (j = 0; j < NUM_OVERHEAD_OPS; j++) {
            SDL_SemPost(sem);
        }
        for (j = 0; j < NUM_OVERHEAD_OPS; j++) {
            SDL_SemWait(sem);
        }
    }
    end_ticks = SDL_GetTicks();

    duration = end_ticks - start_ticks;
    SDL_Log("Took %" SDL_PRIu32 " milliseconds\n\n", duration);

    SDL_DestroySemaphore(sem);
}

static int SDLCALL
ThreadFuncOverheadContended(void *data)
{
    Thread_State *state = (Thread_State *) data;

    if (state->flag) {
        while(alive) {
            if (SDL_SemTryWait(sem) == SDL_MUTEX_TIMEDOUT) {
                ++state->content_count;
            }
            ++state->loop_count;
        }
    } else {
        while(alive) {
            /* Timeout needed to allow check on alive flag */
            if (SDL_SemWaitTimeout(sem, 50) == SDL_MUTEX_TIMEDOUT) {
                ++state->content_count;
            }
            ++state->loop_count;
        }
    }
    return 0;
}

static void
TestOverheadContended(SDL_bool try_wait)
{
    Uint32 start_ticks;
    Uint32 end_ticks;
    Uint32 duration;
    Thread_State thread_states[NUM_THREADS] = { {0} };
    char textBuffer[1024];
    int loop_count;
    int content_count;
    int i, j;
    size_t len;

    sem = SDL_CreateSemaphore(0);
    SDL_Log("Doing %d contended %s operations on semaphore using %d threads\n",
            NUM_OVERHEAD_OPS * NUM_OVERHEAD_OPS_MULT, try_wait ? "Post/TryWait" : "Post/WaitTimeout", NUM_THREADS);
    alive = 1;
    /* Create multiple threads to starve the semaphore and cause contention */
    for (i = 0; i < NUM_THREADS; ++i) {
        char name[64];
        SDL_snprintf(name, sizeof (name), "Thread%u", (unsigned int) i);
        thread_states[i].flag = try_wait;
        thread_states[i].thread = SDL_CreateThread(ThreadFuncOverheadContended, name, (void *) &thread_states[i]);
    }

    start_ticks = SDL_GetTicks();
    for (i = 0; i < NUM_OVERHEAD_OPS_MULT; i++) {
        for (j = 0; j < NUM_OVERHEAD_OPS; j++) {
            SDL_SemPost(sem);
        }
        /* Make sure threads consumed everything */
        while (SDL_SemValue(sem)) { }
    }
    end_ticks = SDL_GetTicks();

    alive = 0;
    loop_count = 0;
    content_count = 0;
    for (i = 0; i < NUM_THREADS; ++i) {
        SDL_WaitThread(thread_states[i].thread, NULL);
        loop_count += thread_states[i].loop_count;
        content_count += thread_states[i].content_count;
    }
    SDL_assert_release((loop_count - content_count) == NUM_OVERHEAD_OPS * NUM_OVERHEAD_OPS_MULT);

    duration = end_ticks - start_ticks;
    SDL_Log("Took %" SDL_PRIu32 " milliseconds, threads %s %d out of %d times in total (%.2f%%)\n",
            duration, try_wait ? "where contended" : "timed out", content_count,
            loop_count, ((float) content_count * 100) / loop_count);
    /* Print how many semaphores where consumed per thread */
    SDL_snprintf(textBuffer, sizeof(textBuffer), "{ ");
    for (i = 0; i < NUM_THREADS; ++i) {
        if (i > 0) {
            len = SDL_strlen(textBuffer);
            SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, ", ");
        }
        len = SDL_strlen(textBuffer);
        SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, "%d", thread_states[i].loop_count - thread_states[i].content_count);
    }
    len = SDL_strlen(textBuffer);
    SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, " }\n");
    SDL_Log("%s\n", textBuffer);

    SDL_DestroySemaphore(sem);
}

int
main(int argc, char **argv)
{
    int init_sem;

    /* Enable standard application logging */
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

    if (argc < 2) {
        SDL_Log("Usage: %s init_value\n", argv[0]);
        return (1);
    }

    /* Load the SDL library */
    if (SDL_Init(0) < 0) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
        return (1);
    }
    signal(SIGTERM, killed);
    signal(SIGINT, killed);

    init_sem = SDL_atoi(argv[1]);
    if (init_sem > 0) {
        TestRealWorld(init_sem);
    }

    TestWaitTimeout();

    TestOverheadUncontended();

    TestOverheadContended(SDL_FALSE);

    TestOverheadContended(SDL_TRUE);

    SDL_Quit();
    return (0);
}
