1 |
/* PEAK Library |
2 |
* |
3 |
* Copyright (c) 2003 |
4 |
* Stephane Thiell <mbuna@bugged.org>. All rights reserved. |
5 |
* |
6 |
* Redistribution and use in source and binary forms, with or without |
7 |
* modification, are permitted provided that the following conditions |
8 |
* are met: |
9 |
* |
10 |
* 1. Redistributions of source code must retain the above copyright |
11 |
* notice, this list of conditions and the following disclaimer. |
12 |
* |
13 |
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
* notice, this list of conditions and the following disclaimer in the |
15 |
* documentation and/or other materials provided with the distribution. |
16 |
* |
17 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
20 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
21 |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
22 |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
23 |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
24 |
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
25 |
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
26 |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
27 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 |
* |
29 |
* $Id: engine_client.h,v 1.2 2005/01/27 16:31:50 mbuna Exp $ |
30 |
*/ |
31 |
#ifndef INCLUDED_PEAK_ENGINE_CLIENT_H_ |
32 |
#define INCLUDED_PEAK_ENGINE_CLIENT_H_ |
33 |
|
34 |
#ifdef HAVE_CONFIG_H |
35 |
#include "config.h" |
36 |
#endif |
37 |
|
38 |
#include "engine.h" |
39 |
#include "spinlock.h" |
40 |
#include "runtime.h" |
41 |
#include <peak/task.h> |
42 |
|
43 |
typedef void (*peak_engine_client_event_process_func)(peak_engine_client c, |
44 |
int event, int info); |
45 |
|
46 |
/* Engine IO client object structure */ |
47 |
struct __peak_engine_client |
48 |
{ |
49 |
PEAK_STRUCT_RT_HEADER; |
50 |
peak_task _task; /* associated task */ |
51 |
peak_engine _engine; /* associated engine */ |
52 |
peak_spinlock_t _lock; |
53 |
int _ident; /* identifier: file descriptor, |
54 |
* signum, etc. |
55 |
*/ |
56 |
/* Optional engine dependent field. |
57 |
*/ |
58 |
#if defined(PEAK_ENGINE_POLL) |
59 |
int _index; |
60 |
#elif defined(PEAK_ENGINE_EPOLL) |
61 |
uint32_t _events; |
62 |
#endif |
63 |
|
64 |
uint16_t _state; /* object state */ |
65 |
uint16_t _sstate; /* saved object state (sorf of |
66 |
* cache) |
67 |
*/ |
68 |
peak_engine_client_event_process_func _ep; /* call out function ptr */ |
69 |
}; |
70 |
|
71 |
/* Bah. :) |
72 |
*/ |
73 |
#define PEAK_STRUCT_ENGINE_CLIENT_HEADER struct __peak_engine_client _c |
74 |
|
75 |
|
76 |
#if defined(__cplusplus) |
77 |
extern "C" { |
78 |
#endif |
79 |
|
80 |
/* Base class engine_client |
81 |
*/ |
82 |
PEAK_CLASS_BASE_DECLARE_VIRTUAL(engine_client); |
83 |
|
84 |
__private_extern__ void _peak_engine_client_configure |
85 |
( |
86 |
peak_engine_client c, |
87 |
int fd, |
88 |
uint32_t state_init, |
89 |
peak_engine_client_event_process_func ep |
90 |
); |
91 |
|
92 |
|
93 |
/* Lock a client to control data structure access. |
94 |
*/ |
95 |
static inline void |
96 |
_peak_engine_client_lock(peak_engine_client c) |
97 |
{ |
98 |
_peak_spinlock_lock(&c->_lock); |
99 |
} |
100 |
|
101 |
/* Unlock a client. |
102 |
*/ |
103 |
static inline void |
104 |
_peak_engine_client_unlock(peak_engine_client c) |
105 |
{ |
106 |
_peak_spinlock_unlock(&c->_lock); |
107 |
} |
108 |
|
109 |
/* Accept was performed. |
110 |
*/ |
111 |
static inline void |
112 |
_peak_engine_client_did_accept(peak_engine_client c) |
113 |
{ |
114 |
_peak_engine_client_lock(c); |
115 |
|
116 |
c->_state |= CS_ACCEPTING; |
117 |
|
118 |
/* When a client's event is currently being handled (probably by ourself, |
119 |
* but it might be another task's thread too), we do nothing as changes |
120 |
* will automagically be commited. Otherwise, we need to edit the client |
121 |
* explicitely. |
122 |
* Summary: |
123 |
* 1. We are processing an event generated by this client... ok, we |
124 |
* don't edit it immediately, as all changes will be commited in |
125 |
* peak_engine_event_postprocess(). |
126 |
* 2. Events of two clients are being processed simultaneously in two |
127 |
* task's threads. Thread of first client do an operation (accept, |
128 |
* read or write) on second client. Probably rare, but we don't edit |
129 |
* it immediately neither. |
130 |
* 3. We are processing an event generated by this client, and are doing |
131 |
* an operation on another "inactive" client (he didn't generate any |
132 |
* event simultaneously)... oh, he needs to know! edit it now. Note that |
133 |
* the other client could have been triggered at the same time for |
134 |
* parallel events but have already finished his processing, then |
135 |
* it won't commit things anymore and we need to edit it explicitely. |
136 |
* |
137 |
* Sure we could ignore this and edit the client every time, however |
138 |
* some event engines like kqueue use a syscall for client's edition... |
139 |
*/ |
140 |
if (c->_engine && !(c->_state & CS_HANDLED)) |
141 |
_peak_engine_edit_client(c->_engine, c); |
142 |
|
143 |
_peak_engine_client_unlock(c); |
144 |
} |
145 |
|
146 |
/* Read was performed. |
147 |
*/ |
148 |
static inline void |
149 |
_peak_engine_client_did_read(peak_engine_client c) |
150 |
{ |
151 |
_peak_engine_client_lock(c); |
152 |
|
153 |
c->_state |= CS_READING; |
154 |
|
155 |
if (c->_engine && !(c->_state & CS_HANDLED)) |
156 |
_peak_engine_edit_client(c->_engine, c); |
157 |
|
158 |
_peak_engine_client_unlock(c); |
159 |
} |
160 |
|
161 |
/* Write was performed. |
162 |
*/ |
163 |
static inline void |
164 |
_peak_engine_client_did_write(peak_engine_client c) |
165 |
{ |
166 |
_peak_engine_client_lock(c); |
167 |
|
168 |
c->_state |= CS_WRITING; |
169 |
|
170 |
if (c->_engine && !(c->_state & CS_HANDLED)) |
171 |
_peak_engine_edit_client(c->_engine, c); |
172 |
|
173 |
_peak_engine_client_unlock(c); |
174 |
} |
175 |
|
176 |
#if defined(__cplusplus) |
177 |
} |
178 |
#endif |
179 |
|
180 |
#endif /* INCLUDED_PEAK_ENGINE_CLIENT_H_ */ |