From: mquinson Date: Thu, 8 Oct 2009 14:47:18 +0000 (+0000) Subject: New function: xbt_dynar_dopar(dynar,fun) X-Git-Tag: SVN~967 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/9118a040580a92c35006b5e55180d4be58904fbb New function: xbt_dynar_dopar(dynar,fun) maps a function over the dynar with one separate thread per value of the dynar. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@6747 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- diff --git a/ChangeLog b/ChangeLog index a532634a4e..8c41c61927 100644 --- a/ChangeLog +++ b/ChangeLog @@ -77,6 +77,9 @@ SimGrid (3.3.4) unstable; urgency=low * Update the start_time and finish_time of tasks on completion/failure * Bugfix: Remove task from state swags when destroyed + XBT: + * New function: xbt_dynar_dopar(dynar,fun) to map a function over the + dynar with one separate thread per value of the dynar. Bug fixes: * GTNetS wrappers should now be usable again (and betterly tested too) diff --git a/include/xbt/function_types.h b/include/xbt/function_types.h index 305d10a18b..291441db96 100644 --- a/include/xbt/function_types.h +++ b/include/xbt/function_types.h @@ -16,8 +16,9 @@ SG_BEGIN_DECL() - typedef void (*void_f_ppvoid_t) (void **); - typedef void (*void_f_pvoid_t) (void *); +typedef void (*void_f_ppvoid_t) (void **); +typedef void (*void_f_pvoid_t) (void *); +typedef void (*void_f_int_pvoid_t) (int,void *); typedef void *(*pvoid_f_void_t) (void); typedef void *(*pvoid_f_pvoid_t) (void *); typedef void (*void_f_void_t) (void); diff --git a/src/Makefile.am b/src/Makefile.am index bd30eaad57..a1545d4e50 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -153,7 +153,7 @@ XBT_SRC=\ xbt/set.c \ xbt/xbt_matrix.c \ \ - xbt/xbt_queue.c \ + xbt/xbt_queue.c xbt/xbt_synchro.c \ \ xbt/xbt_peer.c \ \ @@ -391,12 +391,12 @@ else noinst_PROGRAMS=testall TEST_CFILES=xbt/cunit.c xbt/ex.c \ xbt/dynar.c xbt/dict.c xbt/set.c xbt/swag.c \ - xbt/xbt_str.c xbt/xbt_sha.c \ - xbt/config.c + xbt/xbt_str.c xbt/xbt_strbuff.c xbt/xbt_sha.c \ + xbt/config.c xbt/xbt_synchro.c TEST_UNITS= @builddir@/cunit_unit.c @builddir@/ex_unit.c \ @builddir@/dynar_unit.c @builddir@/dict_unit.c @builddir@/set_unit.c @builddir@/swag_unit.c \ @builddir@/xbt_str_unit.c @builddir@/xbt_strbuff_unit.c @builddir@/xbt_sha_unit.c\ - @builddir@/config_unit.c + @builddir@/config_unit.c @builddir@/xbt_synchro_unit.c BUILT_SOURCES=../include/surf/simgrid_dtd.h surf/simgrid_dtd.c \ ../include/xbt/graphxml.h xbt/graphxml.c \ @@ -414,8 +414,7 @@ EXTRA_DIST+=$(testall_SOURCES) if MAINTAINER_MODE CLEANFILES=$(TEST_UNITS) -$(TEST_UNITS): xbt/cunit.c xbt/ex.c xbt/xbt_str.c xbt/xbt_strbuff.c xbt/xbt_sha.c\ - xbt/dynar.c xbt/dict.c xbt/set.c xbt/swag.c xbt/config.c +$(TEST_UNITS): $(TEST_CFILES) @top_srcdir@/tools/sg_unit_extractor.pl $^ @builddir@/simgrid_units_main.c: $(TEST_UNITS) diff --git a/src/xbt/xbt_synchro.c b/src/xbt/xbt_synchro.c new file mode 100644 index 0000000000..19de24c0d7 --- /dev/null +++ b/src/xbt/xbt_synchro.c @@ -0,0 +1,86 @@ +/* xbt_synchro -- advanced multithreaded features */ +/* Working on top of real threads in RL and of simulated processes in SG */ + +/* Copyright 2009 Da SimGrid Team. All right reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "xbt/sysdep.h" +#include "xbt/dynar.h" +#include "xbt/synchro.h" + +typedef struct { + xbt_dynar_t data; + int rank; + void_f_int_pvoid_t function; + xbt_thread_t worker; +} s_worker_data_t,*worker_data_t; + +static void worker_wait_n_free(void*w) { + worker_data_t worker=*(worker_data_t*)w; + xbt_thread_join(worker->worker); + xbt_free(worker); +} +static void worker_wrapper(void *w) { + worker_data_t me=(worker_data_t)w; + (*me->function)(me->rank,xbt_dynar_get_ptr(me->data,me->rank)); + xbt_thread_exit(); +} + +void xbt_dynar_dopar(xbt_dynar_t datas, void_f_int_pvoid_t function) { + xbt_dynar_t workers = xbt_dynar_new(sizeof(worker_data_t),worker_wait_n_free); + unsigned int cursor; + void *data; + /* Start all workers */ + xbt_dynar_foreach(datas,cursor,data){ + worker_data_t w = xbt_new0(s_worker_data_t,1); + w->data = datas; + w->function = function; + w->rank=cursor; + xbt_dynar_push(workers,&w); + w->worker = xbt_thread_create(NULL,worker_wrapper,w); + } + /* wait them all */ + xbt_dynar_free(&workers); +} + +#ifdef SIMGRID_TEST +#define NB_ELEM 50 +#include "xbt/synchro.h" + +XBT_TEST_SUITE("synchro", "Advanced synchronization mecanisms"); +XBT_LOG_EXTERNAL_CATEGORY(xbt_dyn); +XBT_LOG_DEFAULT_CATEGORY(xbt_dyn); + +static void add100(int rank,void *data) { + //INFO2("Thread%d: Add 100 to %d",rank,*(int*)data); + *(int*)data +=100; +} + +XBT_TEST_UNIT("dopar", test_dynar_dopar, "do parallel on dynars of integers") +{ + xbt_dynar_t d; + int i, cpt; + unsigned int cursor; + + xbt_test_add1("==== Push %d int, add 100 to each of them in parallel and check the results", NB_ELEM); + d = xbt_dynar_new(sizeof(int), NULL); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + xbt_dynar_push_as(d, int, cpt); /* This is faster (and possible only with scalars) */ + xbt_test_log2("Push %d, length=%lu", cpt, xbt_dynar_length(d)); + } + xbt_dynar_dopar(d,add100); + cpt = 100; + xbt_dynar_foreach(d, cursor, i) { + xbt_test_assert2(i == cpt, + "The retrieved value is not the expected one (%d!=%d)", + i, cpt); + cpt++; + } + xbt_dynar_free(&d); +} + +#endif /* SIMGRID_TEST */ + +