1

Comme vous le savez peut-être, depuis quelque temps je bosse sur M*LIB, une librairie permettant de faire des containers génériques en C. En gros un équivalent de la STL en pur C (mais pas que).
Ça a pas mal avancé, et voici un petit aperçu de ce qu'elle permet :
M*LIB is a meta library allowing the programmer to use **generic but type safe container** in pure C language.
The objects within the containers can have proper constructor and destructor: it will be handled by the library. It allows the library to construct fully recursive objects (using container of container of objects).

The available containers are:

* m-list.h: header for creating linked list of generic type,
* m-dict.h: header for creating dictionary of generic types,
* m-shared.h: header for creating shared pointer of generic type,
* m-array.h: header for creating array of generic type and of dynamic variable size,
* m-tuple.h: header for creating arbitrary tuple of generic type,
* m-btree.h: header for creating binary sorted tree TODO

Each containers define iterators which are parts of the generality of the library.

The available intrusive containers are:

* m-i-list.h: header for creating dual-linked intrusive list of generic type, TODO
* m-i-shared.h: header for creating intrusiv eshared pointer of generic type, TODO

The available containers for thread synchronization are:

* m-buffer.h: header for creating fixed-size queue (or stack) of generic type (thread safe),
* m-pbuffer.h: header for creating fixed-size priority queue of generic type (thread safe) TODO,
* m-snapshot: header for creating 'snapshot' buffer for passing data between a producer and multiple consumers running at different rates (thread safe). It ensures that the consumer only sees complete data with minimal lag, but the consumer doesn't expect to see every piece of data.


Other headers offering other functionality are:

* m-bitset.h: header for creating bit set TODO
* m-string.h: header for creating variable-length string,
* m-core.h: header for meta-programming with the C preprocessor.
* m-mutex.h: header for providing a very thin layer accross multiple implementation of mutex/threads.
* m-algo.h: header for providing various generic algorithms to the previous containers. WIP

Il me reste pas mal de boulot à faire pour que tout fonctionne ensemble harmonieusement, mais c'est déjà tout à fait utilisable.
Par contre, je ne sais pas comment nommer cette librarie... ce qui est gênant pour faire une release !

Des idées ?

Link: https://github.com/P-p-H-d/mlib

2

PpHd's Headers ?
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

3

(pourquoi vous ajoutez tous des "/" à la fin des URLs de yAronet ?)

Pas d'idée pour le nom, mais tu as des exemples récents de ce que ça donne à l'utilisation ? smile
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

4

Zeph (./3) :
(pourquoi vous ajoutez tous des "/" à la fin des URLs de yAronet ?)
Fixed Parce que lorsque j'ai récupéré l'url de suivi-sujets, c'était topics/168363-c-preprocessor-tricks-tips-and-idioms/2#post-59 que j'ai retravaillé trop en supprimant 2#post-59
Pas d'idée pour le nom, mais tu as des exemples récents de ce que ça donne à l'utilisation ? smile

Quelques exemples: #include "m-list.h" #include "m-array.h" #include "m-dict.h" #include "m-buffer.h" #include "m-mutex.h" LIST_DEF(string, string_t, STRING_OPLIST) ARRAY_DEF(int, int) list_string_t current_group; bool parse_script_command(char buffer[]) { list_string_t args; list_it_string_t it; STRING_DECL_INIT(command); STRING_DECL_INIT(charac); STRING_DECL_INIT(effect); list_string_init (args); parse_generic_command (args, buffer); list_string_pop_back (&command, args); if (string_equal_str_p (command, "JOIN")) { list_string_pop_back (&charac, args); list_string_push_back(current_group, charac); } else if (string_equal_str_p (command, "LEAVE")) { list_string_pop_back (&charac, args); for(list_string_begin(it, current_group) ; !list_string_end_p(it) ; list_string_next(it)) if (string_equal_p(charac, *list_string_cref(it))) list_string_remove (current_group, it); } else if (string_equal_str_p (command, "GIVE")) { list_string_pop_back (&charac, args); list_string_pop_back (&effect, args); int p = find_character(string_get_cstr(charac)); int w = find_effect(string_get_cstr(effect)); array_int_push_back (character_tab[p].effect_tab, w); // ... } DICT_DEF2(str, string_t, STRING_OPLIST, string_t, STRING_OPLIST) dict_str_t dict; void read_dict(void) { string_t key, ref; dict_str_init(dict); string_init(key); string_init(ref); FILE *f = fopen("dict.txt", "rt"); if (!f) abort(); dict_str_set_at(dict, STRING_CTE("LICENCE"), STRING_CTE("BSD3")); while (!feof(f) && !ferror(f)) { string_fgets(key, f, STRING_READ_PURE_LINE); size_t idx = string_search_char(key, ':'); string_set(ref, key); string_right(ref, idx+1); string_left(key, idx); dict_str_set_at (dict, key, ref); } fclose(f); } void control_dict(void) { for EACH(it, dict, DICT_OPLIST(str)) { const dict_pair_str_t *r = dict_str_cref(it); printf ("key=%s value=%s\n", string_get_cstr((*r)->key), string_get_cstr((*r)->value)); } } // Define a fixed queue of unsigned int BUFFER_DEF(unsigned int, uint, 10, BUFFER_QUEUE|BUFFER_BLOCKING) // Define a variable stack of float BUFFER_DEF(float, floats, 0, BUFFER_STACK|BUFFER_BLOCKING) // Define a fixed stack of char without blocking BUFFER_DEF(char, char, 10, BUFFER_STACK|BUFFER_UNBLOCKING) // Define a fixed queue of long long, unthread safe and without blocking BUFFER_DEF(long long, llong, 16, BUFFER_QUEUE|BUFFER_THREAD_UNSAFE|BUFFER_UNBLOCKING) // Define a fixed queue of mpz_t #include <gmp.h> BUFFER_DEF(mpz_t, mpz, 32, BUFFER_QUEUE, (INIT(mpz_init), SET(mpz_set), CLEAR(mpz_clear))) buffer_uint_t g_buff; static void *conso(void *arg) { unsigned int j; assert (arg == NULL); for(int i = 0; i < 1000;i++) { buffer_uint_pop(&j, g_buff); assert (j < 1000); } return NULL; } static void *prod(void *arg) { assert (arg == NULL); for(unsigned int i = 0; i < 1000;i++) buffer_uint_push(g_buff, &i); return NULL; } static void test_global(void) { M_THREAD_T idx_p[100]; M_THREAD_T idx_c[100]; buffer_uint_init(g_buff, 10); for(int i = 0; i < 100; i++) { M_THREAD_CREATE (idx_p[i], conso, NULL); M_THREAD_CREATE (idx_c[i], prod, NULL); } for(int i = 0; i < 100;i++) { M_THREAD_JOIN(idx_p[i]); M_THREAD_JOIN(idx_c[i]); } buffer_uint_clear(g_buff); }

5

Ah ouais. Bon avec de l'habitude ça doit venir, mais c'est encore plus gore que du C++ grin
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

6

Perso si c'est pour amener le pire du C++ sur le C, c'est sans moi.

Tu as qu'a l'appeler "SM" tongue
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

7

Peut-être qu'il code dans un cadre où le C++ n'est pas une option ?

8

__c_est_encore_plus_verbeux_que_le_java__

9

Pour ceux que ça intéresse, https://github.com/P-p-H-d/mlib

10

MERCI d'avoir publié ca, et MERCI de l'avoir fait en BSD parce que je vais pouvoir le présenter a des gens qui font du C intensif mais pas du tout possible en GPL.

11

Pas de problème !

12

Exemple d'intégration des différentes collections entre elles : https://github.com/P-p-H-d/mlib/blob/master/example/ex08.c
Micro-bench : https://github.com/P-p-H-d/mlib/wiki/performance

13

Y'a pas QtCore dans ton bench. sad
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

14

Added

15

Qt5 doesn't have a container whish is a set offering total ordering. As such, it was QMap which was tested instead.
Essaie QMap<T, QHashDummyValue>. (C'est comme ça qu'est implémenté QSet en termes de QHash. Cela dit, QHash a des optimisations pour éviter de manipuler le nœud bidon inutilement, QMap ne les a pas.)

Et c'est très vieux 5.3.2…
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

16

QHashDummyValue ne fonctionne pas.

17

Euh si, ça fonctionne, au moins chez moi: https://github.com/P-p-H-d/mlib/pull/7
Mais ça n'apporte pas grand chose. L'objet dummy prend quand-même 1 octet (à cause du standard C++ à la con), l'alignement en fait 4 ou 8, QHash a une optimisation pour éviter ça, mais pas QMap.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

18

Merged.

19

La page benchmark a été mise à jour avec plus d'informations : https://github.com/P-p-H-d/mlib/wiki/performance

20

TCC semble avoir été corrigé suite à ton report, tu pourras compléter les tests et mettre la page des compilateurs à jour. smile

21

J'ai vu. Malheureusement, un autre bug empêche de compiler (La macro M_IF_METHOD ne marche pas, alors que M_IF et M_TEST_METHOD pris séparément marchent). J'ai du mal à faire un test case simple (sinon j'enverrai le gros paquet), mais j'avoue que je ne comprends pas du tout ce qui se passe.
Et il y a le problème que tinycc ne supporte pas stdatomic.h

22

MAJ de la page performance avec l'ajout du code dict de M*LIB en mode Open Addressing (L'honneur est sauf!)

23

NEWS:
* Nouveau containers:
- list_dual_push
- deque
- heap priority queue
- set
- Stored hash dictionnary
- intrusive list
- intrusive shared pointer
- variant
- Lock-Free MPMC Queue
- Lock-Free SPSC Queue
- Lock-Free MPMC Snapshot
- Lock-Free SPMC Snapshot
- Bounded shared ressource
* Nouvelles fonctionnalités:
- mempool
- bounded string
- worker support for async execution
- algo stable sort
* Increase performance
* Add new bench:
- K-nucleotide
- string
- mempool
- Compiler bench
* Fix bugs
* Fix compatibility with C++ & TCC & other

24

La version V0.2.0 de M*LIB est sortie apportant:
* un nettoyage de l'API pour qu'elle apparaisse plus uniforme et cohérente,
* quelques containers de plus (m-concurrent pour transformer un containter quelconque en container protégé contre les accès multiples, ...)
* pas mal de bugs fix, surtout sur l'intégration verticale en C11. Ce qui fait qu'un projet implémente maintenant tout son modèle de classes de donnée avec M*LIB cheeky

Prochaine étape: ajouter l'import / export JSON / XML / MSGPACK / BINARY / ... pour tous les types via une interface de customisation.

25

L'import / export JSON est fonctionnel sous master pour ceux que ça intéresse (la sérialisation automatique des types basiques n'est dispo qu'en C11 cependant), tout comme le SSO pour les string.
(Exemple: https://github.com/P-p-H-d/mlib/blob/master/example/ex-json01.c )

26

#bananayel# top
(cheeky)

27

Si vous avez des idées de petits programmes à faire pour enrichir la section exemple, n'hésitez pas.

28

La version 0.4.0 vient de sortir. Elle inclut:
* une meilleure détection des erreurs typiques de la librairie qui finissent en static_assert fail (et on évite donc les pages et les pages d'erreurs)
* Support des fonctions objets
* Plus d’algorithmes disponibles
* Quelques micro optimisation
* Des bug fixes
* Plus de docs.

Exemple de JSON + Fonction Objet:
#include "m-tuple.h" #include "m-array.h" #include "m-algo.h" #include "m-funcobj.h" #include "m-serial-json.h" #include "m-string.h" /* Define the employee */ TUPLE_DEF2(employee, (name, string_t), (age, int), (idnum, int)) #define M_OPL_employee_t() TUPLE_OPLIST(employee, STRING_OPLIST, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST) /* Define an array of employee and some algorithms on it */ ARRAY_DEF(vector_employee, employee_t) #define M_OPL_vector_employee_t() ARRAY_OPLIST(vector_employee, M_OPL_employee_t()) ALGO_DEF(vector_employee, vector_employee_t) /* Define the function object to select the sort order */ FUNC_OBJ_INS_DEF(compare_by, vector_employee_cmp_obj, (a, b), { if (string_equal_str_p(self->sort_field, "name")) return string_cmp(a->name, b->name); else if (string_equal_str_p(self->sort_field, "age")) return a->age < b->age ? -1 : a->age > b->age; else return a->idnum < b->idnum ? -1 : a->idnum > b->idnum; }, (sort_field, string_t) ) #define M_OPL_compare_by_t() FUNC_OBJ_INS_OPLIST(compare_by, STRING_OPLIST) // Let's read an array of person from the given JSON file static void read(vector_employee_t base, const char filename[]) { m_serial_return_code_t ret; // Open the file FILE *f = fopen(filename, "rt"); if (!f) { fprintf(stderr, "ERROR: Cannot open file '%s'.\n", filename); exit(2); } // Initialize the JSON serializer with this file M_LET( (in,f), m_serial_json_read_t) ret = vector_employee_in_serial(base, in); // Let's handle errors if (ret != M_SERIAL_OK_DONE) { fprintf(stderr, "ERROR: Cannot read JSON data from file '%s'.\nParsing stops at:\n", filename); while (!feof(f)) { fputc(fgetc(f), stdout); } fclose(f); exit(2); } fclose(f); } int main(void) { M_LET(emps, vector_employee_t) { /* Code to populate database from JSON */ read(emps, "ex11-algo02.json"); // Sort the database by employee ID number M_LET( (cmp, STRING_CTE("idnum")), compare_by_t ) vector_employee_sort_fo(emps, compare_by_as_interface(cmp)); printf("Employees sorted by idnum are: "); vector_employee_out_str(stdout, emps); M_LET( (cmp, STRING_CTE("name")), compare_by_t ) vector_employee_sort_fo(emps, compare_by_as_interface(cmp)); printf("\nEmployees sorted by name are: "); vector_employee_out_str(stdout, emps); printf("\n"); } return 0; }
PS: Et M*LIB fonctionne avec MS Visual C++ 2019 (modulo encore quelques compiler errors sur quelques fonctionnalités)

29

Par curiosité, cette bibliothèque est utilisée dans ton boulot, ou bien tu sais s'il y a des gens qui s'en servent ? (je vois qu'elle a pas mal de stars sur GitHub, et surtout que tu as l'air d'y avoir passé un temps considérable !)

Félicitations pour la longévité de la maintenance en tout cas hehe
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

30

Il y a plusieurs personnes qui s'en servent. Déjà il y a les bugs reports où on sent bien que le gars l'utilise dans un cas bien précis. Ensuite, il y a les clones automatiques à chaque push sur le dépot qui sent bon l'intégration continue.
Mais je n'ai aucun nom de projet à te donner.