1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci
16d9f0492fSopenharmony_ci#include "le_loop.h"
17d9f0492fSopenharmony_ci#include "le_epoll.h"
18d9f0492fSopenharmony_ci
19d9f0492fSopenharmony_ci
20d9f0492fSopenharmony_cistatic int TaskNodeCompare(const HashNode *node1, const HashNode *node2)
21d9f0492fSopenharmony_ci{
22d9f0492fSopenharmony_ci    BaseTask *task1 = HASHMAP_ENTRY(node1, BaseTask, hashNode);
23d9f0492fSopenharmony_ci    BaseTask *task2 = HASHMAP_ENTRY(node2, BaseTask, hashNode);
24d9f0492fSopenharmony_ci    return (int)task1->taskId.fd - (int)task2->taskId.fd;
25d9f0492fSopenharmony_ci}
26d9f0492fSopenharmony_ci
27d9f0492fSopenharmony_cistatic int TaskKeyCompare(const HashNode *node, const void *key)
28d9f0492fSopenharmony_ci{
29d9f0492fSopenharmony_ci    BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
30d9f0492fSopenharmony_ci    TaskId *taskId = (TaskId *)key;
31d9f0492fSopenharmony_ci    return (int)task->taskId.fd - taskId->taskId.fd;
32d9f0492fSopenharmony_ci}
33d9f0492fSopenharmony_ci
34d9f0492fSopenharmony_cistatic int TaskGetNodeHasCode(const HashNode *node)
35d9f0492fSopenharmony_ci{
36d9f0492fSopenharmony_ci    BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
37d9f0492fSopenharmony_ci    return task->taskId.fd;
38d9f0492fSopenharmony_ci}
39d9f0492fSopenharmony_ci
40d9f0492fSopenharmony_cistatic int TaskGetKeyHasCode(const void *key)
41d9f0492fSopenharmony_ci{
42d9f0492fSopenharmony_ci    TaskId *taskId = (TaskId *)key;
43d9f0492fSopenharmony_ci    return taskId->taskId.fd;
44d9f0492fSopenharmony_ci}
45d9f0492fSopenharmony_ci
46d9f0492fSopenharmony_cistatic void TaskNodeFree(const HashNode *node, void *context)
47d9f0492fSopenharmony_ci{
48d9f0492fSopenharmony_ci    BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
49d9f0492fSopenharmony_ci    CloseTask((const LoopHandle)context, task);
50d9f0492fSopenharmony_ci    free(task);
51d9f0492fSopenharmony_ci}
52d9f0492fSopenharmony_ci
53d9f0492fSopenharmony_cistatic LE_STATUS CreateLoop_(EventLoop **loop, uint32_t maxevents, uint32_t timeout)
54d9f0492fSopenharmony_ci{
55d9f0492fSopenharmony_ci#ifdef LOOP_EVENT_USE_EPOLL
56d9f0492fSopenharmony_ci    LE_STATUS ret = CreateEpollLoop(loop, maxevents, timeout);
57d9f0492fSopenharmony_ci    LE_CHECK(ret == LE_SUCCESS, return ret, "Failed to create epoll loop");
58d9f0492fSopenharmony_ci#endif
59d9f0492fSopenharmony_ci    (*loop)->maxevents = maxevents;
60d9f0492fSopenharmony_ci    (*loop)->timeout = timeout;
61d9f0492fSopenharmony_ci    (*loop)->stop = 0;
62d9f0492fSopenharmony_ci    LoopMutexInit(&(*loop)->mutex);
63d9f0492fSopenharmony_ci
64d9f0492fSopenharmony_ci    OH_ListInit(&((*loop)->idleList));
65d9f0492fSopenharmony_ci
66d9f0492fSopenharmony_ci    HashInfo info = {
67d9f0492fSopenharmony_ci        TaskNodeCompare,
68d9f0492fSopenharmony_ci        TaskKeyCompare,
69d9f0492fSopenharmony_ci        TaskGetNodeHasCode,
70d9f0492fSopenharmony_ci        TaskGetKeyHasCode,
71d9f0492fSopenharmony_ci        TaskNodeFree,
72d9f0492fSopenharmony_ci        128
73d9f0492fSopenharmony_ci    };
74d9f0492fSopenharmony_ci    ret = OH_HashMapCreate(&(*loop)->taskMap, &info);
75d9f0492fSopenharmony_ci    LE_CHECK(ret == LE_SUCCESS, return ret, "failed to create hash map loop");
76d9f0492fSopenharmony_ci    OH_ListInit(&((*loop)->timerList));
77d9f0492fSopenharmony_ci    return ret;
78d9f0492fSopenharmony_ci}
79d9f0492fSopenharmony_ci
80d9f0492fSopenharmony_ciLE_STATUS CloseLoop(EventLoop *loop)
81d9f0492fSopenharmony_ci{
82d9f0492fSopenharmony_ci    if (!loop->stop) {
83d9f0492fSopenharmony_ci        return LE_SUCCESS;
84d9f0492fSopenharmony_ci    }
85d9f0492fSopenharmony_ci    OH_HashMapDestory(loop->taskMap, loop);
86d9f0492fSopenharmony_ci    if (loop->close) {
87d9f0492fSopenharmony_ci        loop->close(loop);
88d9f0492fSopenharmony_ci    }
89d9f0492fSopenharmony_ci    return LE_SUCCESS;
90d9f0492fSopenharmony_ci}
91d9f0492fSopenharmony_ci
92d9f0492fSopenharmony_ciLE_STATUS ProcessEvent(const EventLoop *loop, int fd, uint32_t oper)
93d9f0492fSopenharmony_ci{
94d9f0492fSopenharmony_ci    BaseTask *task = GetTaskByFd((EventLoop *)loop, fd);
95d9f0492fSopenharmony_ci    if (task != NULL) {
96d9f0492fSopenharmony_ci        task->handleEvent((LoopHandle)loop, (TaskHandle)task, oper);
97d9f0492fSopenharmony_ci    } else {
98d9f0492fSopenharmony_ci        loop->delEvent(loop, fd, EVENT_READ | EVENT_WRITE);
99d9f0492fSopenharmony_ci    }
100d9f0492fSopenharmony_ci    return LE_SUCCESS;
101d9f0492fSopenharmony_ci}
102d9f0492fSopenharmony_ci
103d9f0492fSopenharmony_ciLE_STATUS AddTask(EventLoop *loop, BaseTask *task)
104d9f0492fSopenharmony_ci{
105d9f0492fSopenharmony_ci    LoopMutexLock(&loop->mutex);
106d9f0492fSopenharmony_ci    int ret = OH_HashMapAdd(loop->taskMap, &task->hashNode);
107d9f0492fSopenharmony_ci    LoopMutexUnlock(&loop->mutex);
108d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST
109d9f0492fSopenharmony_ci    return ret;
110d9f0492fSopenharmony_ci#else
111d9f0492fSopenharmony_ci    ret = 0;
112d9f0492fSopenharmony_ci    return ret;
113d9f0492fSopenharmony_ci#endif
114d9f0492fSopenharmony_ci}
115d9f0492fSopenharmony_ci
116d9f0492fSopenharmony_ciBaseTask *GetTaskByFd(EventLoop *loop, int fd)
117d9f0492fSopenharmony_ci{
118d9f0492fSopenharmony_ci    BaseTask *task = NULL;
119d9f0492fSopenharmony_ci    LoopMutexLock(&loop->mutex);
120d9f0492fSopenharmony_ci    TaskId id = {0, {fd}};
121d9f0492fSopenharmony_ci    HashNode *node = OH_HashMapGet(loop->taskMap, &id);
122d9f0492fSopenharmony_ci    if (node != NULL) {
123d9f0492fSopenharmony_ci        task = HASHMAP_ENTRY(node, BaseTask, hashNode);
124d9f0492fSopenharmony_ci    }
125d9f0492fSopenharmony_ci    LoopMutexUnlock(&loop->mutex);
126d9f0492fSopenharmony_ci    return task;
127d9f0492fSopenharmony_ci}
128d9f0492fSopenharmony_ci
129d9f0492fSopenharmony_civoid DelTask(EventLoop *loop, BaseTask *task)
130d9f0492fSopenharmony_ci{
131d9f0492fSopenharmony_ci    loop->delEvent(loop, task->taskId.fd,
132d9f0492fSopenharmony_ci        EVENT_READ | EVENT_WRITE | EVENT_ERROR | EVENT_FREE | EVENT_TIMEOUT | EVENT_SIGNAL);
133d9f0492fSopenharmony_ci    LoopMutexLock(&loop->mutex);
134d9f0492fSopenharmony_ci    OH_HashMapRemove(loop->taskMap, (TaskId *)task);
135d9f0492fSopenharmony_ci    LoopMutexUnlock(&loop->mutex);
136d9f0492fSopenharmony_ci    return;
137d9f0492fSopenharmony_ci}
138d9f0492fSopenharmony_ci
139d9f0492fSopenharmony_cistatic EventLoop *g_defaultLoop = NULL;
140d9f0492fSopenharmony_ciLoopHandle LE_GetDefaultLoop(void)
141d9f0492fSopenharmony_ci{
142d9f0492fSopenharmony_ci    if (g_defaultLoop == NULL) {
143d9f0492fSopenharmony_ci        LE_CreateLoop((LoopHandle *)&g_defaultLoop);
144d9f0492fSopenharmony_ci    }
145d9f0492fSopenharmony_ci    return (LoopHandle)g_defaultLoop;
146d9f0492fSopenharmony_ci}
147d9f0492fSopenharmony_ci
148d9f0492fSopenharmony_ciLE_STATUS LE_CreateLoop(LoopHandle *handle)
149d9f0492fSopenharmony_ci{
150d9f0492fSopenharmony_ci    EventLoop *loop = NULL;
151d9f0492fSopenharmony_ci    LE_STATUS ret = CreateLoop_(&loop, LOOP_MAX_SOCKET, DEFAULT_TIMEOUT);
152d9f0492fSopenharmony_ci    *handle = (LoopHandle)loop;
153d9f0492fSopenharmony_ci    return ret;
154d9f0492fSopenharmony_ci}
155d9f0492fSopenharmony_ci
156d9f0492fSopenharmony_civoid LE_RunLoop(const LoopHandle handle)
157d9f0492fSopenharmony_ci{
158d9f0492fSopenharmony_ci    LE_CHECK(handle != NULL, return, "Invalid handle");
159d9f0492fSopenharmony_ci    EventLoop *loop = (EventLoop *)handle;
160d9f0492fSopenharmony_ci    loop->runLoop(loop);
161d9f0492fSopenharmony_ci}
162d9f0492fSopenharmony_ci
163d9f0492fSopenharmony_civoid LE_CloseLoop(const LoopHandle loopHandle)
164d9f0492fSopenharmony_ci{
165d9f0492fSopenharmony_ci    LE_CHECK(loopHandle != NULL, return, "Invalid handle");
166d9f0492fSopenharmony_ci    CloseLoop((EventLoop *)loopHandle);
167d9f0492fSopenharmony_ci    if ((LoopHandle)g_defaultLoop == loopHandle) {
168d9f0492fSopenharmony_ci        g_defaultLoop = NULL;
169d9f0492fSopenharmony_ci    }
170d9f0492fSopenharmony_ci}
171d9f0492fSopenharmony_ci
172d9f0492fSopenharmony_civoid LE_StopLoop(const LoopHandle handle)
173d9f0492fSopenharmony_ci{
174d9f0492fSopenharmony_ci    LE_CHECK(handle != NULL, return, "Invalid handle");
175d9f0492fSopenharmony_ci    EventLoop *loop = (EventLoop *)handle;
176d9f0492fSopenharmony_ci    loop->stop = 1;
177d9f0492fSopenharmony_ci}