• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)46 static void TaskNodeFree(const HashNode *node)
47 {
48     BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode);
49     CloseTask(LE_GetDefaultLoop(), task);
50 }
51 
CreateLoop_(EventLoop ** loop,uint32_t maxevents,uint32_t timeout)52 static LE_STATUS CreateLoop_(EventLoop **loop, uint32_t maxevents, uint32_t timeout)
53 {
54 #ifdef LOOP_EVENT_USE_EPOLL
55     LE_STATUS ret = CreateEpollLoop(loop, maxevents, timeout);
56     LE_CHECK(ret == LE_SUCCESS, return ret, "Failed to create epoll loop");
57 #endif
58     (*loop)->maxevents = maxevents;
59     (*loop)->timeout = timeout;
60     (*loop)->stop = 0;
61     LoopMutexInit(&(*loop)->mutex);
62 
63     HashInfo info = {
64         TaskNodeCompare,
65         TaskKeyCompare,
66         TaskGetNodeHasCode,
67         TaskGetKeyHasCode,
68         TaskNodeFree,
69         128
70     };
71     return HashMapCreate(&(*loop)->taskMap, &info);
72 }
73 
CloseLoop(EventLoop * loop)74 LE_STATUS CloseLoop(EventLoop *loop)
75 {
76     if (!loop->stop) {
77         return LE_SUCCESS;
78     }
79     HashMapDestory(loop->taskMap);
80     if (loop->close) {
81         loop->close(loop);
82     }
83     return LE_SUCCESS;
84 }
85 
ProcessEvent(const EventLoop * loop,int fd,uint32_t oper)86 LE_STATUS ProcessEvent(const EventLoop *loop, int fd, uint32_t oper)
87 {
88     BaseTask *task = GetTaskByFd((EventLoop *)loop, fd);
89     if (task != NULL) {
90         task->handleEvent((LoopHandle)loop, (TaskHandle)task, oper);
91     } else {
92         LE_LOGE("ProcessEvent can not find task for %d", fd);
93         loop->delEvent(loop, fd, oper);
94     }
95     return LE_SUCCESS;
96 }
97 
AddTask(EventLoop * loop,BaseTask * task)98 LE_STATUS AddTask(EventLoop *loop, BaseTask *task)
99 {
100     LoopMutexLock(&loop->mutex);
101     HashMapAdd(loop->taskMap, &task->hashNode);
102     LoopMutexUnlock(&loop->mutex);
103     return LE_SUCCESS;
104 }
105 
GetTaskByFd(EventLoop * loop,int fd)106 BaseTask *GetTaskByFd(EventLoop *loop, int fd)
107 {
108     BaseTask *task = NULL;
109     LoopMutexLock(&loop->mutex);
110     TaskId id = {0, {fd}};
111     HashNode *node = HashMapGet(loop->taskMap, &id);
112     if (node != NULL) {
113         task = HASHMAP_ENTRY(node, BaseTask, hashNode);
114     }
115     LoopMutexUnlock(&loop->mutex);
116     return task;
117 }
118 
DelTask(EventLoop * loop,BaseTask * task)119 void DelTask(EventLoop *loop, BaseTask *task)
120 {
121     loop->delEvent(loop, task->taskId.fd,
122         Event_Read | Event_Write | Event_Error | Event_Free | Event_Timeout | Event_Signal);
123     LoopMutexLock(&loop->mutex);
124     HashMapRemove(loop->taskMap, (TaskId *)task);
125     LoopMutexUnlock(&loop->mutex);
126     return;
127 }
128 
129 static EventLoop *g_defaultLoop = NULL;
LE_GetDefaultLoop(void)130 LoopHandle LE_GetDefaultLoop(void)
131 {
132     if (g_defaultLoop == NULL) {
133         LE_CreateLoop((LoopHandle *)&g_defaultLoop);
134     }
135     return (LoopHandle)g_defaultLoop;
136 }
137 
LE_CreateLoop(LoopHandle * handlle)138 LE_STATUS LE_CreateLoop(LoopHandle *handlle)
139 {
140     EventLoop *loop = NULL;
141     LE_STATUS ret = CreateLoop_(&loop, LOOP_MAX_SOCKET, DEFAULT_TIMEOUT);
142     *handlle = (LoopHandle)loop;
143     return ret;
144 }
145 
LE_RunLoop(const LoopHandle handle)146 void LE_RunLoop(const LoopHandle handle)
147 {
148     LE_CHECK(handle != NULL, return, "Invalid handle");
149     EventLoop *loop = (EventLoop *)handle;
150     loop->runLoop(loop);
151 }
152 
LE_StopLoop(const LoopHandle handle)153 void LE_StopLoop(const LoopHandle handle)
154 {
155     LE_CHECK(handle != NULL, return, "Invalid handle");
156     EventLoop *loop = (EventLoop *)handle;
157     loop->stop = 1;
158 }