xref: /f-stack/app/micro_thread/kqueue_proxy.h (revision 35a81399)
1a9643ea8Slogwang 
2a9643ea8Slogwang /**
3a9643ea8Slogwang  * Tencent is pleased to support the open source community by making MSEC available.
4a9643ea8Slogwang  *
5a9643ea8Slogwang  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8a9643ea8Slogwang  * you may not use this file except in compliance with the License. You may
9a9643ea8Slogwang  * obtain a copy of the License at
10a9643ea8Slogwang  *
11a9643ea8Slogwang  *     https://opensource.org/licenses/GPL-2.0
12a9643ea8Slogwang  *
13a9643ea8Slogwang  * Unless required by applicable law or agreed to in writing, software distributed under the
14a9643ea8Slogwang  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15a9643ea8Slogwang  * either express or implied. See the License for the specific language governing permissions
16a9643ea8Slogwang  * and limitations under the License.
17a9643ea8Slogwang  */
18a9643ea8Slogwang 
19a9643ea8Slogwang 
20a9643ea8Slogwang /**
21a9643ea8Slogwang  *  @filename kqueue.h
22a9643ea8Slogwang  *  @info     kqueue for micro thread manage
23a9643ea8Slogwang  */
24a9643ea8Slogwang 
25a9643ea8Slogwang #ifndef _KQUEUE_PROXY___
26a9643ea8Slogwang #define _KQUEUE_PROXY___
27a9643ea8Slogwang 
28a9643ea8Slogwang #include <stdlib.h>
29a9643ea8Slogwang #include <unistd.h>
30a9643ea8Slogwang #include <sys/queue.h>
31a9643ea8Slogwang 
32a9643ea8Slogwang #include "ff_api.h"
33a9643ea8Slogwang 
34a9643ea8Slogwang #include <set>
35a9643ea8Slogwang #include <vector>
36a9643ea8Slogwang using std::set;
37a9643ea8Slogwang using std::vector;
38a9643ea8Slogwang 
39a9643ea8Slogwang #define kqueue_assert(statement)
40a9643ea8Slogwang //#define kqueue_assert(statement) assert(statement)
41a9643ea8Slogwang 
42a9643ea8Slogwang namespace NS_MICRO_THREAD {
43a9643ea8Slogwang 
44a9643ea8Slogwang #define KQ_EVENT_NONE 0
45a9643ea8Slogwang #define KQ_EVENT_READ 1
46a9643ea8Slogwang #define KQ_EVENT_WRITE 2
47a9643ea8Slogwang 
48a9643ea8Slogwang /**
49a9643ea8Slogwang  * @brief add more detail for linux <sys/queue.h>, freebsd and University of California
50a9643ea8Slogwang  * @info  queue.h version 8.3 (suse)  diff version 8.5 (tlinux)
51a9643ea8Slogwang  */
52a9643ea8Slogwang #ifndef TAILQ_CONCAT
53a9643ea8Slogwang 
54a9643ea8Slogwang #define TAILQ_EMPTY(head)   ((head)->tqh_first == NULL)
55a9643ea8Slogwang #define TAILQ_FIRST(head)   ((head)->tqh_first)
56a9643ea8Slogwang #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
57a9643ea8Slogwang 
58a9643ea8Slogwang #define TAILQ_LAST(head, headname) \
59a9643ea8Slogwang         (*(((struct headname *)((head)->tqh_last))->tqh_last))
60a9643ea8Slogwang 
61a9643ea8Slogwang #define TAILQ_FOREACH(var, head, field)                                     \
62a9643ea8Slogwang         for ((var) = TAILQ_FIRST((head));                                   \
63a9643ea8Slogwang              (var);                                                         \
64a9643ea8Slogwang              (var) = TAILQ_NEXT((var), field))
65a9643ea8Slogwang 
66a9643ea8Slogwang #define TAILQ_CONCAT(head1, head2, field)                                   \
67a9643ea8Slogwang do {                                                                        \
68a9643ea8Slogwang     if (!TAILQ_EMPTY(head2)) {                                              \
69a9643ea8Slogwang         *(head1)->tqh_last = (head2)->tqh_first;                            \
70a9643ea8Slogwang         (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;             \
71a9643ea8Slogwang         (head1)->tqh_last = (head2)->tqh_last;                              \
72a9643ea8Slogwang         TAILQ_INIT((head2));                                                \
73a9643ea8Slogwang     }                                                                       \
74a9643ea8Slogwang } while (0)
75a9643ea8Slogwang 
76a9643ea8Slogwang #endif
77a9643ea8Slogwang 
78a9643ea8Slogwang #ifndef TAILQ_FOREACH_SAFE      // tlinux no this define
79a9643ea8Slogwang #define TAILQ_FOREACH_SAFE(var, head, field, tvar)                          \
80a9643ea8Slogwang         for ((var) = TAILQ_FIRST((head));                                   \
81a9643ea8Slogwang              (var) && ((tvar) = TAILQ_NEXT((var), field), 1);               \
82a9643ea8Slogwang              (var) = (tvar))
83a9643ea8Slogwang #endif
84a9643ea8Slogwang 
85a9643ea8Slogwang 
86a9643ea8Slogwang 
87a9643ea8Slogwang 
88a9643ea8Slogwang /******************************************************************************/
89*35a81399Slogwang /*  Kqueue proxy definition and implementation                                */
90a9643ea8Slogwang /******************************************************************************/
91a9643ea8Slogwang 
92a9643ea8Slogwang class KqueueProxy;
93a9643ea8Slogwang class MicroThread;
94a9643ea8Slogwang 
95a9643ea8Slogwang class KqueuerObj
96a9643ea8Slogwang {
97a9643ea8Slogwang     protected:
98a9643ea8Slogwang         int _fd;
99a9643ea8Slogwang         int _events;
100a9643ea8Slogwang         int _revents;
101a9643ea8Slogwang         int _type;
102a9643ea8Slogwang         MicroThread* _thread;
103a9643ea8Slogwang 
104a9643ea8Slogwang     public:
105a9643ea8Slogwang 
106a9643ea8Slogwang         TAILQ_ENTRY(KqueuerObj) _entry;
107a9643ea8Slogwang 
108a9643ea8Slogwang         explicit KqueuerObj(int fd = -1) {
109a9643ea8Slogwang             _fd       = fd;
110a9643ea8Slogwang             _events   = 0;
111a9643ea8Slogwang             _revents  = 0;
112a9643ea8Slogwang             _type     = 0;
113a9643ea8Slogwang             _thread   = NULL;
114a9643ea8Slogwang         };
~KqueuerObj()115a9643ea8Slogwang         virtual ~KqueuerObj(){};
116a9643ea8Slogwang 
117a9643ea8Slogwang         virtual int InputNotify();
118a9643ea8Slogwang         virtual int OutputNotify();
119a9643ea8Slogwang         virtual int HangupNotify();
120a9643ea8Slogwang         virtual int KqueueCtlAdd(void* args);
121a9643ea8Slogwang         virtual int KqueueCtlDel(void* args);
122a9643ea8Slogwang 
EnableInput()123a9643ea8Slogwang         void EnableInput() {    _events |= KQ_EVENT_READ; };
124a9643ea8Slogwang 
EnableOutput()125a9643ea8Slogwang         void EnableOutput() {     _events |= KQ_EVENT_WRITE; };
126a9643ea8Slogwang 
DisableInput()127a9643ea8Slogwang         void DisableInput() {   _events &= ~KQ_EVENT_READ; };
128a9643ea8Slogwang 
DisableOutput()129a9643ea8Slogwang         void DisableOutput() {    _events &= ~KQ_EVENT_WRITE; };
130a9643ea8Slogwang 
GetOsfd()131a9643ea8Slogwang         int GetOsfd() { return _fd; };
SetOsfd(int fd)132a9643ea8Slogwang         void SetOsfd(int fd) {   _fd = fd; };
133a9643ea8Slogwang 
GetEvents()134a9643ea8Slogwang         int GetEvents() { return _events; };
SetRcvEvents(int revents)135a9643ea8Slogwang         void SetRcvEvents(int revents) { _revents = revents; };
GetRcvEvents()136a9643ea8Slogwang         int GetRcvEvents() { return _revents; };
137a9643ea8Slogwang 
GetNtfyType()138a9643ea8Slogwang         int GetNtfyType() {    return _type; };
Reset()139a9643ea8Slogwang         virtual void Reset() {
140a9643ea8Slogwang             _fd      = -1;
141a9643ea8Slogwang             _events  = 0;
142a9643ea8Slogwang             _revents = 0;
143a9643ea8Slogwang             _type    = 0;
144a9643ea8Slogwang             _thread  = NULL;
145a9643ea8Slogwang         };
146a9643ea8Slogwang 
SetOwnerThread(MicroThread * thread)147a9643ea8Slogwang         void SetOwnerThread(MicroThread* thread) {      _thread = thread; };
GetOwnerThread()148a9643ea8Slogwang         MicroThread* GetOwnerThread() {        return _thread; };
149a9643ea8Slogwang 
150a9643ea8Slogwang };
151a9643ea8Slogwang 
152*35a81399Slogwang typedef TAILQ_HEAD(__KqFdList, KqueuerObj) KqObjList;
153*35a81399Slogwang typedef struct kevent KqEvent;
154a9643ea8Slogwang 
155a9643ea8Slogwang 
156a9643ea8Slogwang class KqFdRef
157a9643ea8Slogwang {
158a9643ea8Slogwang private:
159*35a81399Slogwang     int _wr_ref;
160*35a81399Slogwang     int _rd_ref;
161*35a81399Slogwang     int _events;
162*35a81399Slogwang     int _revents;
163*35a81399Slogwang     KqueuerObj* _kqobj;
164a9643ea8Slogwang 
165a9643ea8Slogwang public:
166a9643ea8Slogwang 
KqFdRef()167a9643ea8Slogwang     KqFdRef() {
168a9643ea8Slogwang         _wr_ref  = 0;
169a9643ea8Slogwang         _rd_ref  = 0;
170a9643ea8Slogwang         _events  = 0;
171a9643ea8Slogwang         _revents = 0;
172a9643ea8Slogwang         _kqobj   = NULL;
173a9643ea8Slogwang     };
~KqFdRef()174a9643ea8Slogwang     ~KqFdRef(){};
175a9643ea8Slogwang 
SetListenEvents(int events)176a9643ea8Slogwang     void SetListenEvents(int events) {
177a9643ea8Slogwang         _events = events;
178a9643ea8Slogwang     };
GetListenEvents()179a9643ea8Slogwang     int GetListenEvents() {
180a9643ea8Slogwang         return _events;
181a9643ea8Slogwang     };
182a9643ea8Slogwang 
SetNotifyObj(KqueuerObj * ntfy)183a9643ea8Slogwang     void SetNotifyObj(KqueuerObj* ntfy) {
184a9643ea8Slogwang         _kqobj = ntfy;
185a9643ea8Slogwang     };
GetNotifyObj()186a9643ea8Slogwang     KqueuerObj* GetNotifyObj() {
187a9643ea8Slogwang         return _kqobj;
188a9643ea8Slogwang     };
189a9643ea8Slogwang 
AttachEvents(int event)190a9643ea8Slogwang     void AttachEvents(int event) {
191a9643ea8Slogwang         if (event & KQ_EVENT_READ) {
192a9643ea8Slogwang             _rd_ref++;
193a9643ea8Slogwang         }
194a9643ea8Slogwang         if (event & KQ_EVENT_WRITE){
195a9643ea8Slogwang             _wr_ref++;
196a9643ea8Slogwang         }
197a9643ea8Slogwang     };
DetachEvents(int event)198a9643ea8Slogwang     void DetachEvents(int event) {
199a9643ea8Slogwang         if (event & KQ_EVENT_READ) {
200a9643ea8Slogwang             if (_rd_ref > 0) {
201a9643ea8Slogwang                 _rd_ref--;
202a9643ea8Slogwang             } else {
203a9643ea8Slogwang                 _rd_ref = 0;
204a9643ea8Slogwang             }
205a9643ea8Slogwang         }
206a9643ea8Slogwang         if (event & KQ_EVENT_WRITE){
207a9643ea8Slogwang             if (_wr_ref > 0) {
208a9643ea8Slogwang                 _wr_ref--;
209a9643ea8Slogwang             } else {
210a9643ea8Slogwang                 _wr_ref = 0;
211a9643ea8Slogwang             }
212a9643ea8Slogwang         }
213a9643ea8Slogwang     };
214a9643ea8Slogwang 
215*35a81399Slogwang 
ReadRefCnt()216a9643ea8Slogwang     int ReadRefCnt() { return _rd_ref; };
WriteRefCnt()217a9643ea8Slogwang     int WriteRefCnt() { return _wr_ref; };
218a9643ea8Slogwang 
219a9643ea8Slogwang };
220a9643ea8Slogwang 
221a9643ea8Slogwang 
222a9643ea8Slogwang class KqueueProxy
223a9643ea8Slogwang {
224a9643ea8Slogwang     public:
225a9643ea8Slogwang         static const int DEFAULT_MAX_FD_NUM = 100000;
226a9643ea8Slogwang 
227a9643ea8Slogwang     private:
228a9643ea8Slogwang         int                       _kqfd;
229a9643ea8Slogwang         int                       _maxfd;
230a9643ea8Slogwang         KqEvent*                  _evtlist;
231a9643ea8Slogwang         KqFdRef*                  _kqrefs;
232a9643ea8Slogwang 
233a9643ea8Slogwang     public:
234a9643ea8Slogwang         KqueueProxy();
~KqueueProxy()235a9643ea8Slogwang         virtual ~KqueueProxy(){};
236a9643ea8Slogwang 
237a9643ea8Slogwang         int InitKqueue(int max_num);
238a9643ea8Slogwang         void TermKqueue(void);
239a9643ea8Slogwang 
KqueueGetTimeout(void)240a9643ea8Slogwang         virtual int KqueueGetTimeout(void) { return 0; };
KqueueSchedule(KqObjList * fdlist,KqueuerObj * fd,int timeout)241a9643ea8Slogwang         virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout) { return false; };
242a9643ea8Slogwang 
243a9643ea8Slogwang         bool KqueueAdd(KqObjList& fdset);
244a9643ea8Slogwang         bool KqueueDel(KqObjList& fdset);
245a9643ea8Slogwang         void KqueueDispatch(void);
246a9643ea8Slogwang         bool KqueueAddObj(KqueuerObj* obj);
247a9643ea8Slogwang         bool KqueueDelObj(KqueuerObj* obj);
248a9643ea8Slogwang         bool KqueueCtrlAdd(int fd, int new_events);
249a9643ea8Slogwang         bool KqueueCtrlDel(int fd, int new_events);
250a9643ea8Slogwang         bool KqueueCtrlDelRef(int fd, int new_events, bool use_ref);
251a9643ea8Slogwang 
KqFdRefGet(int fd)252a9643ea8Slogwang         KqFdRef* KqFdRefGet(int fd) {
253a9643ea8Slogwang             return ((fd >= _maxfd) || (fd < 0)) ? (KqFdRef*)NULL : &_kqrefs[fd];
254a9643ea8Slogwang         }
255a9643ea8Slogwang 
KqueueNtfyReg(int fd,KqueuerObj * obj)256a9643ea8Slogwang         void KqueueNtfyReg(int fd, KqueuerObj* obj) {
257a9643ea8Slogwang             KqFdRef* ref = KqFdRefGet(fd);
258a9643ea8Slogwang             if (ref) {
259a9643ea8Slogwang                 ref->SetNotifyObj(obj);
260a9643ea8Slogwang             }
261a9643ea8Slogwang         };
262a9643ea8Slogwang 
263a9643ea8Slogwang     protected:
264a9643ea8Slogwang         void KqueueRcvEventList(int evtfdnum);
265a9643ea8Slogwang };
266a9643ea8Slogwang 
267a9643ea8Slogwang }
268a9643ea8Slogwang 
269a9643ea8Slogwang 
270a9643ea8Slogwang #endif
271