[gjs] context: Add a context stack API



commit cab6c35e426cc8e7ef58c6b2e875c2b24f88c801
Author: Sam Spilsbury <smspillaz gmail com>
Date:   Mon Jan 13 18:15:45 2014 -0200

    context: Add a context stack API
    
    The current context is now based on a stack model, so clients can
    freely push and pop contexts. The current context is the top of
    the stack.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=721246

 gjs/context.cpp    |   42 ++++++++++++++++++++++++++++++++----------
 gjs/context.h      |    2 ++
 test/gjs-tests.cpp |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 10 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 7fd11dd..e5d2028 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -101,6 +101,7 @@ enum {
 static GMutex gc_idle_lock;
 static GMutex contexts_lock;
 static GList *all_contexts = NULL;
+static GList *context_stack = NULL;
 
 
 static JSBool
@@ -277,7 +278,7 @@ gjs_printerr(JSContext *context,
 static void
 gjs_context_init(GjsContext *js_context)
 {
-    gjs_context_make_current(js_context);
+    gjs_context_push(js_context);
 }
 
 static void
@@ -409,10 +410,8 @@ gjs_context_finalize(GObject *object)
         js_context->program_name = NULL;
     }
 
-    if (gjs_context_get_current() == (GjsContext*)object)
-        gjs_context_make_current(NULL);
-
     g_mutex_lock(&contexts_lock);
+    context_stack = g_list_remove_all(context_stack, object);
     all_contexts = g_list_remove(all_contexts, object);
     g_mutex_unlock(&contexts_lock);
 
@@ -925,18 +924,41 @@ gjs_context_define_string_array(GjsContext  *js_context,
     return TRUE;
 }
 
-static GjsContext *current_context;
-
 GjsContext *
-gjs_context_get_current (void)
+gjs_context_get_current(void)
 {
+    GjsContext *current_context = NULL;
+    g_mutex_lock(&contexts_lock);
+    if (context_stack)
+        current_context = (GjsContext *) (g_list_last(context_stack))->data;
+    g_mutex_unlock(&contexts_lock);
     return current_context;
 }
 
 void
-gjs_context_make_current (GjsContext *context)
+gjs_context_push(GjsContext *context)
+{
+    g_mutex_lock(&contexts_lock);
+    context_stack = g_list_append(context_stack, context);
+    g_mutex_unlock(&contexts_lock);
+}
+
+GjsContext *
+gjs_context_pop(void)
 {
-    g_assert (context == NULL || current_context == NULL);
+    GjsContext *last = NULL;
+    g_mutex_lock(&contexts_lock);
+    GList *last_link = g_list_last(context_stack);
+    if (last_link) {
+        last = (GjsContext *) last_link->data;
+        context_stack = g_list_remove_link(context_stack, last_link);
+    }
+    g_mutex_unlock(&contexts_lock);
+    return last;
+}
 
-    current_context = context;
+void
+gjs_context_make_current(GjsContext *context)
+{
+    gjs_context_push(context);
 }
diff --git a/gjs/context.h b/gjs/context.h
index ccd8bc6..372f309 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -66,6 +66,8 @@ GList*          gjs_context_get_all              (void);
 
 GjsContext     *gjs_context_get_current          (void);
 void            gjs_context_make_current         (GjsContext *js_context);
+void            gjs_context_push                 (GjsContext *js_context);
+GjsContext     *gjs_context_pop                  (void);
 
 void*           gjs_context_get_native_context   (GjsContext *js_context);
 
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index 2dba2b2..ce93d24 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -350,6 +350,48 @@ gjstest_test_strip_shebang_return_null_for_just_shebang(void)
     g_assert(line_number == -1);
 }
 
+static void
+gjstest_test_context_pushed_on_creation(void)
+{
+    GjsContext *context = gjs_context_new();
+    g_assert(gjs_context_get_current() == context);
+    g_object_unref(context);
+}
+
+static void
+gjstest_test_context_removed_on_deletion(void)
+{
+    GjsContext *context = gjs_context_new();
+    g_object_unref(context);
+    g_assert(gjs_context_get_current() == NULL);
+}
+
+static void
+gjstest_test_all_instances_removed_on_deletion(void)
+{
+    GjsContext *context = gjs_context_new();
+    GjsContext *other = gjs_context_new();
+
+    gjs_context_push(context);
+    gjs_context_push(other);
+    gjs_context_push(context);
+    gjs_context_push(context);
+
+    g_object_unref(context);
+
+    g_assert(gjs_context_get_current() == other);
+    g_object_unref(other);
+}
+
+static void
+gjstest_test_pop_context(void)
+{
+    GjsContext *context = gjs_context_new();
+    gjs_context_pop();
+    g_assert(gjs_context_get_current() == NULL);
+    g_object_unref(context);
+}
+
 int
 main(int    argc,
      char **argv)
@@ -367,6 +409,10 @@ main(int    argc,
     g_test_add_func("/gjs/jsutil/strip_shebang/no_shebang", 
gjstest_test_strip_shebang_no_advance_for_no_shebang);
     g_test_add_func("/gjs/jsutil/strip_shebang/have_shebang", 
gjstest_test_strip_shebang_advance_for_shebang);
     g_test_add_func("/gjs/jsutil/strip_shebang/only_shebang", 
gjstest_test_strip_shebang_return_null_for_just_shebang);
+    g_test_add_func("/gjs/context_stack/creation", gjstest_test_context_pushed_on_creation);
+    g_test_add_func("/gjs/context_stack/removed_on_deletion", gjstest_test_context_removed_on_deletion);
+    g_test_add_func("/gjs/context_stack/all_removed_on_deletion", 
gjstest_test_all_instances_removed_on_deletion);
+    g_test_add_func("/gjs/context_stack/pop_context", gjstest_test_pop_context);
     g_test_add_func("/gjs/stack/dump", gjstest_test_func_gjs_stack_dump);
     g_test_add_func("/util/glib/strv/concat/null", gjstest_test_func_util_glib_strv_concat_null);
     g_test_add_func("/util/glib/strv/concat/pointers", gjstest_test_func_util_glib_strv_concat_pointers);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]