Make reindent
[krb5.git] / src / windows / identity / kmq / kmqinternal.h
1 /*
2  * Copyright (c) 2005 Massachusetts Institute of Technology
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 /* $Id$ */
26
27 #ifndef __KHIMAIRA_KMQINTERNAL_H
28 #define __KHIMAIRA_KMQINTERNAL_H
29
30 #define _NIMLIB_
31
32 #include<windows.h>
33 #include<kmq.h>
34 #include<khlist.h>
35 #include<kherror.h>
36 #include<khmsgtypes.h>
37 #include<kconfig.h>
38
39 #define NOEXPORT
40
41 #include<utils.h>
42 #include<strsafe.h>
43
44
45
46
47 /*! \brief Message reference */
48 typedef struct tag_kmq_message_ref {
49     kmq_message * msg;          /*!< Message that we are referring
50                                   to */
51     kmq_callback_t recipient;   /*!< The recipient of the message */
52
53     LDCL(struct tag_kmq_message_ref);
54 } kmq_message_ref;
55
56
57
58
59 /*! \brief Message queue
60
61     Each thread gets its own message queue.  When a message is
62     broadcast to which there is a subscriber in a particular thread, a
63     reference to the message is placed in the message queue of the
64     thread.  The dispatch procedure then dispatches the message as
65     described in the message reference.
66 */
67 typedef struct tag_kmq_queue {
68     kmq_thread_id thread;       /*!< The thread id  */
69
70     CRITICAL_SECTION cs;
71     HANDLE wait_o;
72
73     khm_int32 load;             /*!< Number of messages waiting to be
74                                   processed on this message queue.  */
75     kmq_timer last_post;        /*!< Time the last message was
76                                   received */
77
78     khm_int32 flags;            /*!< Flags.  Currently, it's just KMQ_QUEUE_FLAG_DELETED */
79
80     /*Q*/
81     QDCL(kmq_message_ref);      /*!< Queue of message references  */
82
83     /*Lnode*/
84     LDCL(struct tag_kmq_queue);
85 } kmq_queue;
86
87 #define KMQ_QUEUE_FLAG_DELETED   0x00000008
88 #define KMQ_QUEUE_FLAG_DETACHING 0x00000010
89
90 /*! \brief Message subscription
91
92     A subscription binds a recipient with a message type.  These are
93     specific to a thread. I.e. a subscription that was made in one
94     thread will not receive messages in the context of another thread.
95 */
96 typedef struct tag_kmq_msg_subscription {
97     khm_int32 magic;            /*!< Magic number.  Should always be
98                                   ::KMQ_MSG_SUB_MAGIC */
99     khm_int32 type;             /*!< Type of message */
100     khm_int32 rcpt_type;        /*!< Type of recipient.  One of
101                                   ::KMQ_RCPTTYPE_CB or
102                                   ::KMQ_RCPTTYPE_HWND  */
103     union {
104         kmq_callback_t cb;      /*!< Callback if the subscription is
105                                   of callback type */
106         HWND hwnd;              /*!< Window handle if the subscription
107                                   is a windows message type */
108     } recipient;
109
110     kmq_queue * queue;          /*!< Associated queue */
111
112     /*lnode*/
113     LDCL(struct tag_kmq_msg_subscription);
114 } kmq_msg_subscription;
115
116 #define KMQ_MSG_SUB_MAGIC 0x3821b58e
117
118 /*! \brief Callback recipient type
119
120     The recipient is a callback function */
121 #define KMQ_RCPTTYPE_CB     1
122
123 /*! \brief Windows recipient type
124
125     The recipient is a window */
126 #define KMQ_RCPTTYPE_HWND   2
127
128
129
130
131 /*! \brief A message type
132  */
133 typedef struct tag_kmq_msg_type {
134     khm_int32 id;               /*!< Identifier for the message
135                                   type. */
136     kmq_msg_subscription * subs; /*!< The list of subscriptions */
137     kmq_msg_completion_handler completion_handler; /*!< Completion
138                                   handler for the message type */
139
140     wchar_t * name;             /*!< Name of the message type for
141                                   named types.  Message type names are
142                                   language independant. */
143
144     /*Lnode*/
145     LDCL(struct tag_kmq_msg_type);
146 } kmq_msg_type;
147
148 /*! \brief The maximum number of message types
149  */
150 #define KMQ_MSG_TYPE_MAX 255
151
152 /*! \brief Maximum number of characters in a message type name
153
154     The count includes the terminating NULL
155  */
156 #define KMQ_MAXCCH_TYPE_NAME 256
157
158 /*! \brief Maximum number of bytes in a message type name
159
160     Type count includes the terminating NULL
161  */
162 #define KMQ_MAXCB_TYPE_NAME (KMQ_MAXCCH_TYPE_NAME * sizeof(wchar_t))
163
164
165
166
167 #define KMQ_CONF_SPACE_NAME L"KMQ"
168 #define KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME L"QueueDeadTimeout"
169 #define KMQ_CONF_CALL_DEAD_TIMEOUT_NAME L"CallDeadTimeout"
170
171 extern CRITICAL_SECTION cs_kmq_global;
172 extern kmq_timer kmq_queue_dead_timeout;
173 extern kmq_timer kmq_call_dead_timeout;
174
175 extern kmq_queue * queues;
176
177 /* message type */
178 extern CRITICAL_SECTION cs_kmq_types;
179 extern kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX+1];
180
181 void kmqint_init_msg_types(void);
182 void kmqint_exit_msg_types(void);
183 void kmqint_free_msg_type(int t);
184 void kmqint_msg_type_create(int t);
185 void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s);
186 void kmqint_msg_type_del_sub(kmq_msg_subscription *s);
187 kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd);
188 kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb);
189 khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send);
190 khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler);
191 int kmqint_notify_msg_completion(kmq_message * m);
192
193 /* consumer */
194 extern DWORD kmq_tls_queue;
195
196 void kmqint_post_queue(kmq_queue * q, kmq_message *m);
197 void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send);
198 kmq_queue * kmqint_get_thread_queue(void);
199 void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r);
200 void kmqint_put_message_ref(kmq_message_ref * r);
201
202 /* publisher */
203 extern CRITICAL_SECTION cs_kmq_msg;
204 extern CRITICAL_SECTION cs_kmq_msg_ref;
205
206 kmq_message * kmqint_get_message(void);
207 void kmqint_put_message(kmq_message *m);
208
209 void kmqint_init(void);
210 void kmqint_exit(void);
211 void kmqint_attach_this_thread(void);
212 void kmqint_detach_this_thread(void);
213
214 khm_int32 kmqint_post_message_ex(
215     khm_int32 type,
216     khm_int32 subtype,
217     khm_ui_4 uparam,
218     void * blob,
219     kmq_call * call,
220     khm_boolean try_send);
221
222 int kmqint_call_completion_handler(kmq_msg_completion_handler h,
223                                    kmq_message * m);
224
225 /* global */
226 extern kconf_schema schema_kmqconfig[];
227
228 /* Lock hiearchy :
229
230     cs_kmq_types
231     cs_kmq_msg
232     cs_kmq_msg_ref
233     cs_compl
234     cs_kmq_global
235     kmq_queue::cs
236
237     If you have a level 'x' lock, you can obtain a level 'x+n' lock.
238     You can't obtain a 'x-n' lock if you already have a level 'x' lock.
239     If you don't have any locks, you can obtain any lock.
240  */
241 #endif