1 /*
2 * Copyright (c) 2021 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 "le_loop.h"
17 #include "le_epoll.h"
18
19
TaskNodeCompare(const HashNode * node1,const HashNode * node2)20 static int TaskNodeCompare(const HashNode *node1, const HashNode *node2)
21 {
22 BaseTask *task1 = HASHMAP_ENTRY(node1, BaseTask, hashNode);
23 BaseTask *task2 = HASHMAP_ENTRY(node2, BaseTask, hashNode);
24 return (int)task1->taskId.fd - (int)task2->taskId.fd;
25 }
26
TaskKeyCompare(const HashNode * node,const void * key)27 static int TaskKeyCompare(const HashNode *node, const void *key)
28 {
29 BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
30 TaskId *taskId = (TaskId *)key;
31 return (int)task->taskId.fd - taskId->taskId.fd;
32 }
33
TaskGetNodeHasCode(const HashNode * node)34 static int TaskGetNodeHasCode(const HashNode *node)
35 {
36 BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
37 return task->taskId.fd;
38 }
39
TaskGetKeyHasCode(const void * key)40 static int TaskGetKeyHasCode(const void *key)
41 {
42 TaskId *taskId = (TaskId *)key;
43 return taskId->taskId.fd;
44 }
45
TaskNodeFree(const HashNode * node,void * context)46 static void TaskNodeFree(const HashNode *node, void *context)
47 {
48 BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
49 CloseTask((const LoopHandle)context, task);
50 free(task);
51 }
52
CreateLoop_(EventLoop ** loop,uint32_t maxevents,uint32_t timeout)53 static LE_STATUS CreateLoop_(EventLoop **loop, uint32_t maxevents, uint32_t timeout)
54 {
55 #ifdef LOOP_EVENT_USE_EPOLL
56 LE_STATUS ret = CreateEpollLoop(loop, maxevents, timeout);
57 LE_CHECK(ret == LE_SUCCESS, return ret, "Failed to create epoll loop");
58 #endif
59 (*loop)->maxevents = maxevents;
60 (*loop)->timeout = timeout;
61 (*loop)->stop = 0;
62 LoopMutexInit(&(*loop)->mutex);
63
64 OH_ListInit(&((*loop)->idleList));
65
66 HashInfo info = {
67 TaskNodeCompare,
68 TaskKeyCompare,
69 TaskGetNodeHasCode,
70 TaskGetKeyHasCode,
71 TaskNodeFree,
72 128
73 };
74 ret = OH_HashMapCreate(&(*loop)->taskMap, &info);
75 LE_CHECK(ret == LE_SUCCESS, return ret, "failed to create hash map loop");
76 OH_ListInit(&((*loop)->timerList));
77 return ret;
78 }
79
CloseLoop(EventLoop * loop)80 LE_STATUS CloseLoop(EventLoop *loop)
81 {
82 if (!loop->stop) {
83 return LE_SUCCESS;
84 }
85 OH_HashMapDestory(loop->taskMap, loop);
86 if (loop->close) {
87 loop->close(loop);
88 }
89 return LE_SUCCESS;
90 }
91
ProcessEvent(const EventLoop * loop,int fd,uint32_t oper)92 LE_STATUS ProcessEvent(const EventLoop *loop, int fd, uint32_t oper)
93 {
94 BaseTask *task = GetTaskByFd((EventLoop *)loop, fd);
95 if (task != NULL) {
96 if (oper & EVENT_ERROR) {
97 task->flags |= TASK_FLAGS_INVALID;
98 loop->delEvent(loop, task->taskId.fd, EVENT_READ | EVENT_WRITE);
99 }
100 task->handleEvent((LoopHandle)loop, (TaskHandle)task, oper);
101 } else {
102 loop->delEvent(loop, fd, EVENT_READ | EVENT_WRITE);
103 }
104 return LE_SUCCESS;
105 }
106
AddTask(EventLoop * loop,BaseTask * task)107 LE_STATUS AddTask(EventLoop *loop, BaseTask *task)
108 {
109 LoopMutexLock(&loop->mutex);
110 int ret = OH_HashMapAdd(loop->taskMap, &task->hashNode);
111 LoopMutexUnlock(&loop->mutex);
112 #ifndef STARTUP_INIT_TEST
113 return ret;
114 #else
115 ret = 0;
116 return ret;
117 #endif
118 }
119
GetTaskByFd(EventLoop * loop,int fd)120 BaseTask *GetTaskByFd(EventLoop *loop, int fd)
121 {
122 BaseTask *task = NULL;
123 LoopMutexLock(&loop->mutex);
124 TaskId id = {0, {fd}};
125 HashNode *node = OH_HashMapGet(loop->taskMap, &id);
126 if (node != NULL) {
127 task = HASHMAP_ENTRY(node, BaseTask, hashNode);
128 }
129 LoopMutexUnlock(&loop->mutex);
130 return task;
131 }
132
DelTask(EventLoop * loop,BaseTask * task)133 void DelTask(EventLoop *loop, BaseTask *task)
134 {
135 loop->delEvent(loop, task->taskId.fd,
136 EVENT_READ | EVENT_WRITE | EVENT_ERROR | EVENT_FREE | EVENT_TIMEOUT | EVENT_SIGNAL);
137 LoopMutexLock(&loop->mutex);
138 OH_HashMapRemove(loop->taskMap, (TaskId *)task);
139 LoopMutexUnlock(&loop->mutex);
140 return;
141 }
142
143 static EventLoop *g_defaultLoop = NULL;
LE_GetDefaultLoop(void)144 LoopHandle LE_GetDefaultLoop(void)
145 {
146 if (g_defaultLoop == NULL) {
147 LE_CreateLoop((LoopHandle *)&g_defaultLoop);
148 }
149 return (LoopHandle)g_defaultLoop;
150 }
151
LE_CreateLoop(LoopHandle * handle)152 LE_STATUS LE_CreateLoop(LoopHandle *handle)
153 {
154 EventLoop *loop = NULL;
155 LE_STATUS ret = CreateLoop_(&loop, LOOP_MAX_SOCKET, DEFAULT_TIMEOUT);
156 *handle = (LoopHandle)loop;
157 return ret;
158 }
159
LE_RunLoop(const LoopHandle handle)160 void LE_RunLoop(const LoopHandle handle)
161 {
162 LE_CHECK(handle != NULL, return, "Invalid handle");
163 EventLoop *loop = (EventLoop *)handle;
164 loop->runLoop(loop);
165 }
166
LE_CloseLoop(const LoopHandle loopHandle)167 void LE_CloseLoop(const LoopHandle loopHandle)
168 {
169 LE_CHECK(loopHandle != NULL, return, "Invalid handle");
170 CloseLoop((EventLoop *)loopHandle);
171 if ((LoopHandle)g_defaultLoop == loopHandle) {
172 g_defaultLoop = NULL;
173 }
174 }
175
LE_StopLoop(const LoopHandle handle)176 void LE_StopLoop(const LoopHandle handle)
177 {
178 LE_CHECK(handle != NULL, return, "Invalid handle");
179 EventLoop *loop = (EventLoop *)handle;
180 loop->stop = 1;
181 }