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 20static 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 27static 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 34static int TaskGetNodeHasCode(const HashNode *node) 35{ 36 BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode); 37 return task->taskId.fd; 38} 39 40static int TaskGetKeyHasCode(const void *key) 41{ 42 TaskId *taskId = (TaskId *)key; 43 return taskId->taskId.fd; 44} 45 46static 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 53static 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 80LE_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 92LE_STATUS ProcessEvent(const EventLoop *loop, int fd, uint32_t oper) 93{ 94 BaseTask *task = GetTaskByFd((EventLoop *)loop, fd); 95 if (task != NULL) { 96 task->handleEvent((LoopHandle)loop, (TaskHandle)task, oper); 97 } else { 98 loop->delEvent(loop, fd, EVENT_READ | EVENT_WRITE); 99 } 100 return LE_SUCCESS; 101} 102 103LE_STATUS AddTask(EventLoop *loop, BaseTask *task) 104{ 105 LoopMutexLock(&loop->mutex); 106 int ret = OH_HashMapAdd(loop->taskMap, &task->hashNode); 107 LoopMutexUnlock(&loop->mutex); 108#ifndef STARTUP_INIT_TEST 109 return ret; 110#else 111 ret = 0; 112 return ret; 113#endif 114} 115 116BaseTask *GetTaskByFd(EventLoop *loop, int fd) 117{ 118 BaseTask *task = NULL; 119 LoopMutexLock(&loop->mutex); 120 TaskId id = {0, {fd}}; 121 HashNode *node = OH_HashMapGet(loop->taskMap, &id); 122 if (node != NULL) { 123 task = HASHMAP_ENTRY(node, BaseTask, hashNode); 124 } 125 LoopMutexUnlock(&loop->mutex); 126 return task; 127} 128 129void DelTask(EventLoop *loop, BaseTask *task) 130{ 131 loop->delEvent(loop, task->taskId.fd, 132 EVENT_READ | EVENT_WRITE | EVENT_ERROR | EVENT_FREE | EVENT_TIMEOUT | EVENT_SIGNAL); 133 LoopMutexLock(&loop->mutex); 134 OH_HashMapRemove(loop->taskMap, (TaskId *)task); 135 LoopMutexUnlock(&loop->mutex); 136 return; 137} 138 139static EventLoop *g_defaultLoop = NULL; 140LoopHandle LE_GetDefaultLoop(void) 141{ 142 if (g_defaultLoop == NULL) { 143 LE_CreateLoop((LoopHandle *)&g_defaultLoop); 144 } 145 return (LoopHandle)g_defaultLoop; 146} 147 148LE_STATUS LE_CreateLoop(LoopHandle *handle) 149{ 150 EventLoop *loop = NULL; 151 LE_STATUS ret = CreateLoop_(&loop, LOOP_MAX_SOCKET, DEFAULT_TIMEOUT); 152 *handle = (LoopHandle)loop; 153 return ret; 154} 155 156void LE_RunLoop(const LoopHandle handle) 157{ 158 LE_CHECK(handle != NULL, return, "Invalid handle"); 159 EventLoop *loop = (EventLoop *)handle; 160 loop->runLoop(loop); 161} 162 163void LE_CloseLoop(const LoopHandle loopHandle) 164{ 165 LE_CHECK(loopHandle != NULL, return, "Invalid handle"); 166 CloseLoop((EventLoop *)loopHandle); 167 if ((LoopHandle)g_defaultLoop == loopHandle) { 168 g_defaultLoop = NULL; 169 } 170} 171 172void LE_StopLoop(const LoopHandle handle) 173{ 174 LE_CHECK(handle != NULL, return, "Invalid handle"); 175 EventLoop *loop = (EventLoop *)handle; 176 loop->stop = 1; 177}