1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#include "gate/tests.hpp"
#include "gate/threadpools.hpp"
#include "gate/threading.hpp"
#include "gate/atomics.hpp"

using namespace gate;


class GATE_API_LOCAL ThreadRunnable : public IRunnable
{
public:
    int current_value;
    int future_value;

    ThreadRunnable() : current_value(0), future_value(1) {}

    void run() override
    {
        this->current_value = this->future_value;
    }
};

static ThreadRunnable global_thread_runnable;

static void do_nothing()
{
}

GATEXX_TEST_UNIT(Thread)
{
    Thread::id_t thid = 0;<--- Shadowed declaration
    Thread::handle_t th = Thread::self(&thid);<--- Shadowed declaration<--- Shadowed declaration
    (void)th;
    GATEXX_TEST_CHECK(thid != 0);

    GATEXX_TEST_CHECK_NOTHROW(Thread::yield());
    GATEXX_TEST_CHECK_NOTHROW(Thread::yieldIfPreemptive());

    static Thread::id_t const invalid_thread_id = static_cast<Thread::id_t>(-1);

    {
        Thread th;<--- Shadow variable
        global_thread_runnable.current_value = 0;
        global_thread_runnable.future_value = 42;
        Thread::id_t new_thid = th.start(global_thread_runnable);
        GATEXX_TEST_CHECK_NOT_EQUAL(new_thid, invalid_thread_id);
        GATEXX_TEST_CHECK_OK(th.join());
        GATEXX_TEST_CHECK_EQUAL(global_thread_runnable.current_value, global_thread_runnable.future_value);
    }

    {
        Runnable r = RunnableFunction::create(&do_nothing);
        Thread th;<--- Shadow variable
        Thread::id_t thid = th.start(r);<--- Shadow variable
        GATEXX_TEST_CHECK_NOT_EQUAL(thid, invalid_thread_id);
        th.release();
    }
}

static int dummy = 42;

GATEXX_TEST_UNIT(ThreadStorage)
{
    ThreadStorage ts;
    VoidResult vr = ts.trySet(&dummy);
    GATEXX_TEST_CHECK(!vr.hasError());
    Result<void*> pv = ts.tryGet();
    GATEXX_TEST_CHECK(!pv.hasError());
    GATEXX_TEST_CHECK_EQUAL(pv.value(), &dummy);

    ts.set(NULL);
    void* nptr = ts.get();
    GATEXX_TEST_CHECK_EQUAL(nptr, NULL);
}

static AtomicInt global_shared_state = 0;

static void pool_task_set_state()
{
    global_shared_state.set(1);
}

GATEXX_TEST_UNIT(Threadpool)
{
    ThreadPool pool;
    GATEXX_TEST_CHECK(pool.c_impl() != NULL);
    global_shared_state.set(0);

    GATEXX_TEST_CHECK_EQUAL(pool.getPendingTasksCount(), 0);
    Runnable task = RunnableFunction::create(&pool_task_set_state);
    pool.addTask(task);
    GATEXX_TEST_CHECK_EQUAL(pool.getPendingTasksCount(), 1);
    pool.removeTask(task);
    GATEXX_TEST_CHECK_EQUAL(pool.getPendingTasksCount(), 0);
    pool.addTask(task);
    GATEXX_TEST_CHECK_EQUAL(pool.getPendingTasksCount(), 1);

    pool.start();
    for (int n = 0; n < 1000; ++n)
    {
        if (global_shared_state.get() != 0)
        {
            break;
        }
        Thread::sleep(10);
    }
    pool.stop();
    GATEXX_TEST_CHECK_EQUAL(global_shared_state.get(), 1);
}