static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info, size_t info_len) { scpi_error_t error_value; char * info_ptr = info ? SCPIDEFINE_strndup(&context->error_info_heap, info, info_len) : NULL; SCPI_ERROR_SETVAL(&error_value, err, info_ptr); if (!fifo_add(&context->error_queue, &error_value)) { SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true); fifo_remove_last(&context->error_queue, &error_value); SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true); SCPI_ERROR_SETVAL(&error_value, SCPI_ERROR_QUEUE_OVERFLOW, NULL); fifo_add(&context->error_queue, &error_value); return FALSE; } return TRUE; }
void SCPIParser::SCPI_ErrorAddInternal( int16_t err) { /* * // FreeRTOS * xQueueSend((xQueueHandle)context.error_queue, &err, 0); */ /* basic FIFO */ fifo_add((fifo_t *)context.error_queue, err); }
static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { /* * // FreeRTOS * xQueueSend((xQueueHandle)context->error_queue, &err, 0); */ /* basic FIFO */ fifo_add((fifo_t *)context->error_queue, err); }
static void testFifo() { scpi_fifo_t fifo; fifo_init(&fifo); int16_t value; fifo.size = 4; #define TEST_FIFO_COUNT(n) \ do { \ fifo_count(&fifo, &value); \ CU_ASSERT_EQUAL(value, n); \ } while(0) \ TEST_FIFO_COUNT(0); CU_ASSERT_TRUE(fifo_add(&fifo, 1)); TEST_FIFO_COUNT(1); CU_ASSERT_TRUE(fifo_add(&fifo, 2)); TEST_FIFO_COUNT(2); CU_ASSERT_TRUE(fifo_add(&fifo, 3)); TEST_FIFO_COUNT(3); CU_ASSERT_TRUE(fifo_add(&fifo, 4)); TEST_FIFO_COUNT(4); CU_ASSERT_TRUE(fifo_add(&fifo, 1)); TEST_FIFO_COUNT(4); CU_ASSERT_EQUAL(fifo.data[0], 1); CU_ASSERT_EQUAL(fifo.data[1], 2); CU_ASSERT_EQUAL(fifo.data[2], 3); CU_ASSERT_EQUAL(fifo.data[3], 4); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); CU_ASSERT_EQUAL(value, 2); TEST_FIFO_COUNT(3); CU_ASSERT_TRUE(fifo_add(&fifo, 5)); TEST_FIFO_COUNT(4); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); CU_ASSERT_EQUAL(value, 3); TEST_FIFO_COUNT(3); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); CU_ASSERT_EQUAL(value, 4); TEST_FIFO_COUNT(2); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); CU_ASSERT_EQUAL(value, 1); TEST_FIFO_COUNT(1); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); CU_ASSERT_EQUAL(value, 5); TEST_FIFO_COUNT(0); CU_ASSERT_FALSE(fifo_remove(&fifo, &value)); TEST_FIFO_COUNT(0); }
static void finalize_phase_one(workqueue_t *wq) { int startslot, i; /* * wip slots are cleared out only when maxbatchsz td's have been merged * into them. We're not guaranteed that the number of files we're * merging is a multiple of maxbatchsz, so there will be some partial * groups in the wip array. Move them to the done queue in batch ID * order, starting with the slot containing the next batch that would * have been placed on the done queue, followed by the others. * One thread will be doing this while the others wait at the barrier * back in worker_thread(), so we don't need to worry about pesky things * like locks. */ for (startslot = -1, i = 0; i < wq->wq_nwipslots; i++) { if (wq->wq_wip[i].wip_batchid == wq->wq_lastdonebatch + 1) { startslot = i; break; } } assert(startslot != -1); for (i = startslot; i < startslot + wq->wq_nwipslots; i++) { int slotnum = i % wq->wq_nwipslots; wip_t *wipslot = &wq->wq_wip[slotnum]; if (wipslot->wip_td != NULL) { debug(2, "clearing slot %d (%d) (saving %d)\n", slotnum, i, wipslot->wip_nmerged); } else debug(2, "clearing slot %d (%d)\n", slotnum, i); if (wipslot->wip_td != NULL) { fifo_add(wq->wq_donequeue, wipslot->wip_td); wq->wq_wip[slotnum].wip_td = NULL; } } wq->wq_lastdonebatch = wq->wq_next_batchid++; debug(2, "phase one done: donequeue has %d items\n", fifo_len(wq->wq_donequeue)); }
int main (void) { long long put = 0, get = 0; char str[32]; fifo_t fifo = fifo_create(); while (1) { int i; int block = random() % BLOCK; for (i = 0; i < block; i++) { if ((put & DISPLAY) == DISPLAY) { printf("%lli... (size %lli)\r", put, put - get); fflush(stdout); } sprintf(str, "%lli", put++); fifo_add(fifo, str); } block = random() % BLOCK; for (i = 0; i < block; i++) { char* out = fifo_getdel(fifo); if (!out) break; long long test = atoll(out); if (test != get) { fprintf(stderr, "error, getting %lli (%s), should be %lli\n", test, out, get); exit(1); } get++; free(out); } } return 0; }
static void wip_save_work(workqueue_t *wq, wip_t *slot, int slotnum) { pthread_mutex_lock(&wq->wq_donequeue_lock); while (wq->wq_lastdonebatch + 1 < slot->wip_batchid) pthread_cond_wait(&slot->wip_cv, &wq->wq_donequeue_lock); assert(wq->wq_lastdonebatch + 1 == slot->wip_batchid); fifo_add(wq->wq_donequeue, slot->wip_td); wq->wq_lastdonebatch++; pthread_cond_signal(&wq->wq_wip[(slotnum + 1) % wq->wq_nwipslots].wip_cv); /* reset the slot for next use */ slot->wip_td = NULL; slot->wip_batchid = wq->wq_next_batchid++; pthread_mutex_unlock(&wq->wq_donequeue_lock); }
status_t fifo_write_signal(fifo p, void *data) { status_t rc; assert(p != NULL); assert(data != NULL); if (!fifo_lock(p)) return failure; if (!fifo_add(p, data)) { fifo_unlock(p); return failure; } rc = fifo_signal(p); fifo_unlock(p); return rc; }
/* * Pass a tdata_t tree, built from an input file, off to the work queue for * consumption by worker threads. */ static int merge_ctf_cb(tdata_t *td, char *name, void *arg) { workqueue_t *wq = arg; debug(3, "Adding tdata %p for processing\n", (void *)td); pthread_mutex_lock(&wq->wq_queue_lock); while (fifo_len(wq->wq_queue) > wq->wq_ithrottle) { debug(2, "Throttling input (len = %d, throttle = %d)\n", fifo_len(wq->wq_queue), wq->wq_ithrottle); pthread_cond_wait(&wq->wq_work_removed, &wq->wq_queue_lock); } fifo_add(wq->wq_queue, td); debug(1, "Thread %d announcing %s\n", pthread_self(), name); pthread_cond_broadcast(&wq->wq_work_avail); pthread_mutex_unlock(&wq->wq_queue_lock); return (1); }
static void usb_ctrl_msg(struct st5481_adapter *adapter, u8 request, u8 requesttype, u16 value, u16 index, ctrl_complete_t complete, void *context) { struct st5481_ctrl *ctrl = &adapter->ctrl; int w_index; struct ctrl_msg *ctrl_msg; if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) { WARNING("control msg FIFO full"); return; } ctrl_msg = &ctrl->msg_fifo.data[w_index]; ctrl_msg->dr.bRequestType = requesttype; ctrl_msg->dr.bRequest = request; ctrl_msg->dr.wValue = cpu_to_le16p(&value); ctrl_msg->dr.wIndex = cpu_to_le16p(&index); ctrl_msg->dr.wLength = 0; ctrl_msg->complete = complete; ctrl_msg->context = context; usb_next_ctrl_msg(ctrl->urb, adapter); }
static void worker_runphase2(workqueue_t *wq) { tdata_t *pow1, *pow2; int batchid; for (;;) { pthread_mutex_lock(&wq->wq_queue_lock); if (wq->wq_ninqueue == 1) { pthread_cond_broadcast(&wq->wq_work_avail); pthread_mutex_unlock(&wq->wq_queue_lock); debug(2, "%d: entering p2 completion barrier\n", pthread_self()); if (barrier_wait(&wq->wq_bar1)) { pthread_mutex_lock(&wq->wq_queue_lock); wq->wq_alldone = 1; pthread_cond_signal(&wq->wq_alldone_cv); pthread_mutex_unlock(&wq->wq_queue_lock); } return; } if (fifo_len(wq->wq_queue) < 2) { pthread_cond_wait(&wq->wq_work_avail, &wq->wq_queue_lock); pthread_mutex_unlock(&wq->wq_queue_lock); continue; } /* there's work to be done! */ pow1 = fifo_remove(wq->wq_queue); pow2 = fifo_remove(wq->wq_queue); wq->wq_ninqueue -= 2; batchid = wq->wq_next_batchid++; pthread_mutex_unlock(&wq->wq_queue_lock); debug(2, "%d: merging %p into %p\n", pthread_self(), (void *)pow1, (void *)pow2); merge_into_master(pow1, pow2, NULL, 0); tdata_free(pow1); /* * merging is complete. place at the tail of the queue in * proper order. */ pthread_mutex_lock(&wq->wq_queue_lock); while (wq->wq_lastdonebatch + 1 != batchid) { pthread_cond_wait(&wq->wq_done_cv, &wq->wq_queue_lock); } wq->wq_lastdonebatch = batchid; fifo_add(wq->wq_queue, pow2); debug(2, "%d: added %p to queue, len now %d, ninqueue %d\n", pthread_self(), (void *)pow2, fifo_len(wq->wq_queue), wq->wq_ninqueue); pthread_cond_broadcast(&wq->wq_done_cv); pthread_cond_signal(&wq->wq_work_avail); pthread_mutex_unlock(&wq->wq_queue_lock); } }
static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { if (!fifo_add(&context->error_queue, err)) { fifo_remove_last(&context->error_queue, NULL); fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); } }
int main(void) { fifo f; size_t i, nelem; status_t rc; char dummydata[1000] = "Hello"; clock_t stop, start; double duration; nelem = 1*1000*1000; f = fifo_new(nelem); #if 1 /* Fill the fifo completely */ start = clock(); for (i = 0; i < nelem; i++) { rc = fifo_add(f, dummydata); assert(rc != 0); } stop = clock(); duration = (stop - start) * 1.0 / CLOCKS_PER_SEC; printf("%s: Added %lu elements in %f seconds\n", __FILE__, (unsigned long)nelem, duration); assert(fifo_nelem(f) == nelem); /* Test fifo_peek() */ for (i = 0; i < nelem; i++) { const char *s = fifo_peek(f, i); /* Stupid workaround for gcc 4.0.2 optimization in conjunction with assert() */ int xi; xi = (s != NULL); assert(xi); xi = (strcmp(s, dummydata) == 0); assert(xi); } /* Add a new one, this should fail */ assert(fifo_add(f, dummydata) == 0); /* Now read two and then add one. That should be possible */ assert(fifo_get(f)); assert(fifo_get(f)); assert(fifo_nelem(f) == nelem - 2); assert(fifo_add(f, dummydata) != 0); assert(fifo_nelem(f) == nelem - 1); /* Test fifo_peek() */ for (i = 0; i < fifo_nelem(f); i++) { const char *s = fifo_peek(f, i); int xi; xi = (s != NULL); assert(xi); xi = (strcmp(s, dummydata) == 0); assert(xi); } /* The first should be OK, the next must fail */ assert(fifo_add(f, dummydata) != 0); assert(fifo_nelem(f) == nelem); assert(fifo_add(f, dummydata) == 0); assert(fifo_nelem(f) == nelem); start = clock(); for (i = 0; i < nelem; i++) { char *x = fifo_get(f); (void)x; } stop = clock(); duration = (stop - start) * 1.0 / CLOCKS_PER_SEC; printf("%s: Got %lu elements in %f seconds\n", __FILE__, (unsigned long)nelem, duration); #endif /* Now check signalling and wait for data. * We start two threads, a reader and a writer. * The writer writes n times to the fifo and the reader * prints the data. * This thread joins the writer and calls fifo_wake() when * the writer is done, to stop the reader thread in a controlled * manner. */ { pthread_t w, r; pthread_create(&r, NULL, reader, f); pthread_create(&w, NULL, writer, f); pthread_join(w, NULL); if (!fifo_wake(f)) exit(EXIT_FAILURE); pthread_join(r, NULL); } fifo_free(f, free); return 0; }
void cis_run (void) { int temp_int = 0, temp_int2 = 0; int i = 0, r, w; int eventcount = 0; connection *read_events[__MAXFDS__]; connection *write_events[__MAXFDS__]; fifo_root *global_recvq = NULL; linklist_iter *reaper_iter = NULL; connection *temp = NULL; char *line; int patience = 250; reactor_running = true; global_recvq = fifo_create(); /* main loop */ for(;reactor_running;) { /** Grab some socket events to play with */ eventcount = socketengine->wait(read_events, write_events, patience); r = w = 0; /** Run through the existing connections looking for data to read */ for(i = 0; (r+w) < eventcount; i++) { if (read_events[i] != NULL) { r++; temp_int = read_events[i]->recvq->queue_size; conn_read_to_recvq(read_events[i]); if ((read_events[i]->recvq->queue_size > temp_int) && ((equal_fairness == 0) || (temp_int == 0))) fifo_add(global_recvq, read_events[i]); /* Don't wait for data! too much to do! */ patience = 0; } if (write_events[i] != NULL) { w++; if (write_events[i]->state.connecting == 1) { assert(getsockopt(write_events[i]->fd, SOL_SOCKET, SO_ERROR, &temp_int, &temp_int2) == 0); if (temp_int == 0) { write_events[i]->connected(write_events[i]); write_events[i]->state.connecting = 0; } else { write_events[i]->connect_failed(write_events[i], temp_int); write_events[i]->state.remote_closed = 1; write_events[i]->state.local_read_shutdown = 1; write_events[i]->state.local_write_shutdown = 1; socketengine->del(write_events[i]); cis_reap_connection(write_events[i]); } } else conn_send_from_sendq(write_events[i]); } } // foreach (event) /** Process some of the readq */ if (global_recvq->members > 0) { for (i = 0; i <= 20; i++) { temp = fifo_pop(global_recvq); if (temp == NULL) { /* We seem to be out of connections to process... Have more patience waiting for new data ...*/ patience = 250; break; } if ((temp->state.local_read_shutdown == 0)&&(temp->recvq->queue_size > 0)) { /* Local dead connections don't get processed ... remote dead ones -do- (since they died after sending this...) */ if (temp->callback_read) temp->callback_read(temp); else buffer_empty(temp->recvq); /* If it doesn't have any more messages left, nuke it from the queue... */ if (temp->recvq->queue_size == 0) fifo_del(global_recvq, temp); else { if (equal_fairness == 1) { fifo_del(global_recvq, temp); fifo_add(global_recvq, temp); } else { /* We shove it back on the end of the queue, * just in case there are insufficent instances to cover the buffer content. * * While this behaviour won't break the code it isn't true first come first served, * and it will have a performance impact. * * TODO: It would be nice to have an alternative ... * possibly making conn_read_to_recvq return a line count to allow multiple additions */ fifo_add(global_recvq, temp); } } if (global_recvq->members == 0) { patience = 250; /* Nothing to do, so I don't mind wait a while */ } break; } else { /* So this is either locally dead, or has no recvq ... both could happen, but ignore it either way */ if (temp->recvq->queue_size > 0) { /* Must be locally dead but with a recvq still ... this shouldn't be possible? */ buffer_empty(temp->recvq); } /* In any case, if we're ignoring it, might as well remove it completely ... */ fifo_del(global_recvq, temp); /* Since we didn't do much with this one, we'll try another pass... */ i--; } } } /** Attempt to reap connections... */ reaper_iter = linklist_iter_create(reaper_list); while (temp = linklist_iter_next(reaper_iter)) { /* Has this connection reached the end of it's life? */ if (((temp->state.remote_closed == 1) && (temp->recvq->queue_size == 0)) || (temp->state.local_read_shutdown == 1) && (temp->sendq->queue_size == 0)) { /* Remove it from any relevant queues... */ linklist_iter_del(reaper_iter); fifo_del(global_recvq,temp); /* Make sure it's all closed down... */ temp->state.local_write_shutdown = 1; temp->close(temp); /* Free the important stuff.... */ if (temp->recvq) buffer_free(temp->recvq); if (temp->sendq) buffer_free(temp->sendq); sfree(temp); } } linklist_iter_free(reaper_iter); timers_process(); } return; }
int main(int argc, char **argv) { int **A = NULL; int **N = NULL; int **PLC = NULL; int *GL = NULL; FILE *fichier = NULL; int nbPlaces=0, nbLevels=0; int *listePositif = NULL; int *listeNegatif = NULL; int *listeAVisiter = NULL; int i, j, k, buf; /* * Récupération de la Matrice */ /* Ouverture du fichier */ fichier = fopen("input.data", "r"); if(fichier == NULL) fprintf(stderr,"Erreur : Ouverture du fichier impossible :'(\n"); /* Récupération du nombre de zones */ fscanf(fichier, "%d", &nbPlaces); /* Allocation de la mémoire pour contenir la matrice */ A = (int**) malloc(sizeof(int*)*nbPlaces); for(i=0; i<nbPlaces; i++) A[i] = (int*) malloc(sizeof(int)*nbPlaces); /* Récupération des données et stoquage dans la matrice */ for(i=0; i<nbPlaces; i++) for(j=0; j<nbPlaces; j++) fscanf(fichier, "%d", &A[i][j]); /* Fermeture du fichier */ fclose(fichier); /* * Recherche des composants fortement connectés */ /* Allocation de la mémoire pour enregistrer les niveaux et pour contenir des tableaux temporaires */ GL = (int*) malloc(sizeof(int)*nbPlaces); listePositif = (int*) malloc(sizeof(int)*nbPlaces); listeNegatif = (int*) malloc(sizeof(int)*nbPlaces); listeAVisiter = (int*) malloc(sizeof(int)*nbPlaces); for(i=0; i<nbPlaces; i++) { listePositif[i] = -1; listeNegatif[i] = -1; listeAVisiter[i] = -1; GL[i] = -1; } /* On va effectuer la recherche depuis chaque point du graph (sauf si elle est déjà dans un level) */ for(i=0; i<nbPlaces; i++) { printf("=====================================\n Research starting from the place %2d \n=====================================\n", i); if(GL[i] == -1) { /* Remplissage de la liste positive */ fifo_add(listeAVisiter, nbPlaces, i); while(fifo_isEmpty(listeAVisiter, nbPlaces) == 0) { buf = fifo_pop(listeAVisiter, nbPlaces); fifo_add(listePositif, nbPlaces, buf); for(j=0;j<nbPlaces;j++) if(A[buf][j] == 1) { if(fifo_search(listePositif, nbPlaces, j) == -1) { fifo_add(listeAVisiter, nbPlaces, j); } } } printf("--> Places in the '+' list :\n "); for(j=0;j<fifo_count(listePositif, nbPlaces);j++) printf("%2d ", listePositif[j]); printf("\n"); /* Remplissage de la liste negative */ fifo_add(listeAVisiter, nbPlaces, i); while(fifo_isEmpty(listeAVisiter, nbPlaces) == 0) { buf = fifo_pop(listeAVisiter, nbPlaces); fifo_add(listeNegatif, nbPlaces, buf); for(j=0;j<nbPlaces;j++) if(A[j][buf] == 1 && fifo_search(listeNegatif, nbPlaces, j) == -1) fifo_add(listeAVisiter, nbPlaces, j); } printf("--> Places in the '-' list :\n "); for(j=0;j<fifo_count(listeNegatif, nbPlaces);j++) printf("%2d ", listeNegatif[j]); printf("\n"); /* Recherche d'elements presents dans les deux listes */ printf("--> Intersection :\n "); for(j=0;j<nbPlaces;j++) { for(k=0;k<nbPlaces;k++) if(listePositif[j] == listeNegatif[k] && listePositif[j] != -1) { GL[listePositif[j]] = nbLevels; printf("%2d ", listePositif[j]); } } printf("\n--> Saving them in the new level n°%2d\n\n", nbLevels); nbLevels++; /* Vidage des deux listes */ for(j=0;j<nbPlaces;j++) { listePositif[j] = -1; listeNegatif[j] = -1; } } else printf("--> Already in the level n°%2d\n\n", GL[i]); } printf("\n\n\n========\n Levels\n========\n"); for(i=0;i<nbPlaces;i++) printf("--> Place %2d is in the Level n°%2d\n", i, GL[i]); printf("\n"); for(i=0;i<nbLevels;i++) { k = 0; printf("{"); for(j=0; j<nbPlaces; j++) if(GL[j] == i) { if(k == 1) printf(";"); else k = 1; printf("%2d", j); } printf(" } "); } printf("\n"); /* * Création de la matrice réduite */ /* Allocation et initialisation de la matrice réduite */ N = (int**) malloc(sizeof(int*)*nbLevels); for(i=0; i<nbLevels; i++) { N[i] = (int*) malloc(sizeof(int)*nbLevels); for(j=0; j<nbLevels; j++) N[i][j] = 0; } /* Remplissage de la-dite matrice */ for(i=0; i<nbPlaces; i++) { for(j=0; j<nbPlaces; j++) { if(A[i][j] == 1) { N[GL[i]][GL[j]]++; } } } printf("\n================\n Reduced Matrix\n================\n"); for(i=0; i<nbLevels; i++) { for(j=0; j<nbLevels; j++) printf("%2d ", N[i][j]); printf("\n"); } /* * Calcul du plus long chemin entre le premier et le dernier niveau */ /* Allocation et Reallocation d'une partie de mémoire précédement utilisé et mise à zéro */ listeAVisiter = (int*) realloc(listeAVisiter, sizeof(int)*nbLevels); PLC = (int**) malloc(sizeof(int*)*nbLevels); for(i=0; i<nbLevels; i++) { listeAVisiter[i] = -1; PLC[i] = (int*) malloc(sizeof(int)*nbLevels); for(j=0; j<nbLevels; j++) PLC[i][j] = -1; } /* Application de l'algo de calcul du plus long chemin */ fifo_add(listeAVisiter, nbLevels, GL[0]); while(fifo_isEmpty(listeAVisiter, nbLevels) == 0) { buf = fifo_pop(listeAVisiter, nbLevels); for(i=0; i<nbLevels; i++) if(N[buf][i] >= 1 && buf != i) { if(fifo_count(PLC[buf], nbLevels)+1 > fifo_count(PLC[i], nbLevels)) { for(j=0; j<nbLevels; j++) PLC[i][j] = PLC[buf][j]; fifo_add(PLC[i], nbLevels, buf); fifo_add(listeAVisiter, nbLevels, i); } } } printf("\n==============\n Longest path\n==============\n"); if(fifo_isEmpty(PLC[GL[nbPlaces-1]], nbLevels) == 0) k = GL[nbPlaces-1]; else { k = 0; for(i=1; i<nbLevels; i++) if(fifo_count(PLC[i], nbLevels) > fifo_count(PLC[k], nbLevels)) k = i; } printf("--> { "); for(i=0; i<nbLevels && PLC[k][i] != -1; i++) { printf("%d ; ", PLC[k][i]); } printf("%d }\n", k); /* * Generation d'une image du graph (idée par Jérome BOURSIER, merci à lui !) */ /* Création du fichier */ fichier = fopen("graph.dot","w"); fprintf(fichier, "digraph graphAG44\n{\n"); /* Enregistrement des Niveaux */ srand(time(NULL)); for(i=0; i<nbLevels; i++) { fprintf(fichier, "\tsubgraph sub%d\n\t{\n\t\tnode [style=filled,color=\"#%2x%2x%2x\"];\n", i,rand()%225, rand()%225, rand()%225); for(j=0; j<nbPlaces; j++) if(GL[j] == i) fprintf(fichier, "\t\t%d;\n", j); fprintf(fichier, "\t}\n\n"); } /* Enregistrement des Places */ for(i=0; i<nbPlaces; i++) for(j=0; j<nbPlaces; j++) if(A[i][j] == 1) fprintf(fichier, "\t%d -> %d;\n", i, j); fprintf(fichier, "}"); fclose(fichier); /* Appel au programme dot pour generer l'image a partir du fichier */ if(fork() == 0) execlp("dot", "dot", "-Tpng", "graph.dot", "-o", "graph.png", NULL); if(fork() == 0) execlp("eog", "eog", "graph.png", NULL); /* * Libération de la mémoire allouée */ for(i=0; i<nbPlaces; i++) free(A[i]); free(A); for(i=0; i<nbLevels; i++) { free(N[i]); free(PLC[i]); } free(N); free(PLC); free(GL); free(listePositif); free(listeNegatif); free(listeAVisiter); return 0; }