summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2013-07-18 19:39:33 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2013-10-28 15:47:12 +0900
commit07fb7172d57c0bb9151d1510b1d091ff77e36b7a (patch)
tree49cf8abec911d8541327193d159a1140f9480639
parentdeb8776de5b46e280371fc0db894db96287cf681 (diff)
evas/cserve2: Implement shared index and buffers
Only import the C file for now. Implement the following features: - Shared Arrays Store arrays of elements of fixed size in shm. - Shared Mempool Store random sized buffers in shm. These buffers are indexed in a Shared Array and are referred to using their index only. - Shared Strings Store strings in a shm in a way similar to Eina_Stringshare (except strings are referred to using an int index). - Include evas_cserve2_index.c to the compilation. - Declare shared index functions in header file. - Call init() and shutdown() on the shared index subsystem. - Add find and foreach functions
-rw-r--r--src/Makefile_Evas.am1
-rw-r--r--src/bin/evas/evas_cserve2.h43
-rw-r--r--src/bin/evas/evas_cserve2_index.c878
-rw-r--r--src/bin/evas/evas_cserve2_main.c14
4 files changed, 925 insertions, 11 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index 29bea4b603..de3636bf7d 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -1013,6 +1013,7 @@ bin/evas/evas_cserve2_requests.c \
1013bin/evas/evas_cserve2_fonts.c \ 1013bin/evas/evas_cserve2_fonts.c \
1014bin/evas/evas_cserve2_scale.c \ 1014bin/evas/evas_cserve2_scale.c \
1015bin/evas/evas_cserve2_main_loop_linux.c \ 1015bin/evas/evas_cserve2_main_loop_linux.c \
1016bin/evas/evas_cserve2_index.c \
1016lib/evas/cserve2/evas_cs2_utils.h \ 1017lib/evas/cserve2/evas_cs2_utils.h \
1017lib/evas/cserve2/evas_cs2_utils.c 1018lib/evas/cserve2/evas_cs2_utils.c
1018 1019
diff --git a/src/bin/evas/evas_cserve2.h b/src/bin/evas/evas_cserve2.h
index e7e53f3774..b6bdff3e63 100644
--- a/src/bin/evas/evas_cserve2.h
+++ b/src/bin/evas/evas_cserve2.h
@@ -316,4 +316,47 @@ void *cserve2_font_slave_cb(Slave_Thread_Data *sd, Slave_Command *cmd, const voi
316void cserve2_font_source_ft_free(void *fontsource); 316void cserve2_font_source_ft_free(void *fontsource);
317void cserve2_font_ft_free(void *fontinfo); 317void cserve2_font_ft_free(void *fontinfo);
318 318
319// Shared buffers & indexes
320void cserve2_shared_index_init(void);
321void cserve2_shared_index_shutdown(void);
322
323typedef struct _Shared_Array Shared_Array;
324typedef struct _Shared_Mempool Shared_Mempool;
325typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *, const void *);
326
327// Shared arrays (arrays of fixed size object)
328Shared_Array *cserve2_shared_array_new(int tag, int elemsize, int initcount);
329const char *cserve2_shared_array_name_get(Shared_Array *sa);
330void cserve2_shared_array_del(Shared_Array *sa);
331int cserve2_shared_array_size_get(Shared_Array *sa);
332int cserve2_shared_array_count_get(Shared_Array *sa);
333int cserve2_shared_array_item_size_get(Shared_Array *sa);
334int cserve2_shared_array_generation_id_get(Shared_Array *sa);
335int cserve2_shared_array_size_set(Shared_Array *sa, int newcount);
336int cserve2_shared_array_item_new(Shared_Array *sa);
337void *cserve2_shared_array_item_data_get(Shared_Array *sa, int elemid);
338Shared_Array *cserve2_shared_array_repack(Shared_Array *sa,
339 Shared_Array_Repack_Skip_Cb skip,
340 Eina_Compare_Cb cmp);
341int cserve2_shared_array_item_find(Shared_Array *sa, void *data,
342 Eina_Compare_Cb cmp);
343void *cserve2_shared_array_item_data_find(Shared_Array *sa, void *data,
344 Eina_Compare_Cb cmp);
345int cserve2_shared_array_foreach(Shared_Array *sa, Eina_Each_Cb cb, void *data);
346
347// Shared buffers and memory pools
348Shared_Mempool *cserve2_shared_mempool_new(int initsize);
349void cserve2_shared_mempool_del(Shared_Mempool *sm);
350int cserve2_shared_mempool_buffer_new(Shared_Mempool *sm, int size);
351int cserve2_shared_mempool_buffer_ref(Shared_Mempool *sm, int bufferid);
352void cserve2_shared_mempool_buffer_del(Shared_Mempool *sm, int bufferid);
353void *cserve2_shared_mempool_buffer_get(Shared_Mempool *sm, int bufferid);
354
355
356// Shared strings
357int cserve2_shared_string_add(const char *str);
358int cserve2_shared_string_ref(int id);
359void cserve2_shared_string_del(int id);
360const char *cserve2_shared_string_get(int id);
361
319#endif /* _EVAS_CSERVE2_H */ 362#endif /* _EVAS_CSERVE2_H */
diff --git a/src/bin/evas/evas_cserve2_index.c b/src/bin/evas/evas_cserve2_index.c
new file mode 100644
index 0000000000..2579104a7f
--- /dev/null
+++ b/src/bin/evas/evas_cserve2_index.c
@@ -0,0 +1,878 @@
1/* Shared index for cserve2.
2 * EXPERIMENTAL WORK.
3 */
4
5#ifdef HAVE_CONFIG_H
6# include "config.h"
7#endif
8
9#include "evas_cserve2.h"
10#include "evas_cs2_utils.h"
11
12#include <stdint.h>
13
14typedef struct _Data_Shm Data_Shm;
15typedef struct _Index_Entry Index_Entry;
16typedef struct _Block Block;
17typedef struct _Shared_Array_Header Shared_Array_Header;
18typedef struct _Shared_Index Shared_Index;
19
20static int _instances = 0;
21
22// Static memory pool used for storing strings
23static Shared_Mempool *_string_mempool = NULL;
24
25// Map const char* --> buffer id (valid in _string_mempool)
26static Eina_Hash *_string_entries = NULL;
27
28struct _Data_Shm
29{
30 Shm_Handle *shm;
31 char *data;
32};
33
34struct _Shared_Array_Header
35{
36 int32_t tag;
37 int32_t elemsize;
38 int32_t count;
39 int32_t generation_id;
40 int32_t emptyidx;
41 int32_t _reserved1;
42 int32_t _reserved2;
43 int32_t _reserved3;
44};
45
46struct _Shared_Array
47{
48 Data_Shm *ds;
49 Shared_Array_Header *header;
50};
51
52struct _Shared_Index
53{
54 // Random buffer index
55 Shared_Array *sa;
56 int32_t lastid;
57};
58
59struct _Shared_Mempool
60{
61 Data_Shm *ds;
62 Shared_Index *index;
63 int empty_size;
64 Block *empty_blocks;
65};
66
67// Used for empty blocks. RB tree ordered by length.
68struct _Block
69{
70 EINA_RBTREE;
71 int32_t length;
72 int32_t offset;
73 int32_t shmid;
74};
75
76struct _Index_Entry
77{
78 int32_t id; // Write last, can't be 0
79 int32_t refcount;
80 // Block entry
81 int32_t length;
82 int32_t offset;
83 int32_t shmid;
84};
85
86
87// Data blocks will be aligned to blocks of DATA_BLOCKSIZE bytes to reduce
88// fragmentation (after del). 16 is convenient for debugging with hd :)
89#define DATA_BLOCKSIZE 8
90
91static inline int
92_data_blocksize_roundup(int len)
93{
94 return ((len + DATA_BLOCKSIZE - 1) / DATA_BLOCKSIZE) * DATA_BLOCKSIZE;
95}
96
97static Eina_Rbtree_Direction
98_block_rbtree_cmp(const Eina_Rbtree *l, const Eina_Rbtree *r,
99 void *data EINA_UNUSED)
100{
101 const Block *left = (Block *) l;
102 const Block *right = (Block *) r;
103
104 if (!left)
105 return EINA_RBTREE_RIGHT;
106
107 if (!right)
108 return EINA_RBTREE_LEFT;
109
110 if (left->length <= right->length)
111 return EINA_RBTREE_LEFT;
112 else
113 return EINA_RBTREE_RIGHT;
114}
115
116static inline int
117_block_rbtree_empty_spot_find(const Block *node, const void *key,
118 int key_length EINA_UNUSED,
119 void *data EINA_UNUSED)
120{
121 int32_t length = (int32_t) (intptr_t) key;
122
123 // Found best spot
124 if (node->length == length)
125 return 0;
126
127 // We're good, can we find better?
128 if (node->length > length)
129 {
130 Block *lson = (Block *) node->__rbtree.son[0];
131
132 if (lson && lson->length >= length)
133 return -1;
134
135 // This is the best we can do...
136 return 0;
137 }
138
139 // Keep calm and carry on
140 return 1;
141}
142
143static inline int
144_block_rbtree_block_find(const Block *node, const void *key,
145 int key_length EINA_UNUSED,
146 void *data EINA_UNUSED)
147{
148 const Index_Entry *ie = key;
149
150 // Found best spot
151 if ((node->length == ie->length)
152 && (node->offset == ie->offset)
153 && (node->shmid == ie->shmid))
154 return 0;
155
156 // We're good, can we find better?
157 if (node->length > ie->length)
158 {
159 Block *lson = (Block *) node->__rbtree.son[0];
160
161 if (lson && lson->length >= ie->length)
162 return -1;
163
164 // This is the best we can do...
165 return 0;
166 }
167
168 // Keep calm and carry on
169 return 1;
170}
171
172
173// Data shm
174
175Data_Shm *
176_shared_data_shm_new(int size)
177{
178 Data_Shm *ds;
179 size_t mapping_size;
180
181 if (size <= 0)
182 return NULL;
183
184 ds = calloc(1, sizeof(Data_Shm));
185 if (!ds) return NULL;
186
187 mapping_size = cserve2_shm_size_normalize((size_t) size);
188
189 ds->shm = cserve2_shm_request("data", mapping_size);
190 if (!ds->shm)
191 {
192 ERR("Could not create shm of size %u", (unsigned) mapping_size);
193 free(ds);
194 return NULL;
195 }
196
197 ds->data = cserve2_shm_map(ds->shm);
198 if (!ds->data)
199 {
200 ERR("Could not map shm of size %u", (unsigned) mapping_size);
201 cserve2_shm_unref(ds->shm);
202 free(ds);
203 return NULL;
204 }
205
206 DBG("Created data shm of size %d: %d", size, cserve2_shm_id_get(ds->shm));
207 return ds;
208}
209
210void
211_shared_data_shm_del(Data_Shm *ds)
212{
213 if (!ds) return;
214 cserve2_shm_unref(ds->shm);
215 free(ds);
216}
217
218int
219_shared_data_shm_resize(Data_Shm *ds, size_t newsize)
220{
221 Shm_Handle *shm;
222 size_t mapping_size;
223
224 if (newsize <= 0)
225 return -1;
226
227 mapping_size = cserve2_shm_size_normalize(newsize);
228 cserve2_shm_unmap(ds->shm);
229 ds->data = NULL;
230
231 shm = cserve2_shm_resize(ds->shm, mapping_size);
232 if (!shm)
233 {
234 ERR("Could not resize shm %d to %u",
235 cserve2_shm_id_get(ds->shm), (unsigned) newsize);
236 return -1;
237 }
238
239 ds->shm = shm;
240 ds->data = cserve2_shm_map(ds->shm);
241 if (!ds->data)
242 {
243 ERR("Failed to remap shm %d after resizing to %u bytes",
244 cserve2_shm_id_get(ds->shm), (unsigned) mapping_size);
245 return -1;
246 }
247
248 return mapping_size;
249}
250
251
252// Arrays
253
254Shared_Array *
255cserve2_shared_array_new(int tag, int elemsize, int initcount)
256{
257 Shared_Array *sa;
258 Data_Shm *ds;
259 int mapping_size;
260
261 if (elemsize <= 0 || initcount < 0)
262 return NULL;
263
264 sa = calloc(1, sizeof(Shared_Array));
265 if (!sa) return NULL;
266
267 if (!initcount) initcount = 1;
268 mapping_size = cserve2_shm_size_normalize(elemsize * initcount
269 + sizeof(Shared_Array_Header));
270 ds = _shared_data_shm_new(mapping_size);
271 if (!ds)
272 {
273 free(sa);
274 return NULL;
275 }
276
277 sa->ds = ds;
278 sa->header = (Shared_Array_Header *) ds->data;
279 sa->header->count = (mapping_size - sizeof(Shared_Array_Header)) / elemsize;
280 sa->header->elemsize = elemsize;
281 sa->header->generation_id = 1;
282 sa->header->emptyidx = 0;
283 sa->header->tag = tag;
284 memset(&sa->header->_reserved1, 0, sizeof(int32_t) * 3);
285
286 return sa;
287}
288
289const char *
290cserve2_shared_array_name_get(Shared_Array *sa)
291{
292 if (!sa) return NULL;
293 return cserve2_shm_name_get(sa->ds->shm);
294}
295
296void
297cserve2_shared_array_del(Shared_Array *sa)
298{
299 if (!sa) return;
300 _shared_data_shm_del(sa->ds);
301 free(sa);
302}
303
304int
305cserve2_shared_array_size_get(Shared_Array *sa)
306{
307 if (!sa) return -1;
308 return sa->header->count;
309}
310
311int
312cserve2_shared_array_count_get(Shared_Array *sa)
313{
314 if (!sa) return -1;
315 return sa->header->emptyidx;
316}
317
318int
319cserve2_shared_array_item_size_get(Shared_Array *sa)
320{
321 if (!sa) return -1;
322 return sa->header->elemsize;
323}
324
325int
326cserve2_shared_array_generation_id_get(Shared_Array *sa)
327{
328 if (!sa) return -1;
329 return sa->header->generation_id;
330}
331
332int
333cserve2_shared_array_size_set(Shared_Array *sa, int newcount)
334{
335 int mapping_size;
336
337 if (!sa) return -1;
338 mapping_size = cserve2_shm_size_normalize(sa->header->elemsize * newcount
339 + sizeof(Shared_Array_Header));
340 if (_shared_data_shm_resize(sa->ds, mapping_size) < 0)
341 {
342 sa->header = NULL;
343 return -1;
344 }
345 sa->header = (Shared_Array_Header *) sa->ds->data;
346 sa->header->count = (mapping_size - sizeof(Shared_Array_Header))
347 / sa->header->elemsize;
348
349 return sa->header->count;
350}
351
352int
353cserve2_shared_array_item_new(Shared_Array *sa)
354{
355 if (!sa) return -1;
356 if (sa->header->emptyidx >= sa->header->count)
357 {
358 int newcount = cserve2_shared_array_size_set(sa, sa->header->count + 1);
359 if (newcount < 0) return -1;
360 }
361
362 return sa->header->emptyidx++;
363}
364
365const void *
366cserve2_shared_array_item_data(Shared_Array *sa)
367{
368 return cserve2_shared_array_item_data_get(sa, 0);
369}
370
371void *
372cserve2_shared_array_item_data_get(Shared_Array *sa, int elemid)
373{
374 char *ptr;
375
376 if (!sa) return NULL;
377 if (elemid < 0 || elemid >= sa->header->count)
378 return NULL;
379
380 ptr = (char *) sa->header;
381 ptr += sizeof(Shared_Array_Header);
382 ptr += elemid * sa->header->elemsize;
383
384 return ptr;
385}
386
387int
388cserve2_shared_array_foreach(Shared_Array *sa, Eina_Each_Cb cb, void *data)
389{
390 char *ptr;
391 int k;
392
393 if (!sa || !cb) return -1;
394 ptr = sa->ds->data + sizeof(Shared_Array_Header);
395
396 for (k = 0; k < sa->header->emptyidx; k++)
397 {
398 if (!cb(sa, ptr, data))
399 break;
400 ptr += sa->header->elemsize;
401 }
402
403 return k;
404}
405
406Shared_Array *
407cserve2_shared_array_repack(Shared_Array *sa,
408 Shared_Array_Repack_Skip_Cb skip,
409 Eina_Compare_Cb cmp)
410{
411 Eina_List *l = NULL;
412 Shared_Array *sa2;
413 const char *srcdata;
414 char *dstdata;
415 int k, elemsize, newcount = 0;
416
417 if (!sa || !skip || !cmp) return NULL;
418 srcdata = sa->ds->data + sizeof(Shared_Array_Header);
419 elemsize = sa->header->elemsize;
420
421 // Build ordered list of pointers
422 for (k = 0; k < sa->header->emptyidx; k++)
423 {
424 const char *data = srcdata + k * elemsize;
425 if (skip(sa, data)) continue;
426 l = eina_list_sorted_insert(l, cmp, data);
427 newcount++;
428 }
429
430 // Create new array
431 sa2 = cserve2_shared_array_new(0, elemsize, newcount);
432 if (!sa)
433 {
434 ERR("Can not repack array: failed to create new array");
435 return NULL;
436 }
437 sa2->header->generation_id = sa->header->generation_id + 1;
438
439 // Write data
440 dstdata = sa2->ds->data + sizeof(Shared_Array_Header);
441 while (l)
442 {
443 const char *data = eina_list_data_get(l);
444 l = eina_list_remove_list(l, l);
445 memcpy(dstdata, data, elemsize);
446 }
447
448 // Finalize & return
449 sa2->header->emptyidx = newcount;
450 sa2->header->tag = sa->header->tag;
451 return sa2;
452}
453
454int
455cserve2_shared_array_item_find(Shared_Array *sa, void *data,
456 Eina_Compare_Cb cmp)
457{
458 int k;
459 const char *ptr;
460
461 if (!sa || !cmp) return -1;
462
463 // TODO: Fast search in the sorted zone
464
465 ptr = sa->ds->data;
466
467 // Linear search O(n)
468 for (k = 0; k < sa->header->emptyidx; k++)
469 {
470 if (!cmp(ptr, data))
471 return k;
472 ptr += sa->header->elemsize;
473 }
474
475 return -1;
476}
477
478void *
479cserve2_shared_array_item_data_find(Shared_Array *sa, void *data,
480 Eina_Compare_Cb cmp)
481{
482 int elemid;
483
484 elemid = cserve2_shared_array_item_find(sa, data, cmp);
485 if (elemid < 0) return NULL;
486
487 return cserve2_shared_array_item_data_get(sa, elemid);
488}
489
490
491// Shared index (used by the random mempool)
492
493static Index_Entry *
494_shared_index_entry_new(Shared_Index *si)
495{
496 Index_Entry *ie;
497 int id;
498
499 if (!si) return NULL;
500
501 id = cserve2_shared_array_item_new(si->sa);
502 if (id < 0) return NULL;
503
504 ie = cserve2_shared_array_item_data_get(si->sa, id);
505 ie->id = si->lastid++;
506 return ie;
507}
508
509static Index_Entry *
510_shared_index_entry_find(Shared_Index *si, int id)
511{
512 int k, count;
513
514 if (!si) return NULL;
515 count = cserve2_shared_array_count_get(si->sa);
516
517 // FIXME: Linear search O(n)
518 for (k = 0; k < count; k++)
519 {
520 Index_Entry *ie;
521 ie = cserve2_shared_array_item_data_get(si->sa, k);
522 if (!ie) break;
523 if (ie->id == id)
524 return ie;
525 }
526
527 return NULL;
528}
529
530static Shared_Index *
531_shared_index_new()
532{
533 Shared_Index *si;
534 Index_Entry *ie;
535 int tag = 1234; // FIXME?
536
537 si = calloc(1, sizeof(Shared_Index));
538 if (!si) return NULL;
539
540 si->sa = cserve2_shared_array_new(tag, sizeof(Index_Entry), 1);
541 if (!si->sa)
542 {
543 free(si);
544 return NULL;
545 }
546
547 si->lastid = 0;
548 ie = _shared_index_entry_new(si);
549 if (!ie)
550 {
551 cserve2_shared_array_del(si->sa);
552 free(si);
553 return NULL;
554 }
555
556 return si;
557}
558
559void
560_shared_index_del(Shared_Index *si)
561{
562 if (!si) return;
563 cserve2_shared_array_del(si->sa);
564 free(si);
565}
566
567
568// Shared memory pool
569
570Shared_Mempool *
571cserve2_shared_mempool_new(int initsize)
572{
573 Shared_Mempool *sm;
574 size_t mapping_size;
575
576 if (initsize < 0) return NULL;
577
578 sm = calloc(1, sizeof(Shared_Mempool));
579 if (!sm) return NULL;
580
581 if (!initsize) initsize = 1;
582 mapping_size = cserve2_shm_size_normalize((size_t) initsize);
583
584 sm->ds = _shared_data_shm_new(mapping_size);
585 if (!sm->ds)
586 {
587 free(sm);
588 return NULL;
589 }
590
591 sm->index = _shared_index_new();
592 if (!sm->index)
593 {
594 _shared_data_shm_del(sm->ds);
595 free(sm);
596 return NULL;
597 }
598
599 sm->empty_size = mapping_size;
600 return sm;
601}
602
603static void
604_shared_mempool_block_del(Eina_Rbtree *node, void *data EINA_UNUSED)
605{
606 Block *blk = (Block *) node;
607 free(blk);
608}
609
610void
611cserve2_shared_mempool_del(Shared_Mempool *sm)
612{
613 if (!sm) return;
614 eina_rbtree_delete(EINA_RBTREE_GET(sm->empty_blocks),
615 EINA_RBTREE_FREE_CB(_shared_mempool_block_del), sm);
616 _shared_data_shm_del(sm->ds);
617 _shared_index_del(sm->index);
618 free(sm);
619}
620
621static Index_Entry *
622_shared_mempool_buffer_new(Shared_Mempool *sm, int size)
623{
624
625 Index_Entry *ie;
626 Block *blk;
627 int mapping_size, new_mapping_size;
628 int rsize = _data_blocksize_roundup(size);
629
630 if (!sm) return NULL;
631 if (size <= 0) return NULL;
632
633 mapping_size = cserve2_shm_map_size_get(sm->ds->shm);
634
635 ie = _shared_index_entry_new(sm->index);
636 if (!ie) return NULL;
637
638 // Append if possible
639 if (rsize <= sm->empty_size)
640 {
641 ie->length = rsize;
642 ie->offset = mapping_size - sm->empty_size;
643 ie->shmid = cserve2_shm_id_get(sm->ds->shm);
644 ie->refcount = 1;
645 sm->empty_size -= rsize;
646 return ie;
647 }
648
649 // Find empty spot
650 blk = (Block *) eina_rbtree_inline_lookup(
651 EINA_RBTREE_GET(sm->empty_blocks), (void *) (intptr_t) rsize, 0,
652 EINA_RBTREE_CMP_KEY_CB(_block_rbtree_empty_spot_find), NULL);
653 if (blk && blk->length >= rsize)
654 {
655 ie->length = blk->length;
656 ie->offset = blk->offset;
657 ie->shmid = cserve2_shm_id_get(sm->ds->shm);
658 ie->refcount = 1;
659
660 sm->empty_blocks = (Block *) eina_rbtree_inline_remove(
661 EINA_RBTREE_GET(sm->empty_blocks), EINA_RBTREE_GET(blk),
662 EINA_RBTREE_CMP_NODE_CB(_block_rbtree_cmp), NULL);
663 if (blk->length == rsize)
664 free(blk);
665 else
666 {
667 blk->length -= rsize;
668 blk->offset += rsize;
669 sm->empty_blocks = (Block *) eina_rbtree_inline_insert(
670 EINA_RBTREE_GET(sm->empty_blocks), EINA_RBTREE_GET(blk),
671 EINA_RBTREE_CMP_NODE_CB(_block_rbtree_cmp), NULL);
672 }
673
674 return ie;
675 }
676
677 // Grow mempool
678 new_mapping_size = _shared_data_shm_resize(
679 sm->ds, mapping_size + rsize - sm->empty_size);
680 if (new_mapping_size < 0)
681 {
682 memset(ie, 0, sizeof(Index_Entry));
683 return NULL;
684 }
685 ie->length = rsize;
686 ie->offset = mapping_size - sm->empty_size;
687 ie->shmid = cserve2_shm_id_get(sm->ds->shm);
688 ie->refcount = 1;
689 sm->empty_size += (new_mapping_size - mapping_size) - rsize;
690 return ie;
691}
692
693int
694cserve2_shared_mempool_buffer_new(Shared_Mempool *sm, int size)
695{
696 Index_Entry *ie;
697
698 ie = _shared_mempool_buffer_new(sm, size);
699 if (!ie) return -1;
700
701 return ie->id;
702}
703
704int
705cserve2_shared_mempool_buffer_ref(Shared_Mempool *sm, int bufferid)
706{
707 Index_Entry *ie;
708
709 if (!sm) return -1;
710 ie = _shared_index_entry_find(sm->index, bufferid);
711 if (!ie) return -1;
712
713 if (!ie->refcount)
714 {
715 Block *blk = (Block *)
716 eina_rbtree_inline_lookup(EINA_RBTREE_GET(sm->empty_blocks),
717 ie, sizeof(Index_Entry),
718 EINA_RBTREE_CMP_KEY_CB(
719 _block_rbtree_block_find),
720 sm);
721 if (blk && (blk->length == ie->length)
722 && (blk->offset == ie->offset)
723 && (blk->shmid == ie->shmid))
724 {
725 sm->empty_blocks = (Block *) eina_rbtree_inline_remove(
726 EINA_RBTREE_GET(sm->empty_blocks), EINA_RBTREE_GET(blk),
727 EINA_RBTREE_CMP_NODE_CB(_block_rbtree_cmp), NULL);
728 free(blk);
729 }
730 }
731
732 ie->refcount++;
733 return ie->id;
734}
735
736void
737cserve2_shared_mempool_buffer_del(Shared_Mempool *sm, int bufferid)
738{
739 Index_Entry *ie;
740
741 if (!sm || !bufferid) return;
742 ie = _shared_index_entry_find(sm->index, bufferid);
743 if (!ie || ie->refcount <= 0)
744 {
745 CRIT("Tried to delete invalid buffer or with refcount 0");
746 return;
747 }
748
749 ie->refcount--;
750 if (!ie->refcount)
751 {
752 Block *newblk = calloc(1, sizeof(Block));
753 newblk->length = ie->length;
754 newblk->offset = ie->offset;
755 newblk->shmid = ie->shmid;
756 sm->empty_blocks = (Block *) eina_rbtree_inline_insert(
757 EINA_RBTREE_GET(sm->empty_blocks), EINA_RBTREE_GET(newblk),
758 EINA_RBTREE_CMP_NODE_CB(_block_rbtree_cmp), NULL);
759 }
760}
761
762void *
763cserve2_shared_mempool_buffer_get(Shared_Mempool *sm, int bufferid)
764{
765 Index_Entry *ie;
766 char *data;
767
768 if (!sm) return NULL;
769 ie = _shared_index_entry_find(sm->index, bufferid);
770 if (!ie || ie->refcount <= 0)
771 {
772 CRIT("Tried to access invalid buffer or with refcount 0");
773 return NULL;
774 }
775
776 data = sm->ds->data + ie->offset;
777 return data;
778}
779
780
781// Shared strings
782
783int
784cserve2_shared_string_add(const char *str)
785{
786 Index_Entry *ie;
787 char *data;
788 int len, id;
789
790 if (!str) return -1;
791
792 // Find in known strings
793 id = (int) (intptr_t) eina_hash_find(_string_entries, str);
794 if (id > 0)
795 {
796 ie = _shared_index_entry_find(_string_mempool->index, id);
797 if (!ie || ie->refcount <= 0)
798 {
799 CRIT("String found in hash but not in mempool!");
800 eina_hash_del(_string_entries, str, (void *) (intptr_t) id);
801 goto new_entry;
802 }
803 ie->refcount++;
804 return ie->id;
805 }
806
807 // Add new entry
808new_entry:
809 len = strlen(str) + 1;
810 ie = _shared_mempool_buffer_new(_string_mempool, len);
811 if (!ie)
812 {
813 ERR("Could not store new string in shm");
814 return -1;
815 }
816
817 eina_hash_add(_string_entries, str, (void *) (intptr_t) ie->id);
818 data = _string_mempool->ds->data + ie->offset;
819 memcpy(data, str, len);
820 return ie->id;
821}
822
823int
824cserve2_shared_string_ref(int id)
825{
826 if (!id) return 0;
827 return cserve2_shared_mempool_buffer_ref(_string_mempool, id);
828}
829
830void
831cserve2_shared_string_del(int id)
832{
833 if (!id) return;
834 if (_shared_mempool_buffer_del(_string_mempool, id))
835 {
836 if (!eina_hash_del_by_data(_string_entries, (void *) (intptr_t) id))
837 CRIT("Invalid free");
838 }
839}
840
841const char *
842cserve2_shared_string_get(int id)
843{
844 if (!id) return NULL;
845 return cserve2_shared_mempool_buffer_get(_string_mempool, id);
846}
847
848
849
850// Init/destroy
851
852void
853cserve2_shared_index_init(void)
854{
855 if (!_instances)
856 {
857 DBG("Initializing shared index");
858 _string_mempool = cserve2_shared_mempool_new(4096);
859 _string_entries = eina_hash_string_djb2_new(NULL);
860 }
861 _instances++;
862}
863
864void
865cserve2_shared_index_shutdown(void)
866{
867 _instances--;
868 if (!_instances)
869 {
870 DBG("Destroying shared index");
871 cserve2_shared_mempool_del(_string_mempool);
872 eina_hash_free(_string_entries);
873
874 _string_mempool = NULL;
875 _string_entries = NULL;
876 }
877}
878
diff --git a/src/bin/evas/evas_cserve2_main.c b/src/bin/evas/evas_cserve2_main.c
index a2bb9c402d..e77eba2f14 100644
--- a/src/bin/evas/evas_cserve2_main.c
+++ b/src/bin/evas/evas_cserve2_main.c
@@ -327,34 +327,26 @@ main(int argc EINA_UNUSED, const char *argv[])
327 goto error; 327 goto error;
328 } 328 }
329 329
330 cserve2_shm_init();
331 cserve2_shared_index_init();
330 cserve2_requests_init(); 332 cserve2_requests_init();
331
332 cserve2_scale_init(); 333 cserve2_scale_init();
333
334 cserve2_font_init(); 334 cserve2_font_init();
335
336 cserve2_cache_init(); 335 cserve2_cache_init();
337
338 cserve2_shm_init();
339
340 _clients_setup(); 336 _clients_setup();
341 337
342 cserve2_main_loop_run(); 338 cserve2_main_loop_run();
343 339
344 _clients_finish(); 340 _clients_finish();
345
346 cserve2_cache_shutdown(); 341 cserve2_cache_shutdown();
347
348 cserve2_font_shutdown(); 342 cserve2_font_shutdown();
349
350 cserve2_scale_shutdown(); 343 cserve2_scale_shutdown();
351
352 cserve2_requests_shutdown(); 344 cserve2_requests_shutdown();
353
354 cserve2_slaves_shutdown(); 345 cserve2_slaves_shutdown();
355 346
356 cserve2_main_loop_finish(); 347 cserve2_main_loop_finish();
357 348
349 cserve2_shared_index_shutdown();
358 cserve2_shm_shutdown(); 350 cserve2_shm_shutdown();
359 351
360 eina_prefix_free(_evas_cserve2_pfx); 352 eina_prefix_free(_evas_cserve2_pfx);