changeset 125:1c1f28c124c9

Postponding free request when a subject is in subject_notify
author Thinker K.F. Li <thinker@branda.to>
date Tue, 16 Sep 2008 15:31:49 +0800
parents ad5ab8e61c2b
children 55f2c6402c81
files src/observer.c src/observer.h
diffstat 2 files changed, 26 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/observer.c	Tue Sep 16 14:55:24 2008 +0800
+++ b/src/observer.c	Tue Sep 16 15:31:49 2008 +0800
@@ -18,9 +18,20 @@
     return subject;
 }
 
+/*!
+ * \todo Keep ob_factory following subject objects.
+ */
 void subject_free(ob_factory_t *factory, subject_t *subject) {
     observer_t *observer;
 
+    if(subject->flags & SUBF_BUSY) {
+	/* Postpond the request until busy status been stoped.
+	 * SUBF_BUSY means in subject_notify().
+	 */
+	subject->flags |= SUBF_FREE;
+	return;
+    }
+	
     while((observer = STAILQ_HEAD(subject->observers))) {
 	STAILQ_REMOVE(subject->observers, observer_t, next, observer);
 	factory->observer_free(factory, observer);
@@ -32,6 +43,13 @@
 void subject_notify(ob_factory_t *factory, subject_t *subject, event_t *evt) {
     observer_t *observer;
 
+    /*!
+     * \note What is happend when the subject is freed by observer?
+     *		Postponding the request of free until notification
+     *		been finished. (\ref SUBF_BUSY / \ref SUBF_FREE)
+     */
+    subject->flags |= SUBF_BUSY;
+
     evt->tgt = subject;
     while(subject) {
 	evt->cur_tgt = subject->obj;
@@ -46,6 +64,10 @@
 
 	subject = factory->get_parent_subject(factory, subject);
     }
+
+    subject->flags &= ~SUBF_BUSY;
+    if(subject->flags & SUBF_FREE)
+	subject_free(factory, subject);
 }
 
 observer_t *subject_add_observer(ob_factory_t *factory,
--- a/src/observer.h	Tue Sep 16 14:55:24 2008 +0800
+++ b/src/observer.h	Tue Sep 16 15:31:49 2008 +0800
@@ -32,13 +32,15 @@
  * \see http://en.wikipedia.org/wiki/Observer_pattern
  */
 struct _subject {
-    int obj_type;		/*!< type of object (a.k.a. OBJT_*). */
-    void *obj;			/*!< the object this subject for. */
+    int obj_type;		/*!< \brief type of object (a.k.a. OBJT_*). */
+    void *obj;			/*!< \brief the object this subject for. */
     int flags;
     STAILQ(observer_t) observers;
 };
 /*! \brief Flag that make a subject to propagate events to parents. */
 #define SUBF_STOP_PROPAGATE 0x1
+#define SUBF_BUSY 0x2		/*!< \brief in subject_notify() */
+#define SUBF_FREE 0x4		/*!< \brief in postponding subject_free() */
 
 enum {OBJT_GEO, OBJT_COORD, OBJT_KB, OBJT_PROGM};