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 /*----------------------------------------------------------------------------*/
39 int session::command_queue_sync::push(command *c)
41 return (c and c->plugin())? c->run() : MAPS_ERROR_INVALID_PARAMETER;
44 session::command* session::command_queue_sync::pop(plugin::plugin_s *p)
46 return command::empty_ptr();
49 void session::command_queue_sync::process(plugin::plugin_s *p)
54 void session::command_queue_sync::clear(plugin::plugin_s *p)
59 /*----------------------------------------------------------------------------*/
62 * This is the implementation of asynchronous queue.
63 * In order to pass code coverage tests it is blocked.
65 #ifdef _MAPS_SERVICE_SUPPORTS_ASYNC_QUEUE_
66 int session::command_queue_async::push(command *c)
68 if (!c || !c->plugin() || !c->plugin()->request_queue)
69 return MAPS_ERROR_INVALID_PARAMETER;
71 queue_autoref(c->plugin()->request_queue);
72 g_async_queue_push(c->plugin()->request_queue, c);
74 /* Lazy initialization: run plugin thread if it is not started yet */
75 thread().run(c->plugin());
77 return MAPS_ERROR_NONE;
80 session::command *session::command_queue_async::pop(plugin::plugin_s *p)
82 if (!p || !p->request_queue)
83 return command::empty_ptr();
85 queue_autoref(p->request_queue);
87 /* Pops data from the queue . */
88 /* If the queue is empty, blocks for timeout microseconds, or until data
89 * becomes available. */
90 /* If no data is received before the timeout, NULL is returned. */
91 /* https://developer.gnome.org/glib/stable/glib-Asynchronous-Queues.html#g-async-queue-timeout-pop */
93 (command *) g_async_queue_timeout_pop(p->request_queue,
94 10 * G_TIME_SPAN_MILLISECOND);
95 return (c) ? c : command::empty_ptr();
98 void session::command_queue_async::process(plugin::plugin_s *p)
100 if (not p or not p->request_queue)
103 queue_autoref(p->request_queue);
107 void session::command_queue_async::clear(plugin::plugin_s *p)
109 if (not p or not p->request_queue)
112 queue_autoref(p->request_queue);
113 while (g_async_queue_length(p->request_queue))
118 /*----------------------------------------------------------------------------*/
120 session::command_queue* session::command_queue_view::interface()
122 static command_queue_view view_queue;
126 /*static int __dbg_queue_length = 0;*/
128 gint session::command_queue_view::iterate(gconstpointer a,
132 /*__dbg_queue_length ++;*/
134 /* Extracting command data from params */
135 command *ca = (command *)a;
136 command *cb = (command *)b;
137 command *c_new = (command *)user_data;
139 /* Attempting to update existing command with freshier data.
140 * It is decided not to store a number of commands of the same type:
141 * one command is enough */
143 if (ca->get_type() == c_new->get_type()) {
145 //c_new->set_merged();
146 } else if (cb->get_type() == c_new->get_type()) {
148 //c_new->set_merged();
152 /* Sorting the commands in the que with their prioirties:
153 * the lower priority, the far the command from the queue front
155 * https://developer.gnome.org/glib/stable/
156 * glib-Asynchronous-Queues.html#g-async-queue-sort */
157 const int pa = ca->get_priority();
158 const int pb = cb->get_priority();
159 return (pa < pb ? +1 : pa == pb ? 0 : -1);
162 int session::command_queue_view::push(command *c)
164 /*g_print("session::command_queue_view::push "
165 "pushed a command: %p\n", c);*/
166 if (c == command::empty_ptr())
167 return MAPS_ERROR_NONE;
169 if (!c || !c->plugin() || !c->plugin()->request_queue)
170 return MAPS_ERROR_INVALID_PARAMETER;
173 queue_autoref(c->plugin()->request_queue);
176 /* ---------------------------------------------- */
177 /* This is the routine without queue modification */
178 const bool _dbg_simple_queue = false;
179 if (_dbg_simple_queue) {
180 g_async_queue_push(c->plugin()->request_queue, c);
181 return MAPS_ERROR_NONE;
183 /* ---------------------------------------------- */
186 /* Iterating the queue; sorting it and simultaneously attempting
187 * to update the data of the existing command of the current type.
188 * This approach allows to store only one instance of a command per
190 /*__dbg_queue_length = 0;*/
191 g_async_queue_sort(c->plugin()->request_queue,
192 session::command_queue_view::iterate, c);
193 /*g_print("Queue Length: %d\n", __dbg_queue_length);*/
195 /* If the command was merged, it is not needed any more.
196 * If the command data was not merged to the existing command instance
197 * of the same type, we should:
198 * a. add this command to the queue and
199 * b. sort the queue once again without any attempt to update
202 * https://developer.gnome.org/glib/stable/
203 * glib-Asynchronous-Queues.html#g-async-queue-push-sorted */
207 g_async_queue_push_sorted(c->plugin()->request_queue, c,
208 session::command_queue_view::iterate,
211 return MAPS_ERROR_NONE;
214 session::command* session::command_queue_view::pop(plugin::plugin_s *p)
216 /*g_print("session::command_queue_view::pop\n");*/
217 if (!p || !p->request_queue)
218 return command::empty_ptr();
220 queue_autoref(p->request_queue);
223 * Pops data from the queue.
224 * If the queue is empty, blocks for timeout microseconds, or until data
226 * If no data is received before the timeout, NULL is returned.
227 * https://developer.gnome.org/glib/stable/glib-Asynchronous-Queues.html#g-async-queue-timeout-pop
230 (command*)g_async_queue_timeout_pop(p->request_queue,
231 /*300 * G_TIME_SPAN_MILLISECOND);*/
232 /* Small timeout is better for UI */
233 10 * G_TIME_SPAN_MILLISECOND);
235 g_print("session::command_queue_view::pop "
236 "extracted a command: %p\n", c);*/
237 return (c) ? c : command::empty_ptr();
240 void session::command_queue_view::process(plugin::plugin_s *p)
242 if (!p || !p->request_queue)
245 queue_autoref(p->request_queue);
249 void session::command_queue_view::clear(plugin::plugin_s *p)
251 if (!p || !p->request_queue)
254 queue_autoref(p->request_queue);
255 while (g_async_queue_length(p->request_queue))
259 #endif /* _MAPS_SERVICE_SUPPORTS_ASYNC_QUEUE_ */