1 /* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "command_queue.h"
21 session::command_queue *session::command_queue::interface()
24 #ifdef _MAPS_SERVICE_SUPPORTS_ASYNC_QUEUE_
25 static command_queue_async async_queue;
28 static command_queue_sync sync_queue;
30 #endif /* _MAPS_SERVICE_SUPPORTS_ASYNC_QUEUE_ */
32 static command_queue_sync sync_queue;
37 /*----------------------------------------------------------------------------*/
40 int session::command_queue_sync::push(command *c)
42 return (c and c->plugin())? c->run() : MAPS_ERROR_INVALID_PARAMETER;
45 session::command* session::command_queue_sync::pop(plugin::plugin_s *p)
47 return command::empty_ptr();
50 void session::command_queue_sync::process(plugin::plugin_s *p)
56 void session::command_queue_sync::clear(plugin::plugin_s *p)
61 /*----------------------------------------------------------------------------*/
64 * This is the implementation of asynchronous queue.
65 * In order to pass code coverage tests it is blocked.
67 #ifdef _MAPS_SERVICE_SUPPORTS_ASYNC_QUEUE_
68 int session::command_queue_async::push(command *c)
70 if (!c || !c->plugin() || !c->plugin()->request_queue)
71 return MAPS_ERROR_INVALID_PARAMETER;
73 queue_autoref(c->plugin()->request_queue);
74 g_async_queue_push(c->plugin()->request_queue, c);
76 /* Lazy initialization: run plugin thread if it is not started yet */
77 thread().run(c->plugin());
79 return MAPS_ERROR_NONE;
82 session::command *session::command_queue_async::pop(plugin::plugin_s *p)
84 if (!p || !p->request_queue)
85 return command::empty_ptr();
87 queue_autoref(p->request_queue);
89 /* Pops data from the queue . */
90 /* If the queue is empty, blocks for timeout microseconds, or until data
91 * becomes available. */
92 /* If no data is received before the timeout, NULL is returned. */
93 /* https://developer.gnome.org/glib/stable/glib-Asynchronous-Queues.html#g-async-queue-timeout-pop */
95 (command *) g_async_queue_timeout_pop(p->request_queue,
96 10 * G_TIME_SPAN_MILLISECOND);
97 return (c) ? c : command::empty_ptr();
100 void session::command_queue_async::process(plugin::plugin_s *p)
102 if (not p or not p->request_queue)
105 queue_autoref(p->request_queue);
109 void session::command_queue_async::clear(plugin::plugin_s *p)
111 if (not p or not p->request_queue)
114 queue_autoref(p->request_queue);
115 while (g_async_queue_length(p->request_queue))
120 /*----------------------------------------------------------------------------*/
122 session::command_queue* session::command_queue_view::interface()
124 static command_queue_view view_queue;
128 /*static int __dbg_queue_length = 0;*/
130 gint session::command_queue_view::iterate(gconstpointer a,
134 /*__dbg_queue_length ++;*/
136 /* Extracting command data from params */
137 command *ca = (command *)a;
138 command *cb = (command *)b;
139 command *c_new = (command *)user_data;
141 /* Attempting to update existing command with freshier data.
142 * It is decided not to store a number of commands of the same type:
143 * one command is enough */
145 if (ca->get_type() == c_new->get_type()) {
147 //c_new->set_merged();
148 } else if (cb->get_type() == c_new->get_type()) {
150 //c_new->set_merged();
154 /* Sorting the commands in the que with their prioirties:
155 * the lower priority, the far the command from the queue front
157 * https://developer.gnome.org/glib/stable/
158 * glib-Asynchronous-Queues.html#g-async-queue-sort */
159 const int pa = ca->get_priority();
160 const int pb = cb->get_priority();
161 return (pa < pb ? +1 : pa == pb ? 0 : -1);
164 int session::command_queue_view::push(command *c)
166 /*g_print("session::command_queue_view::push "
167 "pushed a command: %p\n", c);*/
168 if (c == command::empty_ptr())
169 return MAPS_ERROR_NONE;
171 if (!c || !c->plugin() || !c->plugin()->request_queue)
172 return MAPS_ERROR_INVALID_PARAMETER;
175 queue_autoref(c->plugin()->request_queue);
178 /* ---------------------------------------------- */
179 /* This is the routine without queue modification */
180 const bool _dbg_simple_queue = false;
181 if (_dbg_simple_queue) {
182 g_async_queue_push(c->plugin()->request_queue, c);
183 return MAPS_ERROR_NONE;
185 /* ---------------------------------------------- */
188 /* Iterating the queue; sorting it and simultaneously attempting
189 * to update the data of the existing command of the current type.
190 * This approach allows to store only one instance of a command per
192 /*__dbg_queue_length = 0;*/
193 g_async_queue_sort(c->plugin()->request_queue,
194 session::command_queue_view::iterate, c);
195 /*g_print("Queue Length: %d\n", __dbg_queue_length);*/
197 /* If the command was merged, it is not needed any more.
198 * If the command data was not merged to the existing command instance
199 * of the same type, we should:
200 * a. add this command to the queue and
201 * b. sort the queue once again without any attempt to update
204 * https://developer.gnome.org/glib/stable/
205 * glib-Asynchronous-Queues.html#g-async-queue-push-sorted */
209 g_async_queue_push_sorted(c->plugin()->request_queue, c,
210 session::command_queue_view::iterate,
213 return MAPS_ERROR_NONE;
216 session::command* session::command_queue_view::pop(plugin::plugin_s *p)
218 /*g_print("session::command_queue_view::pop\n");*/
219 if (!p || !p->request_queue)
220 return command::empty_ptr();
222 queue_autoref(p->request_queue);
225 * Pops data from the queue.
226 * If the queue is empty, blocks for timeout microseconds, or until data
228 * If no data is received before the timeout, NULL is returned.
229 * https://developer.gnome.org/glib/stable/glib-Asynchronous-Queues.html#g-async-queue-timeout-pop
232 (command*)g_async_queue_timeout_pop(p->request_queue,
233 /*300 * G_TIME_SPAN_MILLISECOND);*/
234 /* Small timeout is better for UI */
235 10 * G_TIME_SPAN_MILLISECOND);
237 g_print("session::command_queue_view::pop "
238 "extracted a command: %p\n", c);*/
239 return (c) ? c : command::empty_ptr();
242 void session::command_queue_view::process(plugin::plugin_s *p)
244 if (!p || !p->request_queue)
247 queue_autoref(p->request_queue);
251 void session::command_queue_view::clear(plugin::plugin_s *p)
253 if (!p || !p->request_queue)
256 queue_autoref(p->request_queue);
257 while (g_async_queue_length(p->request_queue))
261 #endif /* _MAPS_SERVICE_SUPPORTS_ASYNC_QUEUE_ */