summaryrefslogtreecommitdiff
path: root/components/cplusplus/cpp11/gcc/thread.cpp
blob: 3979da0dc4518e980406221f00a29a47f05cdbeb (plain)
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
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-04-27     flybreak     the first version.
 */

#include "thread"
#include "__utils.h"


#define _RT_NPROCS 0

namespace std
{

    extern "C"
    {
        static void* execute_native_thread_routine(void *p)
        {
            thread::invoker_base* t = static_cast<thread::invoker_base*>(p);
            thread::invoker_base_ptr local;
            local.swap(t->this_ptr); // tranfer the ownership of the invoker into the thread entry

            local->invoke();

            return NULL;
        }
    }

    void thread::start_thread(invoker_base_ptr b)
    {
        auto raw_ptr = b.get();
        // transfer the ownership of the invoker to the new thread
        raw_ptr->this_ptr = std::move(b);
        int err = pthread_create(&_m_thr.__cpp_thread_t, NULL,
                &execute_native_thread_routine, raw_ptr);

        if (err)
        {
            raw_ptr->this_ptr.reset();
            throw_system_error(err, "Failed to create a thread");
        }

    }

    thread::~thread()
    {
        if (joinable()) // when either not joined or not detached
            terminate();
    }

    void thread::join()
    {
        int err = EINVAL;

        if (joinable())
            err = pthread_join(native_handle(), NULL);

        if (err)
        {
            throw_system_error(err, "thread::join failed");
        }

        _m_thr = id();
    }

    void thread::detach()
    {
        int err = EINVAL;

        if (joinable())
            err = pthread_detach(native_handle());
        if (err)
        {
            throw_system_error(err, "thread::detach failed");
        }

        _m_thr = id();
    }

    // TODO: not yet actually implemented.
    // The standard states that the returned value should only be considered a hint.
    unsigned thread::hardware_concurrency() noexcept
    {
        int __n = _RT_NPROCS;
        if (__n < 0)
            __n = 0;
        return __n;
    }
}