1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "c/thread.h"
17#include "cpp/thread.h"
18#include "internal_inc/osal.h"
19#include "dfx/log/ffrt_log_api.h"
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24struct ThreadRes {
25    bool is_joinable;
26    void* result;
27};
28API_ATTRIBUTE((visibility("default")))
29int ffrt_thread_create(ffrt_thread_t* thr, const ffrt_thread_attr_t* attr, void* (*func)(void*), void* arg)
30{
31    if (!thr || !func) {
32        FFRT_LOGE("thr and func should not be empty");
33        return ffrt_error_inval;
34    }
35    if (attr) {
36        FFRT_LOGE("attr should be empty");
37        return ffrt_error;
38    }
39
40    auto p = reinterpret_cast<ThreadRes*>(malloc(sizeof(ThreadRes)));
41    if (p == nullptr) {
42        FFRT_LOGE("p is empty");
43        return ffrt_error_nomem;
44    }
45    p->is_joinable = true;
46    p->result = nullptr;
47    ffrt::submit([p, func, arg]() {
48        p->result = func(arg);
49    }, {}, {p});
50
51    *thr = p;
52    return ffrt_success;
53}
54
55API_ATTRIBUTE((visibility("default")))
56int ffrt_thread_join(ffrt_thread_t thr, void** res)
57{
58    if (!thr || !res) {
59        FFRT_LOGE("thr or res should not be empty");
60        return ffrt_error_inval;
61    }
62
63    auto p = reinterpret_cast<ThreadRes*>(thr);
64    if (p == nullptr || !p->is_joinable) {
65        return ffrt_error_inval;
66    }
67    ffrt::wait({p});
68    *res = p->result;
69    p->is_joinable = false;
70    free(p);
71    return ffrt_success;
72}
73
74API_ATTRIBUTE((visibility("default")))
75int ffrt_thread_detach(ffrt_thread_t thr)
76{
77    if (!thr) {
78        FFRT_LOGE("thr should not be empty");
79        return ffrt_error_inval;
80    }
81    auto p = reinterpret_cast<ThreadRes*>(thr);
82    if (p == nullptr || !p->is_joinable) {
83        return ffrt_error_inval;
84    }
85    p->is_joinable = false;
86    ffrt::submit([thr]() { free(thr); }, {thr});
87    return ffrt_success;
88}
89#ifdef __cplusplus
90}
91#endif
92