|
Packit |
bc1512 |
/* This file is part of GEGL
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is free software; you can redistribute it and/or
|
|
Packit |
bc1512 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License as published by the Free Software Foundation; either
|
|
Packit |
bc1512 |
* version 3 of the License, or (at your option) any later version.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is distributed in the hope that it will be useful,
|
|
Packit |
bc1512 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
bc1512 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
bc1512 |
* Lesser General Public License for more details.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Copyright 2003 Calvin Williamson
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "config.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include <glib-object.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl-types-internal.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl.h"
|
|
Packit |
bc1512 |
#include "graph/gegl-node.h"
|
|
Packit |
bc1512 |
#include "graph/gegl-pad.h"
|
|
Packit |
bc1512 |
#include "gegl-visitor.h"
|
|
Packit |
bc1512 |
#include "gegl-visitable.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
typedef struct _GeglVisitInfo GeglVisitInfo;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
struct _GeglVisitInfo
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gboolean visited;
|
|
Packit |
bc1512 |
gboolean discovered;
|
|
Packit |
bc1512 |
gint shared_count;
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
enum
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
PROP_0,
|
|
Packit |
bc1512 |
PROP_ID
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void gegl_visitor_class_init (GeglVisitorClass *klass);
|
|
Packit |
bc1512 |
static void gegl_visitor_init (GeglVisitor *self);
|
|
Packit |
bc1512 |
static void finalize (GObject *gobject);
|
|
Packit |
bc1512 |
static void init_dfs_traversal (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static void dfs_traverse (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static void init_bfs_traversal (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static void visit_info_destroy (GeglVisitInfo *visit_info);
|
|
Packit |
bc1512 |
static void insert (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static GeglVisitInfo* lookup (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static gboolean get_visited (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static void set_visited (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable,
|
|
Packit |
bc1512 |
gboolean visited);
|
|
Packit |
bc1512 |
static gboolean get_discovered (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static void set_discovered (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable,
|
|
Packit |
bc1512 |
gboolean discovered);
|
|
Packit |
bc1512 |
static gint get_shared_count (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable);
|
|
Packit |
bc1512 |
static void set_shared_count (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable,
|
|
Packit |
bc1512 |
gint shared_count);
|
|
Packit |
bc1512 |
static void visit_pad (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglPad *pad);
|
|
Packit |
bc1512 |
static void visit_node (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglNode *node);
|
|
Packit |
bc1512 |
static void set_property (GObject *gobject,
|
|
Packit |
bc1512 |
guint prop_id,
|
|
Packit |
bc1512 |
const GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec);
|
|
Packit |
bc1512 |
static void get_property (GObject *gobject,
|
|
Packit |
bc1512 |
guint prop_id,
|
|
Packit |
bc1512 |
GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
G_DEFINE_TYPE (GeglVisitor, gegl_visitor, G_TYPE_OBJECT)
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_visitor_class_init (GeglVisitorClass *klass)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gobject_class->finalize = finalize;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
klass->visit_pad = visit_pad;
|
|
Packit |
bc1512 |
klass->visit_node = visit_node;
|
|
Packit |
bc1512 |
gobject_class->set_property = set_property;
|
|
Packit |
bc1512 |
gobject_class->get_property = get_property;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_class_install_property (gobject_class, PROP_ID,
|
|
Packit |
bc1512 |
g_param_spec_pointer ("id",
|
|
Packit |
bc1512 |
"evaluation-id",
|
|
Packit |
bc1512 |
"The identifier for the evaluation context",
|
|
Packit |
bc1512 |
G_PARAM_CONSTRUCT |
|
|
Packit |
bc1512 |
G_PARAM_READWRITE));
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
set_property (GObject *gobject,
|
|
Packit |
bc1512 |
guint property_id,
|
|
Packit |
bc1512 |
const GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitor *self = GEGL_VISITOR (gobject);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
switch (property_id)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
case PROP_ID:
|
|
Packit |
bc1512 |
self->context_id = g_value_get_pointer (value);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
default:
|
|
Packit |
bc1512 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
get_property (GObject *gobject,
|
|
Packit |
bc1512 |
guint property_id,
|
|
Packit |
bc1512 |
GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitor *self = GEGL_VISITOR (gobject);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
switch (property_id)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
case PROP_ID:
|
|
Packit |
bc1512 |
g_value_set_pointer (value, self->context_id);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
default:
|
|
Packit |
bc1512 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_visitor_init (GeglVisitor *self)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
self->visits_list = NULL;
|
|
Packit |
bc1512 |
self->hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
Packit |
bc1512 |
NULL,
|
|
Packit |
bc1512 |
(GDestroyNotify) visit_info_destroy);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
finalize (GObject *gobject)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitor *self = GEGL_VISITOR (gobject);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_slist_free (self->visits_list);
|
|
Packit |
bc1512 |
g_hash_table_destroy (self->hash);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
G_OBJECT_CLASS (gegl_visitor_parent_class)->finalize (gobject);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static GeglVisitInfo *
|
|
Packit |
bc1512 |
lookup (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return g_hash_table_lookup (self->hash, visitable);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* resets the object's data (list of visits and visitable statuses) */
|
|
Packit |
bc1512 |
void gegl_visitor_reset (GeglVisitor *self)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (self->visits_list)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_slist_free (self->visits_list);
|
|
Packit |
bc1512 |
self->visits_list = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
g_hash_table_remove_all (self->hash);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Inserts the visitable into the object's hash table of visitables with the
|
|
Packit |
bc1512 |
* object as a key and a new GeglVisitInfo (zero initialised) as object
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
insert (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (lookup (self, visitable))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning ("visitable already in visitor's hash table");
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_hash_table_insert (self->hash, visitable, g_slice_new0 (GeglVisitInfo));
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Returns TRUE if a GeglVisitable has already been visited */
|
|
Packit |
bc1512 |
static gboolean
|
|
Packit |
bc1512 |
get_visited (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (visit_info);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return visit_info->visited;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
set_visited (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable,
|
|
Packit |
bc1512 |
gboolean visited)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (visit_info);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
visit_info->visited = visited;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gboolean
|
|
Packit |
bc1512 |
get_discovered (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (visit_info);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return visit_info->discovered;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
set_discovered (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable,
|
|
Packit |
bc1512 |
gboolean discovered)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (visit_info);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
visit_info->discovered = discovered;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gint
|
|
Packit |
bc1512 |
get_shared_count (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (visit_info);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return visit_info->shared_count;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
set_shared_count (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable,
|
|
Packit |
bc1512 |
gint shared_count)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (visit_info);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
visit_info->shared_count = shared_count;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/**
|
|
Packit |
bc1512 |
* gegl_visitor_get_visits_list
|
|
Packit |
bc1512 |
* @self: a #GeglVisitor.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Gets a list of the visitables the visitor has visited so far.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Returns: A list of the visitables visited by this visitor.
|
|
Packit |
bc1512 |
**/
|
|
Packit |
bc1512 |
GSList *
|
|
Packit |
bc1512 |
gegl_visitor_get_visits_list (GeglVisitor *self)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_return_val_if_fail (GEGL_IS_VISITOR (self), NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return self->visits_list;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
visit_info_destroy (GeglVisitInfo *visit_info)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_slice_free (GeglVisitInfo, visit_info);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/**
|
|
Packit |
bc1512 |
* gegl_visitor_dfs_traverse:
|
|
Packit |
bc1512 |
* @self: #GeglVisitor
|
|
Packit |
bc1512 |
* @visitable: the start #GeglVisitable
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Traverse depth first starting at @visitable.
|
|
Packit |
bc1512 |
**/
|
|
Packit |
bc1512 |
void
|
|
Packit |
bc1512 |
gegl_visitor_dfs_traverse (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* sets up the structures that keeps track of the */
|
|
Packit |
bc1512 |
init_dfs_traversal (self, visitable);
|
|
Packit |
bc1512 |
dfs_traverse (self, visitable);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Recursively (depth first) sets up the structure (hash) that keeps track of
|
|
Packit |
bc1512 |
* if a visitable's status
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
init_dfs_traversal (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GSList *depends_on_list;
|
|
Packit |
bc1512 |
GSList *llink;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* add the visitable to the list */
|
|
Packit |
bc1512 |
insert (self, visitable);
|
|
Packit |
bc1512 |
depends_on_list = gegl_visitable_depends_on (visitable);
|
|
Packit |
bc1512 |
llink = depends_on_list;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (llink)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitable *visitable = llink->data;
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* if the visitable doesn't have a visit_info,
|
|
Packit |
bc1512 |
* then it needs to be initialised
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
if (!visit_info)
|
|
Packit |
bc1512 |
init_dfs_traversal (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
llink = g_slist_next (llink);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_slist_free (depends_on_list);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Recursively (depth first) traverses the visitables and call's their
|
|
Packit |
bc1512 |
* accept methods
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
dfs_traverse (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GSList *depends_on_list;
|
|
Packit |
bc1512 |
GSList *llink;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
depends_on_list = gegl_visitable_depends_on (visitable);
|
|
Packit |
bc1512 |
llink = depends_on_list;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (llink)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitable *visitable = llink->data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* if the visitable has not yet been visitied then visit it */
|
|
Packit |
bc1512 |
if (!get_visited (self, visitable))
|
|
Packit |
bc1512 |
dfs_traverse (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
llink = g_slist_next (llink);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_slist_free (depends_on_list);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* trigger the actual visit (call the visitable's accept method that will
|
|
Packit |
bc1512 |
* call the visitable's visit method (c.f. the visitor pattern)
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
gegl_visitable_accept (visitable, self);
|
|
Packit |
bc1512 |
/* mark the visitable as already visited*/
|
|
Packit |
bc1512 |
set_visited (self, visitable, TRUE);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
init_bfs_traversal (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GSList *depends_on_list;
|
|
Packit |
bc1512 |
GSList *llink;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
insert (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
depends_on_list = gegl_visitable_depends_on (visitable);
|
|
Packit |
bc1512 |
llink = depends_on_list;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (llink)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint shared_count;
|
|
Packit |
bc1512 |
GeglVisitable *depends_on_visitable = llink->data;
|
|
Packit |
bc1512 |
GeglVisitInfo *visit_info = lookup (self, depends_on_visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!visit_info)
|
|
Packit |
bc1512 |
init_bfs_traversal (self, depends_on_visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
shared_count = get_shared_count (self, depends_on_visitable);
|
|
Packit |
bc1512 |
shared_count++;
|
|
Packit |
bc1512 |
set_shared_count (self, depends_on_visitable, shared_count);
|
|
Packit |
bc1512 |
llink = g_slist_next (llink);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_slist_free (depends_on_list);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/**
|
|
Packit |
bc1512 |
* gegl_visitor_bfs_traverse:
|
|
Packit |
bc1512 |
* @self: a #GeglVisitor
|
|
Packit |
bc1512 |
* @visitable: the root #GeglVisitable.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Traverse breadth-first starting at @visitable.
|
|
Packit |
bc1512 |
**/
|
|
Packit |
bc1512 |
void
|
|
Packit |
bc1512 |
gegl_visitor_bfs_traverse (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglVisitable *visitable)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GQueue queue = G_QUEUE_INIT;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Init all visitables */
|
|
Packit |
bc1512 |
init_bfs_traversal (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Initialize the queue with this visitable */
|
|
Packit |
bc1512 |
g_queue_push_head (&queue, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Mark visitable as "discovered" */
|
|
Packit |
bc1512 |
set_discovered (self, visitable, TRUE);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Pop the top of the queue*/
|
|
Packit |
bc1512 |
while ((visitable = g_queue_pop_head (&queue)))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint shared_count = get_shared_count (self, visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Put this one at the end of the queue if its active
|
|
Packit |
bc1512 |
* immediate parents haven't all been visited yet.
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
if (shared_count > 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_queue_push_tail (&queue, visitable);
|
|
Packit |
bc1512 |
continue;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Loop through visitable's sources and examine them */
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GSList *depends_on_list = gegl_visitable_depends_on (visitable);
|
|
Packit |
bc1512 |
GSList *llink;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (llink = depends_on_list; llink; llink = g_slist_next (llink))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitable *depends_on_visitable = llink->data;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
shared_count = get_shared_count (self, depends_on_visitable);
|
|
Packit |
bc1512 |
shared_count--;
|
|
Packit |
bc1512 |
set_shared_count (self, depends_on_visitable, shared_count);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Add any undiscovered visitable to the queue at end */
|
|
Packit |
bc1512 |
if (!get_discovered (self, depends_on_visitable))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_queue_push_tail (&queue, depends_on_visitable);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Mark it as discovered */
|
|
Packit |
bc1512 |
set_discovered (self, depends_on_visitable, TRUE);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_slist_free (depends_on_list);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* Visit the visitable */
|
|
Packit |
bc1512 |
gegl_visitable_accept (visitable, self);
|
|
Packit |
bc1512 |
set_visited (self, visitable, TRUE);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* should be called by extending classes when their visit_pad function
|
|
Packit |
bc1512 |
* is called
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
void
|
|
Packit |
bc1512 |
gegl_visitor_visit_pad (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglPad *pad)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitorClass *klass;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
klass = GEGL_VISITOR_GET_CLASS (self);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (klass->visit_pad)
|
|
Packit |
bc1512 |
klass->visit_pad (self, pad);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
visit_pad (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglPad *pad)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
self->visits_list = g_slist_prepend (self->visits_list, pad);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* should be called by extending classes when their visit_node function
|
|
Packit |
bc1512 |
* is called
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
void
|
|
Packit |
bc1512 |
gegl_visitor_visit_node (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglNode *node)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglVisitorClass *klass;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
klass = GEGL_VISITOR_GET_CLASS (self);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (klass->visit_node)
|
|
Packit |
bc1512 |
klass->visit_node (self, node);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* adds the visiting node to the list of visits */
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
visit_node (GeglVisitor *self,
|
|
Packit |
bc1512 |
GeglNode *node)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
#if 0
|
|
Packit |
bc1512 |
#if ENABLE_MT
|
|
Packit |
bc1512 |
g_mutex_lock (node->mutex);
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
self->visits_list = g_slist_prepend (self->visits_list, node);
|
|
Packit |
bc1512 |
#if 0
|
|
Packit |
bc1512 |
#if ENABLE_MT
|
|
Packit |
bc1512 |
g_mutex_unlock (node->mutex);
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
#endif
|
|
Packit |
bc1512 |
}
|