# HG changeset patch # User Thinker K.F. Li # Date 1227015750 -28800 # Node ID 54fdc2a65242dd8d2443ecd3f0eaf36c530d968d # Parent 18f8c3126cdba7dd09f2f84d96cb22b10ff3c84b Remove factory from observer APIs. - Save factory that used to new a subject as subject's attribute. - Get factory from subject himself instead of passing as an argument. - It make API of observer more simple and clean. diff -r 18f8c3126cdb -r 54fdc2a65242 examples/calculator/main.c --- a/examples/calculator/main.c Tue Nov 18 13:55:09 2008 +0800 +++ b/examples/calculator/main.c Tue Nov 18 21:42:30 2008 +0800 @@ -151,22 +151,18 @@ static void setup_observers(calc_data_t *calc_data) { calculator_scr_t *calculator_scr; - ob_factory_t *factory; subject_t *subject; coord_t *coord; - redraw_man_t *rdman; int off; int i; calculator_scr = calc_data->code; - rdman = X_MB_rdman(calc_data->rt); - factory = rdman_get_ob_factory(rdman); for(i = 0; i < 16; i++) { off = tgt_list[i].off; coord = OFF2TYPE(calculator_scr, off, coord_t *); subject = coord_get_mouse_event(coord); - subject_add_observer(factory, subject, buttons_handler, calc_data); + subject_add_observer(subject, buttons_handler, calc_data); } } diff -r 18f8c3126cdb -r 54fdc2a65242 examples/svg2code_ex/main.c --- a/examples/svg2code_ex/main.c Tue Nov 18 13:55:09 2008 +0800 +++ b/examples/svg2code_ex/main.c Tue Nov 18 21:42:30 2008 +0800 @@ -48,7 +48,6 @@ X_MB_runtime_t *rt; redraw_man_t *rdman; svg2code_ex_t *svg2code; - ob_factory_t *factory; subject_t *subject; ex_rt_t ex_rt; @@ -64,18 +63,14 @@ svg2code = svg2code_ex_new(rdman, rdman->root_coord); /* - * Get observer factory - */ - factory = rdman_get_ob_factory(rdman); - /* * Register observers to subjects of events for objects. */ subject = coord_get_mouse_event(svg2code->file_button); ex_rt.rt = rt; ex_rt.code = svg2code; - subject_add_observer(factory, subject, file_button_handler, &ex_rt); + subject_add_observer(subject, file_button_handler, &ex_rt); subject = coord_get_mouse_event(svg2code->file_menu); - subject_add_observer(factory, subject, file_menu_handler, &ex_rt); + subject_add_observer(subject, file_menu_handler, &ex_rt); /* * Start handle connections, includes one to X server. diff -r 18f8c3126cdb -r 54fdc2a65242 examples/tank/tank_main.c --- a/examples/tank/tank_main.c Tue Nov 18 13:55:09 2008 +0800 +++ b/examples/tank/tank_main.c Tue Nov 18 21:42:30 2008 +0800 @@ -266,8 +266,7 @@ /* Clean program when it is completed. */ comp_sub = mb_progm_get_complete(progm); - subject_add_observer(factory, comp_sub, - clean_tank_progm_handler, tank); + subject_add_observer(comp_sub, clean_tank_progm_handler, tank); get_now(&now); mb_progm_start(progm, tman, &now); @@ -492,7 +491,6 @@ mb_action_t *act; mb_timeval_t start, playing; mb_timeval_t now, next; - ob_factory_t *factory; mb_tman_t *tman; subject_t *subject; static int map_xy_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; @@ -546,8 +544,7 @@ /*! \todo Simplify the procdure of using observer pattern. */ subject = mb_progm_get_complete(progm); - factory = rdman_get_ob_factory(rdman); - subject_add_observer(factory, subject, bullet_go_out_map, tank); + subject_add_observer(subject, bullet_go_out_map, tank); get_now(&now); MB_TIMEVAL_CP(&bullet->start_time, &now); @@ -614,16 +611,14 @@ X_MB_runtime_t *mb_rt; subject_t *kbevents; redraw_man_t *rdman; - ob_factory_t *factory; mb_rt = tank_rt->mb_rt; kbevents = X_MB_kbevents(mb_rt); rdman = X_MB_rdman(mb_rt); - factory = rdman_get_ob_factory(rdman); tank_rt->kb_observer = - subject_add_observer(factory, kbevents, keyboard_handler, tank_rt); + subject_add_observer(kbevents, keyboard_handler, tank_rt); } /*! \brief Make coord objects to decorate elfs (tanks). diff -r 18f8c3126cdb -r 54fdc2a65242 include/mb_animate.h --- a/include/mb_animate.h Tue Nov 18 13:55:09 2008 +0800 +++ b/include/mb_animate.h Tue Nov 18 21:42:30 2008 +0800 @@ -44,6 +44,7 @@ mb_timeval_t *now); extern void mb_progm_abort(mb_progm_t *progm); extern subject_t *mb_progm_get_complete(mb_progm_t *progm); +extern void mb_progm_free_completed(mb_progm_t *progm); /*! \defgroup ani_actions Animation Actions * @{ diff -r 18f8c3126cdb -r 54fdc2a65242 include/mb_observer.h --- a/include/mb_observer.h Tue Nov 18 13:55:09 2008 +0800 +++ b/include/mb_observer.h Tue Nov 18 21:42:30 2008 +0800 @@ -35,6 +35,7 @@ int obj_type; /*!< \brief type of object (a.k.a. OBJT_*). */ void *obj; /*!< \brief the object this subject for. */ int flags; + ob_factory_t *factory; STAILQ(observer_t) observers; }; /*! \brief Flag that make a subject to propagate events to parents. */ @@ -77,14 +78,11 @@ extern subject_t *subject_new(ob_factory_t *factory, void *obj, int obj_type); -extern void subject_free(ob_factory_t *factory, subject_t *subject); -extern void subject_notify(ob_factory_t *factory, - subject_t *subject, event_t *evt); -extern observer_t *subject_add_observer(ob_factory_t *factory, - subject_t *subject, +extern void subject_free(subject_t *subject); +extern void subject_notify(subject_t *subject, event_t *evt); +extern observer_t *subject_add_observer(subject_t *subject, evt_handler hdr, void *arg); -extern void subject_remove_observer(ob_factory_t *factory, - subject_t *subject, +extern void subject_remove_observer(subject_t *subject, observer_t *observer); diff -r 18f8c3126cdb -r 54fdc2a65242 src/X_supp.c --- a/src/X_supp.c Tue Nov 18 13:55:09 2008 +0800 +++ b/src/X_supp.c Tue Nov 18 21:42:30 2008 +0800 @@ -80,13 +80,14 @@ kbinfo->kbevents = subject_new(factory, kbinfo, OBJT_KB); if(kbinfo->kbevents == NULL) return ERR; + /*! \todo Make sure ob_factory is still need. */ kbinfo->ob_factory = factory; return OK; } static void X_kb_destroy(X_kb_info_t *kbinfo) { - subject_free(kbinfo->ob_factory, kbinfo->kbevents); + subject_free(kbinfo->kbevents); XFree(kbinfo->syms); } @@ -107,7 +108,7 @@ event.keycode = code; event.sym = sym; - subject_notify(kbinfo->ob_factory, kbinfo->kbevents, &event.event); + subject_notify(kbinfo->kbevents, &event.event); } /* @} */ @@ -151,7 +152,6 @@ unsigned int button) { mouse_event_t mouse_event; subject_t *subject; - ob_factory_t *factory; mouse_event.event.type = etype; mouse_event.x = x; @@ -160,9 +160,8 @@ mouse_event.button = button; subject = sh_get_mouse_event_subject(shape); - factory = rdman_get_ob_factory(rdman); - subject_notify(factory, subject, (event_t *)&mouse_event); + subject_notify(subject, (event_t *)&mouse_event); } /*! \brief Dispatch all X events in the queue. diff -r 18f8c3126cdb -r 54fdc2a65242 src/animate.c --- a/src/animate.c Tue Nov 18 13:55:09 2008 +0800 +++ b/src/animate.c Tue Nov 18 21:42:30 2008 +0800 @@ -140,9 +140,6 @@ int n_words; mb_word_t *word; mb_action_t *cur_act; -#ifndef UNITTEST - ob_factory_t *factory; -#endif /* UNITTEST */ int i; n_words = progm->n_words; @@ -157,8 +154,7 @@ } #ifndef UNITTEST - factory = rdman_get_ob_factory(progm->rdman); - subject_free(factory, progm->complete); + subject_free(progm->complete); #endif /* UNITTEST */ free(progm); @@ -238,7 +234,6 @@ #ifndef UNITTEST /*! \todo Leverage aspective programming to prevent problem of unittest. */ - ob_factory_t *factory; mb_progm_complete_t comp_evt; #endif /* UNITTEST */ mb_timeval_t next_tmo; @@ -294,11 +289,10 @@ } else { /* Make program to complete. */ #ifndef UNITTEST - factory = rdman_get_ob_factory(progm->rdman); comp_evt.event.type = EVT_PROGM_COMPLETE; comp_evt.event.tgt = comp_evt.event.cur_tgt = progm->complete; comp_evt.progm = progm; - subject_notify(factory, progm->complete, &comp_evt.event); + subject_notify(progm->complete, &comp_evt.event); #endif /* UNITTEST */ progm->cur_timer = NULL; } @@ -352,6 +346,20 @@ return progm->complete; } +static void _free_completed_hdlr(event_t *event, void *arg) { + mb_progm_t *progm = (mb_progm_t *)arg; + + mb_progm_free(progm); +} + +/*! \brief The program should be freed after completed. */ +void mb_progm_free_completed(mb_progm_t *progm) { + subject_t *complete; + + complete = mb_progm_get_complete(progm); + subject_add_observer(complete, _free_completed_hdlr, progm); +} + #ifdef UNITTEST #include diff -r 18f8c3126cdb -r 54fdc2a65242 src/observer.c --- a/src/observer.c Tue Nov 18 13:55:09 2008 +0800 +++ b/src/observer.c Tue Nov 18 21:42:30 2008 +0800 @@ -19,13 +19,16 @@ subject->flags = 0; STAILQ_INIT(subject->observers); + subject->factory = factory; + return subject; } /*! * \todo Keep ob_factory following subject objects. */ -void subject_free(ob_factory_t *factory, subject_t *subject) { +void subject_free(subject_t *subject) { + ob_factory_t *factory = subject->factory; observer_t *observer; ASSERT(!(subject->flags & SUBF_FREE)); @@ -45,7 +48,8 @@ } -void subject_notify(ob_factory_t *factory, subject_t *subject, event_t *evt) { +void subject_notify(subject_t *subject, event_t *evt) { + ob_factory_t *factory = subject->factory; observer_t *observer; evt->tgt = subject; @@ -66,7 +70,7 @@ subject->flags &= ~SUBF_BUSY; if(subject->flags & SUBF_FREE) - subject_free(factory, subject); + subject_free(subject); if(subject->flags & SUBF_STOP_PROPAGATE) break; @@ -76,9 +80,9 @@ } -observer_t *subject_add_observer(ob_factory_t *factory, - subject_t *subject, +observer_t *subject_add_observer(subject_t *subject, evt_handler hdr, void *arg) { + ob_factory_t *factory = subject->factory; observer_t *observer; observer = factory->observer_alloc(factory); @@ -92,9 +96,10 @@ return observer; } -void subject_remove_observer(ob_factory_t *factory, - subject_t *subject, +void subject_remove_observer(subject_t *subject, observer_t *observer) { + ob_factory_t *factory = subject->factory; + STAILQ_REMOVE(subject->observers, observer_t, next, observer); factory->observer_free(factory, observer); } @@ -154,20 +159,18 @@ subject = subject_new(&test_factory, NULL, 0); subject->flags |= SUBF_STOP_PROPAGATE; - observer[0] = subject_add_observer(&test_factory, subject, - handler, &cnt); - observer[1] = subject_add_observer(&test_factory, subject, - handler, &cnt); + observer[0] = subject_add_observer(subject, handler, &cnt); + observer[1] = subject_add_observer(subject, handler, &cnt); evt.type = EVT_MOUSE_OUT; evt.tgt = NULL; evt.cur_tgt = NULL; - subject_notify(&test_factory, subject, &evt); + subject_notify(subject, &evt); CU_ASSERT(cnt == 2); - subject_remove_observer(&test_factory, subject, observer[0]); - subject_remove_observer(&test_factory, subject, observer[1]); - subject_free(&test_factory, subject); + subject_remove_observer(subject, observer[0]); + subject_remove_observer(subject, observer[1]); + subject_free(subject); } CU_pSuite get_observer_suite(void) { diff -r 18f8c3126cdb -r 54fdc2a65242 src/redraw_man.c --- a/src/redraw_man.c Tue Nov 18 13:55:09 2008 +0800 +++ b/src/redraw_man.c Tue Nov 18 21:42:30 2008 +0800 @@ -445,7 +445,7 @@ geo_detach_coord(geo, shape->coord); sh_detach_coord(shape); sh_detach_geo(shape); - subject_free(&rdman->ob_factory, geo->mouse_event); + subject_free(geo->mouse_event); elmpool_elm_free(rdman->geo_pool, geo); } STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, shape); @@ -547,60 +547,66 @@ return coord; } +static int rdman_coord_free_postponse(redraw_man_t *rdman, coord_t *coord) { + int r; + + if(coord->flags & COF_FREE) + return ERR; + + coord->flags |= COF_FREE; + coord_hide(coord); + if(!(coord->flags & COF_DIRTY)) { + r = add_dirty_coord(rdman, coord); + if(r != OK) + return ERR; + } + r = add_free_obj(rdman, coord, (free_func_t)rdman_coord_free); + if(r != OK) + return ERR; + return OK; +} + /*! \brief Free a coord of a redraw_man_t object. * + * All children and members should be freed before parent being freed. + * * \param coord is a coord_t without children and members. * \return 0 for successful, -1 for error. * - * \note Removing coords when the rdman is dirty, the removing is postponsed. + * \note Free is postponsed if the coord is dirty or it has children + * or members postponsed for free. */ int rdman_coord_free(redraw_man_t *rdman, coord_t *coord) { coord_t *parent; coord_t *child; geo_t *member; - int r; + int cm_cnt; /* children & members counter */ parent = coord->parent; if(parent == NULL) return ERR; - if(rdman_is_dirty(rdman)) { - if(coord->flags & COF_FREE) + cm_cnt = 0; + FORCHILDREN(coord, child) { + cm_cnt++; + if(!(child->flags & COF_FREE)) return ERR; - - FORCHILDREN(coord, child) { - if(!(child->flags & COF_FREE)) - return ERR; - } - FORMEMBERS(coord, member) { - if(!(member->flags & GEF_FREE)) - return ERR; - } - coord->flags |= COF_FREE; - coord_hide(coord); - if(!(coord->flags & COF_DIRTY)) { - r = add_dirty_coord(rdman, coord); - if(r != OK) - return ERR; - } - r = add_free_obj(rdman, coord, (free_func_t)rdman_coord_free); - if(r != OK) + } + FORMEMBERS(coord, member) { + cm_cnt++; + if(!(member->flags & GEF_FREE)) return ERR; - return OK; } - - if(FIRST_MEMBER(coord) != NULL) - return ERR; - - if(FIRST_CHILD(coord) != NULL) - return ERR; + + if(cm_cnt || rdman_is_dirty(rdman)) + return rdman_coord_free_postponse(rdman, coord); /* Free canvas (\ref redraw) */ if(coord->flags & COF_OWN_CANVAS) free_canvas(coord->canvas); RM_CHILD(parent, coord); - subject_free(&rdman->ob_factory, coord->mouse_event); + subject_free(coord->mouse_event); elmpool_elm_free(rdman->coord_pool, coord); rdman->n_coords--; @@ -1118,7 +1124,6 @@ int n_dirty_areas; area_t **dirty_areas; event_t event; - ob_factory_t *factory; subject_t *redraw; r = clean_rdman_dirties(rdman); @@ -1142,11 +1147,10 @@ /* Free postponsed removing */ free_free_objs(rdman); - factory = rdman_get_ob_factory(rdman); redraw = rdman_get_redraw_subject(rdman); event.type = EVT_RDMAN_REDRAW; event.tgt = event.cur_tgt = redraw; - subject_notify(factory, redraw, &event); + subject_notify(redraw, &event); return OK; }