2 * Copyright (c) 2005 Massachusetts Institute of Technology
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
27 #ifndef __KHIMAIRA_KMQINTERNAL_H
28 #define __KHIMAIRA_KMQINTERNAL_H
36 #include<khmsgtypes.h>
47 /*! \brief Message reference */
48 typedef struct tag_kmq_message_ref {
49 kmq_message * msg; /*!< Message that we are referring
51 kmq_callback_t recipient; /*!< The recipient of the message */
53 LDCL(struct tag_kmq_message_ref);
59 /*! \brief Message queue
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.
67 typedef struct tag_kmq_queue {
68 kmq_thread_id thread; /*!< The thread id */
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
78 khm_int32 flags; /*!< Flags. Currently, it's just KMQ_QUEUE_FLAG_DELETED */
81 QDCL(kmq_message_ref); /*!< Queue of message references */
84 LDCL(struct tag_kmq_queue);
87 #define KMQ_QUEUE_FLAG_DELETED 0x00000008
88 #define KMQ_QUEUE_FLAG_DETACHING 0x00000010
90 /*! \brief Message subscription
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.
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
102 ::KMQ_RCPTTYPE_HWND */
104 kmq_callback_t cb; /*!< Callback if the subscription is
106 HWND hwnd; /*!< Window handle if the subscription
107 is a windows message type */
110 kmq_queue * queue; /*!< Associated queue */
113 LDCL(struct tag_kmq_msg_subscription);
114 } kmq_msg_subscription;
116 #define KMQ_MSG_SUB_MAGIC 0x3821b58e
118 /*! \brief Callback recipient type
120 The recipient is a callback function */
121 #define KMQ_RCPTTYPE_CB 1
123 /*! \brief Windows recipient type
125 The recipient is a window */
126 #define KMQ_RCPTTYPE_HWND 2
131 /*! \brief A message type
133 typedef struct tag_kmq_msg_type {
134 khm_int32 id; /*!< Identifier for the message
136 kmq_msg_subscription * subs; /*!< The list of subscriptions */
137 kmq_msg_completion_handler completion_handler; /*!< Completion
138 handler for the message type */
140 wchar_t * name; /*!< Name of the message type for
141 named types. Message type names are
142 language independant. */
145 LDCL(struct tag_kmq_msg_type);
148 /*! \brief The maximum number of message types
150 #define KMQ_MSG_TYPE_MAX 255
152 /*! \brief Maximum number of characters in a message type name
154 The count includes the terminating NULL
156 #define KMQ_MAXCCH_TYPE_NAME 256
158 /*! \brief Maximum number of bytes in a message type name
160 Type count includes the terminating NULL
162 #define KMQ_MAXCB_TYPE_NAME (KMQ_MAXCCH_TYPE_NAME * sizeof(wchar_t))
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"
171 extern CRITICAL_SECTION cs_kmq_global;
172 extern kmq_timer kmq_queue_dead_timeout;
173 extern kmq_timer kmq_call_dead_timeout;
175 extern kmq_queue * queues;
178 extern CRITICAL_SECTION cs_kmq_types;
179 extern kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX+1];
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);
194 extern DWORD kmq_tls_queue;
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);
203 extern CRITICAL_SECTION cs_kmq_msg;
204 extern CRITICAL_SECTION cs_kmq_msg_ref;
206 kmq_message * kmqint_get_message(void);
207 void kmqint_put_message(kmq_message *m);
209 void kmqint_init(void);
210 void kmqint_exit(void);
211 void kmqint_attach_this_thread(void);
212 void kmqint_detach_this_thread(void);
214 khm_int32 kmqint_post_message_ex(
220 khm_boolean try_send);
222 int kmqint_call_completion_handler(kmq_msg_completion_handler h,
226 extern kconf_schema schema_kmqconfig[];
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.