File Coverage

third_party/modest/source/modest/finder/thread.c
Criterion Covered Total %
statement 0 213 0.0
branch 0 116 0.0
condition n/a
subroutine n/a
pod n/a
total 0 329 0.0


line stmt bran cond sub pod time code
1             /*
2             Copyright (C) 2016-2017 Alexander Borisov
3            
4             This library is free software; you can redistribute it and/or
5             modify it under the terms of the GNU Lesser General Public
6             License as published by the Free Software Foundation; either
7             version 2.1 of the License, or (at your option) any later version.
8            
9             This library is distributed in the hope that it will be useful,
10             but WITHOUT ANY WARRANTY; without even the implied warranty of
11             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12             Lesser General Public License for more details.
13            
14             You should have received a copy of the GNU Lesser General Public
15             License along with this library; if not, write to the Free Software
16             Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17            
18             Author: lex.borisov@gmail.com (Alexander Borisov)
19             */
20              
21             #include "modest/finder/thread.h"
22              
23             /* private functions */
24             #ifndef MyCORE_BUILD_WITHOUT_THREADS
25             static void modest_finder_thread_stream(mythread_id_t thread_id, void* arg);
26             #else
27             static void modest_finder_thread_stream_single(modest_finder_thread_t* finder_thread, mycss_selectors_list_t* selector_list);
28             #endif
29              
30             static modest_finder_thread_context_t * modest_finder_thread_create_context(modest_finder_thread_t* finder_thread, size_t count);
31             //static void modest_finder_thread_callback_found(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_list_t* selector_list,
32             // mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec, void* ctx);
33              
34             /* basic functions */
35 0           modest_finder_thread_t * modest_finder_thread_create(void)
36             {
37 0           return (modest_finder_thread_t*)mycore_calloc(1, sizeof(modest_finder_thread_t));
38             }
39              
40 0           mystatus_t modest_finder_thread_init(modest_finder_t* finder, modest_finder_thread_t* finder_thread, size_t thread_count)
41             {
42             #ifdef MyCORE_BUILD_WITHOUT_THREADS
43             thread_count = 1;
44             #endif
45            
46 0           finder_thread->finder = finder;
47            
48             /* objects for nodes */
49 0           finder_thread->entry_obj = mcobject_async_create();
50 0 0         if(finder_thread->entry_obj == NULL)
51 0           return MODEST_STATUS_OK;
52            
53 0           mcobject_async_status_t mcstatus = mcobject_async_init(finder_thread->entry_obj, 128, 1024, sizeof(modest_finder_thread_entry_t));
54 0 0         if(mcstatus)
55 0           return MODEST_STATUS_OK;
56            
57             /* objects for declarations */
58 0           finder_thread->declaration_obj = mcobject_async_create();
59 0 0         if(finder_thread->declaration_obj == NULL)
60 0           return MODEST_STATUS_OK;
61            
62 0           mcstatus = mcobject_async_init(finder_thread->declaration_obj, 128, 1024, sizeof(modest_finder_thread_declaration_t));
63 0 0         if(mcstatus)
64 0           return MODEST_STATUS_OK;
65            
66 0           finder_thread->context_list = modest_finder_thread_create_context(finder_thread, thread_count);
67 0 0         if(finder_thread->context_list == NULL)
68 0           return MODEST_STATUS_OK;
69            
70             /* create and init threads */
71             #ifdef MyCORE_BUILD_WITHOUT_THREADS
72             finder_thread->thread = NULL;
73             #else
74 0           finder_thread->thread = mythread_create();
75            
76 0 0         if(finder_thread->thread == NULL)
77 0           return MODEST_STATUS_OK;
78            
79 0           mystatus_t status = mythread_init(finder_thread->thread, MyTHREAD_TYPE_STREAM, thread_count, 0);
80 0 0         if(status) {
81 0           mythread_destroy(finder_thread->thread, NULL, NULL, true);
82 0           return MODEST_STATUS_OK;
83             }
84            
85 0           finder_thread->thread->context = finder_thread;
86            
87             /* create threads */
88 0 0         for(size_t i = 0; i < finder_thread->thread->entries_size; i++) {
89 0           myhread_entry_create(finder_thread->thread, mythread_function, modest_finder_thread_stream, MyTHREAD_OPT_STOP);
90             }
91             #endif
92            
93 0           return MODEST_STATUS_OK;
94             }
95              
96 0           void modest_finder_thread_clean(modest_finder_thread_t* finder_thread, bool self_destroy)
97             {
98 0 0         for(size_t i = 1; i < finder_thread->context_list_size; i++) {
99 0           mcobject_async_node_clean(finder_thread->entry_obj, finder_thread->context_list[i].entry_node_id);
100 0           mcobject_async_node_clean(finder_thread->declaration_obj, finder_thread->context_list[i].declaration_node_id);
101             }
102 0           }
103              
104 0           modest_finder_thread_t * modest_finder_thread_destroy(modest_finder_thread_t* finder_thread, bool self_destroy)
105             {
106 0 0         if(finder_thread == NULL)
107 0           return NULL;
108            
109             #ifndef MyCORE_BUILD_WITHOUT_THREADS
110 0 0         if(finder_thread->thread) {
111 0           finder_thread->thread = mythread_destroy(finder_thread->thread, mythread_callback_quit, NULL, true);
112             }
113             #endif
114            
115 0           finder_thread->entry_obj = mcobject_async_destroy(finder_thread->entry_obj, true);
116 0           finder_thread->declaration_obj = mcobject_async_destroy(finder_thread->declaration_obj, true);
117            
118 0 0         if(finder_thread->context_list) {
119 0           mycore_free(finder_thread->context_list);
120            
121 0           finder_thread->context_list = NULL;
122 0           finder_thread->context_list_size = 0;
123             }
124            
125 0 0         if(self_destroy) {
126 0           mycore_free(finder_thread);
127 0           return NULL;
128             }
129            
130 0           return finder_thread;
131             }
132              
133 0           void modest_finder_thread_collate_node(modest_t* modest, myhtml_tree_node_t* node, modest_finder_thread_entry_t* entry)
134             {
135 0           modest_finder_thread_declaration_t* dec = entry->declaration;
136            
137 0 0         while(dec) {
138 0 0         if(dec->entry)
139 0           modest_style_map_collate_declaration(modest, node, dec->entry, dec->entry->type, &dec->raw_spec);
140            
141 0           dec = dec->next;
142             }
143 0           }
144              
145             #ifdef MyCORE_BUILD_WITHOUT_THREADS
146             mystatus_t modest_finder_thread_process(modest_t* modest, modest_finder_thread_t* finder_thread,
147             myhtml_tree_node_t* scope_node, mycss_selectors_list_t* selector_list)
148             {
149             finder_thread->base_node = scope_node;
150             finder_thread->selector_list = selector_list;
151            
152             if(finder_thread->finder == NULL)
153             return MODEST_STATUS_ERROR;
154            
155             modest_finder_thread_stream_single(finder_thread, selector_list);
156            
157             /* calc result */
158             modest_finder_thread_context_t* context = finder_thread->context_list;
159             myhtml_tree_node_t* node = scope_node;
160            
161             /* compare results */
162             while(node) {
163             modest_finder_thread_entry_t* entry = context->entry;
164            
165             while(entry) {
166             if(entry->node == node)
167             {
168             if(entry->next)
169             entry->next->prev = entry->prev;
170             else
171             context->entry_last = entry->prev;
172            
173             if(entry->prev)
174             entry->prev->next = entry->next;
175             else
176             context->entry = entry->next;
177            
178             modest_finder_thread_collate_node(modest, node, entry);
179             }
180            
181             entry = entry->next;
182             }
183            
184             if(node->child)
185             node = node->child;
186             else {
187             while(node != scope_node && node->next == NULL)
188             node = node->parent;
189            
190             if(node == scope_node)
191             break;
192            
193             node = node->next;
194             }
195             }
196            
197             return MyCORE_STATUS_OK;
198             }
199              
200             #else /* end def MyCORE_BUILD_WITHOUT_THREADS */
201 0           mystatus_t modest_finder_thread_process(modest_t* modest, modest_finder_thread_t* finder_thread,
202             myhtml_tree_node_t* scope_node, mycss_selectors_list_t* selector_list)
203             {
204 0           finder_thread->base_node = scope_node;
205 0           finder_thread->selector_list = selector_list;
206            
207 0 0         if(finder_thread->finder == NULL)
208 0           return MODEST_STATUS_ERROR;
209            
210 0           mythread_resume(finder_thread->thread, MyTHREAD_OPT_UNDEF);
211 0           modest_finder_thread_wait_for_all_done(finder_thread);
212            
213             /* calc result */
214 0           modest_finder_thread_context_t* context_list = finder_thread->context_list;
215 0           myhtml_tree_node_t* node = scope_node;
216            
217             /* compare results */
218 0 0         while(node) {
219 0 0         for(size_t i = 0; i < finder_thread->thread->entries_length; i++)
220             {
221 0           modest_finder_thread_context_t* context = &context_list[i];
222 0           modest_finder_thread_entry_t* entry = context->entry;
223            
224 0 0         while(entry) {
225 0 0         if(entry->node == node)
226             {
227 0 0         if(entry->next)
228 0           entry->next->prev = entry->prev;
229             else
230 0           context->entry_last = entry->prev;
231            
232 0 0         if(entry->prev)
233 0           entry->prev->next = entry->next;
234             else
235 0           context->entry = entry->next;
236            
237 0           modest_finder_thread_collate_node(modest, node, entry);
238             }
239            
240 0           entry = entry->next;
241             }
242             }
243            
244 0 0         if(node->child)
245 0           node = node->child;
246             else {
247 0 0         while(node != scope_node && node->next == NULL)
    0          
248 0           node = node->parent;
249            
250 0 0         if(node == scope_node)
251 0           break;
252            
253 0           node = node->next;
254             }
255             }
256            
257 0           return MODEST_STATUS_OK;
258             }
259              
260 0           void modest_finder_thread_wait_for_all_done(modest_finder_thread_t* finder_thread)
261             {
262 0 0         for (size_t idx = 0; idx < finder_thread->thread->entries_length; idx++) {
263 0 0         while((finder_thread->thread->entries[idx].context.opt & MyTHREAD_OPT_DONE) == 0) {
264 0           mythread_nanosleep_sleep(finder_thread->thread->timespec);
265             }
266             }
267 0           }
268             #endif /* if undef MyCORE_BUILD_WITHOUT_THREADS */
269              
270 0           modest_finder_thread_context_t * modest_finder_thread_create_context(modest_finder_thread_t* finder_thread, size_t count)
271             {
272 0           finder_thread->context_list_size = count;
273            
274 0           modest_finder_thread_context_t *ctx = mycore_calloc(count, sizeof(modest_finder_thread_context_t));
275            
276 0 0         if(ctx == NULL)
277 0           return NULL;
278            
279             mcobject_async_status_t mcstatus;
280            
281 0 0         for(size_t i = 0; i < count; i++) {
282 0           ctx[i].entry_node_id = mcobject_async_node_add(finder_thread->entry_obj, &mcstatus);
283            
284 0 0         if(mcstatus) {
285 0 0         while(i) {
286 0           i--;
287 0           mcobject_async_node_delete(finder_thread->entry_obj, ctx[i].entry_node_id);
288             }
289            
290 0           mycore_free(ctx);
291 0           return NULL;
292             }
293             }
294            
295 0 0         for(size_t i = 0; i < count; i++) {
296 0           ctx[i].declaration_node_id = mcobject_async_node_add(finder_thread->declaration_obj, &mcstatus);
297            
298 0 0         if(mcstatus) {
299 0           size_t t = count;
300 0 0         while(t > 1) {
301 0           t--;
302 0           mcobject_async_node_delete(finder_thread->entry_obj, ctx[t].entry_node_id);
303             }
304            
305 0 0         while(i > 1) {
306 0           i--;
307 0           mcobject_async_node_delete(finder_thread->declaration_obj, ctx[i].declaration_node_id);
308             }
309            
310 0           mycore_free(ctx);
311 0           return NULL;
312             }
313             }
314            
315 0           return ctx;
316             }
317              
318 0           bool modest_finder_thread_spec_is_up(modest_style_raw_specificity_t* spec_f, modest_style_raw_specificity_t* spec_t)
319             {
320 0 0         if(spec_f->x > spec_t->x)
321 0           return true;
322 0 0         else if(spec_f->x < spec_t->x)
323 0           return false;
324            
325 0 0         if(spec_f->a > spec_t->a)
326 0           return true;
327 0 0         else if(spec_f->a < spec_t->a)
328 0           return false;
329            
330 0 0         if(spec_f->b > spec_t->b)
331 0           return true;
332 0 0         else if(spec_f->b < spec_t->b)
333 0           return false;
334            
335 0 0         if(spec_f->c > spec_t->c)
336 0           return true;
337 0 0         else if(spec_f->c < spec_t->c)
338 0           return false;
339            
340             /* when a property is repeated with multiple values take the last one*/
341 0           return true;
342             }
343              
344 0           void modest_finder_thread_declaratin_append(modest_finder_thread_found_context_t* found_context, bool is_low_priority,
345             modest_finder_thread_entry_t* entry, mycss_declaration_entry_t* dec_entry,
346             modest_style_raw_specificity_t* raw_spec)
347             {
348 0 0         if(entry->declaration == NULL) {
349 0           entry->declaration = entry->declaration_last = mcobject_async_malloc(found_context->finder_thread->declaration_obj,
350 0           found_context->context->declaration_node_id, NULL);
351            
352 0           entry->declaration->entry = dec_entry;
353 0           entry->declaration->raw_spec = *raw_spec;
354 0           entry->declaration->next = NULL;
355 0           entry->declaration->prev = NULL;
356            
357 0           return;
358             }
359            
360 0           modest_finder_thread_declaration_t* thr_dec = entry->declaration;
361            
362 0 0         while(thr_dec) {
363 0 0         if(thr_dec->entry->type == dec_entry->type)
364             {
365 0 0         if(modest_finder_thread_spec_is_up(raw_spec, &thr_dec->raw_spec)) {
366 0           thr_dec->entry = dec_entry;
367 0           thr_dec->raw_spec = *raw_spec;
368             }
369            
370 0           return;
371             }
372            
373 0           thr_dec = thr_dec->next;
374             }
375            
376 0           thr_dec = mcobject_async_malloc(found_context->finder_thread->declaration_obj,
377 0           found_context->context->declaration_node_id, NULL);
378            
379 0           thr_dec->next = NULL;
380 0           thr_dec->entry = dec_entry;
381 0           thr_dec->raw_spec = *raw_spec;
382            
383 0           entry->declaration_last->next = thr_dec;
384 0           thr_dec->prev = entry->declaration_last;
385            
386 0           entry->declaration_last = thr_dec;
387             }
388              
389 0           void modest_finder_thread_declaratin_list_replace(modest_finder_thread_found_context_t* found_context,
390             modest_finder_thread_entry_t* entry, mycss_declaration_entry_t* dec_entry,
391             mycss_selectors_specificity_t* spec)
392             {
393 0 0         while(dec_entry) {
394 0           modest_style_raw_specificity_t raw_spec = {((unsigned int)dec_entry->is_important), spec->a, spec->b, spec->c};
395            
396 0           modest_finder_thread_declaratin_append(found_context, false, entry, dec_entry, &raw_spec);
397            
398 0           dec_entry = dec_entry->next;
399             }
400 0           }
401              
402 0           void modest_finder_thread_callback_found(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_list_t* selector_list, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec, void* ctx)
403             {
404 0           modest_finder_thread_found_context_t* found_context = (modest_finder_thread_found_context_t*)ctx;
405 0           modest_finder_thread_context_t* thread_context = found_context->context;
406            
407 0 0         if(thread_context->entry_last) {
408 0           modest_finder_thread_entry_t* entry = thread_context->entry;
409            
410 0 0         while(entry)
411             {
412 0 0         if(entry->node == node) {
413 0           modest_finder_thread_declaratin_list_replace(found_context, entry, selector_list->declaration_entry, spec);
414 0           return;
415             }
416            
417 0           entry = entry->next;
418             }
419             }
420            
421 0           modest_finder_thread_entry_t* entry = mcobject_async_malloc(found_context->finder_thread->entry_obj, thread_context->entry_node_id, NULL);
422 0           memset(entry, 0, sizeof(modest_finder_thread_entry_t));
423            
424 0           entry->node = node;
425            
426 0           modest_finder_thread_declaratin_list_replace(found_context, entry, selector_list->declaration_entry, spec);
427            
428 0 0         if(thread_context->entry_last) {
429 0           entry->prev = thread_context->entry_last;
430            
431 0           thread_context->entry_last->next = entry;
432 0           thread_context->entry_last = entry;
433             }
434             else {
435 0           thread_context->entry_last = thread_context->entry = entry;
436             }
437             }
438              
439 0           void modest_finder_thread_stream_single(modest_finder_thread_t* finder_thread, mycss_selectors_list_t* selector_list)
440             {
441 0           modest_finder_thread_found_context_t found_ctx = {finder_thread, finder_thread->context_list};
442            
443 0 0         while(selector_list)
444             {
445 0 0         for(size_t i = 0; i < selector_list->entries_list_length; i++) {
446 0           mycss_selectors_entries_list_t *entries = &selector_list->entries_list[i];
447 0           mycss_selectors_specificity_t spec = entries->specificity;
448            
449 0           modest_finder_node_combinator_begin(finder_thread->finder, finder_thread->base_node, selector_list,
450             entries->entry, &spec, modest_finder_thread_callback_found, &found_ctx);
451             }
452            
453 0           selector_list = selector_list->next;
454             }
455 0           }
456              
457             #ifndef MyCORE_BUILD_WITHOUT_THREADS
458 0           void modest_finder_thread_stream(mythread_id_t thread_id, void* arg)
459             {
460 0           mythread_context_t* ctx = (mythread_context_t*)arg;
461 0           modest_finder_thread_t* finder_thread = (modest_finder_thread_t*)ctx->mythread->context;
462 0           mycss_selectors_list_t* selector_list = finder_thread->selector_list;
463            
464 0           modest_finder_thread_found_context_t found_ctx = {finder_thread, &finder_thread->context_list[ctx->id]};
465            
466 0           size_t count = 0, counnt_done = ctx->id - 1;
467 0           size_t offset = (ctx->mythread->entries_size - 1);
468            
469 0 0         while(selector_list) {
470 0 0         for(size_t i = 0; i < selector_list->entries_list_length; i++) {
471             /* split selectors by thread id */
472 0 0         if(count == counnt_done) {
473 0           mycss_selectors_entries_list_t *entries = &selector_list->entries_list[i];
474 0           mycss_selectors_specificity_t spec = entries->specificity;
475            
476 0           modest_finder_node_combinator_begin(finder_thread->finder, finder_thread->base_node, selector_list,
477             entries->entry, &spec, modest_finder_thread_callback_found, &found_ctx);
478            
479 0           counnt_done += offset;
480             }
481            
482 0           count++;
483             }
484            
485 0           selector_list = selector_list->next;
486             }
487 0           }
488             #endif
489