diff options
author | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2012-12-04 18:23:18 +0100 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2012-12-04 18:23:18 +0100 |
commit | 9d7478bf103b36f244283c82d80a11b303217432 (patch) | |
tree | b2a80358925482baa2be45c9192d7ae5f6f513bd | |
parent | a21147c0a5d9a7eff9e8c02865ac7dc62f0213fb (diff) |
First integration step of the prototype
This is introducing better multi GPU handling and cluster processing using zmq.
73 files changed, 4457 insertions, 6384 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 82eb779..39db0e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ set(UFO_VERSION_PATCH "0") set(UFO_GIR_VERSION "${UFO_VERSION_MAJOR}.${UFO_VERSION_MINOR}") # increase UFO_SO_VERSION on each version that breaks ABI compatibility -set(UFO_SO_VERSION "2") +set(UFO_SO_VERSION "3") set(UFO_DESCRIPTION "UFO high-speed image processing core library") set(UFO_DESCRIPTION_SUMMARY "UFO high-speed image processing core library") @@ -55,6 +55,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ) add_definitions("-std=c99 -pedantic -Wall -Wextra -fPIC") + if (CMAKE_COMPILER_IS_GNUCC) add_definitions("-Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wredundant-decls -Wcast-qual @@ -66,10 +67,10 @@ endif() add_definitions(-DG_LOG_DOMAIN=\"Ufo\") add_subdirectory(src) -add_subdirectory(docs) -add_subdirectory(python) -add_subdirectory(tests) -add_subdirectory(tools) +#add_subdirectory(docs) +#add_subdirectory(python) +#add_subdirectory(tests) +#add_subdirectory(tools) # --- Package generation ------------------------------------------------------ diff --git a/docs/Ufo-sections.txt.in b/docs/Ufo-sections.txt.in index abb7853..b518754 100644 --- a/docs/Ufo-sections.txt.in +++ b/docs/Ufo-sections.txt.in @@ -1,19 +1,19 @@ <SECTION> -<FILE>ufo-configuration</FILE> -<TITLE>UfoConfiguration</TITLE> -UfoConfiguration -ufo_configuration_new -ufo_configuration_get_paths +<FILE>ufo-config</FILE> +<TITLE>UfoConfig</TITLE> +UfoConfig +ufo_config_new +ufo_config_get_paths <SUBSECTION Standard> -UFO_CONFIGURATION -UFO_CONFIGURATION_CLASS -UFO_CONFIGURATION_GET_CLASS -UFO_IS_CONFIGURATION -UFO_IS_CONFIGURATION_CLASS -UFO_TYPE_CONFIGURATION -ufo_configuration_get_type +UFO_CONFIG +UFO_CONFIG_CLASS +UFO_CONFIG_GET_CLASS +UFO_IS_CONFIG +UFO_IS_CONFIG_CLASS +UFO_TYPE_CONFIG +ufo_config_get_type <SUBSECTION Private> -UfoConfigurationPrivate +UfoConfigPrivate </SECTION> <SECTION> @@ -38,8 +38,8 @@ UfoConfigurableIface UfoPluginManagerError UfoPluginManager ufo_plugin_manager_new -ufo_plugin_manager_get_filter -ufo_plugin_manager_get_all_filter_names +ufo_plugin_manager_get_task +ufo_plugin_manager_get_all_task_names <SUBSECTION Standard> UFO_PLUGIN_MANAGER UFO_IS_PLUGIN_MANAGER @@ -56,82 +56,27 @@ ufo_plugin_manager_error_quark <SECTION> <FILE>ufo-resource-manager</FILE> -<TITLE>UfoResourceManager</TITLE> -CHECK_OPENCL_ERROR -UfoResourceManagerError -UfoResourceManager -ufo_resource_manager_new -ufo_resource_manager_get_kernel -ufo_resource_manager_get_kernel_from_source -ufo_resource_manager_get_context -ufo_resource_manager_get_command_queues -ufo_resource_manager_get_command_queue -ufo_resource_manager_get_number_of_devices -ufo_resource_manager_memdup -ufo_resource_manager_memalloc -ufo_resource_manager_request_buffer -ufo_resource_manager_get_queue_number -<SUBSECTION Standard> -UFO_RESOURCE_MANAGER -UFO_IS_RESOURCE_MANAGER -UFO_TYPE_RESOURCE_MANAGER -ufo_resource_manager_get_type -UFO_RESOURCE_MANAGER_CLASS -UFO_IS_RESOURCE_MANAGER_CLASS -UFO_RESOURCE_MANAGER_GET_CLASS -<SUBSECTION Private> -UFO_RESOURCE_MANAGER_ERROR -UfoResourceManagerClass -UfoResourceManagerPrivate +<TITLE>UfoResources</TITLE> +UfoResourcesError +UfoResources +ufo_resources_new +ufo_resources_get_kernel +ufo_resources_get_kernel_from_source +ufo_resources_get_context +<SUBSECTION Standard> +UFO_RESOURCES +UFO_IS_RESOURCES +UFO_TYPE_RESOURCES +ufo_resources_get_type +UFO_RESOURCES_CLASS +UFO_IS_RESOURCES_CLASS +UFO_RESOURCES_GET_CLASS +<SUBSECTION Private> +UFO_RESOURCES_ERROR +UfoResourcesClass +UfoResourcesPrivate opencl_map_error -ufo_resource_manager_error_quark -</SECTION> - -<SECTION> -<FILE>ufo-filter</FILE> -<TITLE>UfoFilter</TITLE> -UfoFilterError -UfoFilter -UfoFilterClass -UfoFilterConditionFunc -UfoInputParameter -UfoOutputParameter -UFO_FILTER_INFINITE_INPUT -ufo_filter_initialize -ufo_filter_process_cpu -ufo_filter_process_gpu -ufo_filter_register_inputs -ufo_filter_register_outputs -ufo_filter_get_num_inputs -ufo_filter_get_num_outputs -ufo_filter_get_input_parameters -ufo_filter_get_output_parameters -ufo_filter_set_plugin_name -ufo_filter_get_plugin_name -ufo_filter_get_unique_name -ufo_filter_set_resource_manager -ufo_filter_get_resource_manager -ufo_filter_set_command_queue -ufo_filter_get_command_queue -ufo_filter_set_profiler -ufo_filter_get_profiler -ufo_filter_set_input_channel -ufo_filter_get_input_channel -ufo_filter_set_output_channel -ufo_filter_get_output_channel -ufo_filter_wait_until -<SUBSECTION Standard> -UFO_FILTER -UFO_IS_FILTER -UFO_TYPE_FILTER -ufo_filter_get_type -UFO_FILTER_CLASS -UFO_IS_FILTER_CLASS -UFO_FILTER_GET_CLASS -<SUBSECTION Private> -UFO_FILTER_ERROR -UfoFilterPrivate -ufo_filter_error_quark +ufo_resources_error_quark </SECTION> <SECTION> @@ -161,204 +106,10 @@ UfoProfilerPrivate </SECTION> <SECTION> -<FILE>ufo-filter-sink</FILE> -<TITLE>UfoFilterSink</TITLE> -UfoFilterSink -UfoFilterSinkClass -ufo_filter_sink_initialize -ufo_filter_sink_consume -<SUBSECTION Standard> -UFO_TYPE_FILTER_SINK -UFO_FILTER_SINK -UFO_FILTER_SINK_CLASS -UFO_FILTER_SINK_GET_CLASS -UFO_IS_FILTER_SINK -UFO_IS_FILTER_SINK_CLASS -ufo_filter_sink_get_type -<SUBSECTION Private> -UfoFilterSinkPrivate -</SECTION> - -<SECTION> -<FILE>ufo-filter-sink-direct</FILE> -<TITLE>UfoFilterSinkDirect</TITLE> -UfoFilterSinkDirect -ufo_filter_sink_direct_pop -ufo_filter_sink_direct_release -<SUBSECTION Standard> -UfoFilterSinkDirectClass -UFO_TYPE_FILTER_SINK_DIRECT -UFO_FILTER_SINK_DIRECT -UFO_FILTER_SINK_DIRECT_CLASS -UFO_FILTER_SINK_DIRECT_GET_CLASS -UFO_IS_FILTER_SINK_DIRECT -UFO_IS_FILTER_SINK_DIRECT_CLASS -ufo_filter_sink_direct_get_type -<SUBSECTION Private> -UfoFilterSinkDirectPrivate -</SECTION> - -<SECTION> -<FILE>ufo-filter-source</FILE> -<TITLE>UfoFilterSource</TITLE> -UfoFilterSource -UfoFilterSourceClass -ufo_filter_source_initialize -ufo_filter_source_generate -<SUBSECTION Standard> -UFO_TYPE_FILTER_SOURCE -UFO_FILTER_SOURCE -UFO_FILTER_SOURCE_CLASS -UFO_FILTER_SOURCE_GET_CLASS -UFO_IS_FILTER_SOURCE -UFO_IS_FILTER_SOURCE_CLASS -ufo_filter_source_get_type -<SUBSECTION Private> -UfoFilterSourcePrivate -</SECTION> - -<SECTION> -<FILE>ufo-filter-source-direct</FILE> -<TITLE>UfoFilterSourceDirect</TITLE> -UfoFilterSourceDirect -ufo_filter_source_direct_push -ufo_filter_source_direct_stop -<SUBSECTION Standard> -UfoFilterSourceDirectClass -UFO_FILTER_SOURCE_DIRECT -UFO_FILTER_SOURCE_DIRECT_CLASS -UFO_FILTER_SOURCE_DIRECT_GET_CLASS -UFO_IS_FILTER_SOURCE_DIRECT -UFO_IS_FILTER_SOURCE_DIRECT_CLASS -UFO_TYPE_FILTER_SOURCE_DIRECT -ufo_filter_source_direct_get_type -<SUBSECTION Private> -UfoFilterSourceDirectPrivate -</SECTION> - -<SECTION> -<FILE>ufo-filter-reduce</FILE> -<TITLE>UfoFilterReduce</TITLE> -UfoFilterReduce -UfoFilterReduceClass -ufo_filter_reduce_initialize -ufo_filter_reduce_collect -ufo_filter_reduce_reduce -<SUBSECTION Standard> -UFO_TYPE_FILTER_REDUCE -UFO_FILTER_REDUCE -UFO_FILTER_REDUCE_CLASS -UFO_FILTER_REDUCE_GET_CLASS -UFO_IS_FILTER_REDUCE -UFO_IS_FILTER_REDUCE_CLASS -ufo_filter_reduce_get_type -<SUBSECTION Private> -UfoFilterReducePrivate -</SECTION> - -<SECTION> -<FILE>ufo-filter-repeater</FILE> -<TITLE>UfoFilterRepeater</TITLE> -UfoFilterRepeater -UfoFilterRepeaterClass -<SUBSECTION Standard> -UFO_FILTER_REPEATER -UFO_FILTER_REPEATER_CLASS -UFO_FILTER_REPEATER_GET_CLASS -UFO_IS_FILTER_REPEATER -UFO_IS_FILTER_REPEATER_CLASS -UFO_TYPE_FILTER_REPEATER -ufo_filter_repeater_get_type -<SUBSECTION Private> -UfoFilterRepeaterPrivate -</SECTION> - -<SECTION> -<FILE>ufo-filter-splitter</FILE> -<TITLE>UfoFilterSplitter</TITLE> -UfoFilterSplitter -UfoFilterSplitterClass -<SUBSECTION Standard> -UFO_TYPE_FILTER_SPLITTER -UFO_FILTER_SPLITTER -UFO_FILTER_SPLITTER_CLASS -UFO_FILTER_SPLITTER_GET_CLASS -UFO_IS_FILTER_SPLITTER -UFO_IS_FILTER_SPLITTER_CLASS -ufo_filter_splitter_get_type -<SUBSECTION Private> -UfoFilterSplitterPrivate -</SECTION> - -<SECTION> -<FILE>ufo-relation</FILE> -<TITLE>UfoRelation</TITLE> -UfoRelation -UfoRelationMode -ufo_relation_new -ufo_relation_add_consumer -ufo_relation_get_producer -ufo_relation_get_consumers -ufo_relation_get_consumer_port -ufo_relation_get_producer_port -ufo_relation_get_consumer_queues -ufo_relation_get_producer_queues -ufo_relation_has_consumer -ufo_relation_push_poison_pill -<SUBSECTION Standard> -UFO_TYPE_RELATION -UFO_RELATION -UFO_RELATION_CLASS -UFO_RELATION_GET_CLASS -UFO_IS_RELATION -UFO_IS_RELATION_CLASS -ufo_relation_get_type -<SUBSECTION Private> -UfoRelationPrivate -</SECTION> - -<SECTION> -<FILE>ufo-channel</FILE> -<TITLE>UfoChannel</TITLE> -UfoChannel -ufo_channel_new -ufo_channel_ref -ufo_channel_insert -ufo_channel_fetch_input -ufo_channel_release_input -ufo_channel_fetch_output -ufo_channel_release_output -ufo_channel_daisy_chain -ufo_channel_finish -ufo_channel_finish_next -<SUBSECTION Standard> -UFO_CHANNEL -UFO_IS_CHANNEL -UFO_TYPE_CHANNEL -ufo_channel_get_type -UFO_CHANNEL_CLASS -UFO_IS_CHANNEL_CLASS -UFO_CHANNEL_GET_CLASS -<SUBSECTION Private> -UfoChannelClass -UfoChannelPrivate -</SECTION> - -<SECTION> <FILE>ufo-graph</FILE> <TITLE>UfoGraph</TITLE> -UfoGraphError UfoGraph -UfoTransferMode ufo_graph_new -ufo_graph_connect_filters -ufo_graph_connect_filters_full -ufo_graph_read_from_json -ufo_graph_save_to_json -ufo_graph_get_filters -ufo_graph_get_roots -ufo_graph_get_children -ufo_graph_get_num_filters <SUBSECTION Standard> UFO_GRAPH UFO_IS_GRAPH @@ -382,25 +133,11 @@ UfoBuffer UFO_BUFFER_MAX_NDIMS ufo_buffer_new ufo_buffer_copy -ufo_buffer_alloc_host_mem -ufo_buffer_transfer_id ufo_buffer_get_size -ufo_buffer_get_id -ufo_buffer_get_dimensions ufo_buffer_get_2d_dimensions ufo_buffer_resize -ufo_buffer_reinterpret -ufo_buffer_fill_with_value -ufo_buffer_set_host_array ufo_buffer_get_host_array -ufo_buffer_swap_host_arrays ufo_buffer_get_device_array -ufo_buffer_set_cl_mem -ufo_buffer_invalidate_gpu_data -ufo_buffer_get_transfer_timer -ufo_buffer_attach_event -ufo_buffer_get_events -ufo_buffer_clear_events <SUBSECTION>UfoBufferParamSpec</SUBSECTION> UfoBufferParamSpec ufo_buffer_param_spec diff --git a/docs/scangobj.sh.in b/docs/scangobj.sh.in index 5a208c2..aedf3f0 100644 --- a/docs/scangobj.sh.in +++ b/docs/scangobj.sh.in @@ -1 +1 @@ -LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${CMAKE_CURRENT_BINARY_DIR}" CFLAGS="${GTK_DOC_CFLAGS}" LDFLAGS="${GTK_DOC_LDFLAGS} -L${CMAKE_CURRENT_BINARY_DIR} -lufo" gtkdoc-scangobj --types=${CMAKE_CURRENT_SOURCE_DIR}/Ufo.types --module=Ufo +LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${CMAKE_CURRENT_BINARY_DIR}" CFLAGS="${GTK_DOC_CFLAGS}" LDFLAGS="${GTK_DOC_LDFLAGS} -L${CMAKE_CURRENT_BINARY_DIR} -lufo" gtkdoc-scangobj --module=Ufo diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f0c427..ded3b95 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,52 +2,55 @@ cmake_minimum_required(VERSION 2.6) # --- Set sources ------------------------------------------------------------- set(ufocore_SRCS - ufo-scheduler.c - ufo-channel.c + ufo-arch-graph.c + ufo-buffer.c ufo-configurable.c - ufo-configuration.c + ufo-config.c + ufo-cpu-node.c + ufo-cpu-task-iface.c + ufo-gpu-node.c + ufo-gpu-task-iface.c ufo-graph.c - ufo-buffer.c - ufo-filter.c - ufo-filter-source.c - ufo-filter-source-direct.c - ufo-filter-sink.c - ufo-filter-sink-direct.c - ufo-filter-reduce.c - ufo-filter-repeater.c - ufo-filter-splitter.c + ufo-group.c + ufo-input-task.c + ufo-node.c + ufo-output-task.c ufo-plugin-manager.c ufo-profiler.c - ufo-resource-manager.c + ufo-remote-node.c + ufo-remote-task.c + ufo-resources.c + ufo-scheduler.c + ufo-task-iface.c + ufo-task-graph.c + ufo-task-node.c ) set(ufocore_HDRS - ufo-scheduler.h - ufo-channel.h + ufo-arch-graph.h + ufo-buffer.h ufo-configurable.h - ufo-configuration.h + ufo-config.h + ufo-cpu-node.h + ufo-cpu-task-iface.h + ufo-gpu-node.h + ufo-gpu-task-iface.h ufo-graph.h - ufo-buffer.h - ufo-filter.h - ufo-filter-source.h - ufo-filter-source-direct.h - ufo-filter-sink.h - ufo-filter-sink-direct.h - ufo-filter-reduce.h - ufo-filter-repeater.h - ufo-filter-splitter.h + ufo-group.h + ufo-input-task.h + ufo-node.h + ufo-output-task.h ufo-plugin-manager.h ufo-profiler.h - ufo-resource-manager.h - ) - -set(ufocore_NODOC_SRCS - ufo-aux.c + ufo-remote-node.h + ufo-remote-task.h + ufo-resources.h + ufo-scheduler.h + ufo-task-iface.h + ufo-task-graph.h + ufo-task-node.h ) -set(ufocore_NODOC_HDRS - ufo-aux.h - ) # --- Find packages and libraries --------------------------------------------- find_program(INTROSPECTION_SCANNER "g-ir-scanner") @@ -57,6 +60,7 @@ find_program(GLIB2_MKENUMS glib-mkenums REQUIRED) pkg_check_modules(GMODULE2 gmodule-2.0>=2.22 REQUIRED) pkg_check_modules(GTHREAD2 gthread-2.0>=2.22 REQUIRED) pkg_check_modules(JSON_GLIB json-glib-1.0 REQUIRED) +pkg_check_modules(ZMQ libzmq>=3.2 REQUIRED) set(ufocore_LIBS ${OPENCL_LIBRARIES} @@ -65,6 +69,7 @@ set(ufocore_LIBS ${GMODULE2_LIBRARIES} ${GTHREAD2_LIBRARIES} ${JSON_GLIB_LIBRARIES} + ${ZMQ_LIBRARIES} ) # --- Add enum generation targets --------------------------------------------- @@ -98,7 +103,7 @@ set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}") include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${JSON_GLIB_INCLUDE_DIRS} - ) + ${ZMQ_INCLUDE_DIRS}) if(CMAKE_BUILD_TYPE MATCHES "Release") add_definitions(-DG_DISABLE_ASSERT) @@ -164,7 +169,9 @@ if (INTROSPECTION_SCANNER AND INTROSPECTION_COMPILER) --no-libtool --include=GObject-2.0 --include=GModule-2.0 + --include=GLib-2.0 -I${OPENCL_INCLUDE_DIRS} + -I${CMAKE_CURRENT_SOURCE_DIR} --output ${GIR_XML} --warn-all ${_gir_input} @@ -225,28 +232,10 @@ if(GTK_DOC_FOUND) endforeach() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../docs/Ufo-docs.xml.in" "${docs_out}/Ufo-docs.xml") - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../docs/Ufo-sections.txt.in" "${docs_out}/Ufo-sections.txt") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../docs/scangobj.sh.in" "${docs_out}/scangobj.sh") set(reference_files "${docs_out}/index.html" - "${docs_out}/annotation-glossary.html" - "${docs_out}/api-index-full.html" - "${docs_out}/ch01.html" - "${docs_out}/UfoBuffer.html" - "${docs_out}/UfoChannel.html" - "${docs_out}/UfoConfigurable.html" - "${docs_out}/UfoConfiguration.html" - "${docs_out}/UfoFilter.html" - "${docs_out}/UfoFilterReduce.html" - "${docs_out}/UfoFilterSink.html" - "${docs_out}/UfoFilterSinkDirect.html" - "${docs_out}/UfoFilterSource.html" - "${docs_out}/UfoFilterSourceDirect.html" - "${docs_out}/UfoGraph.html" - "${docs_out}/UfoPluginManager.html" - "${docs_out}/UfoProfiler.html" - "${docs_out}/UfoResourceManager.html" "${docs_out}/UfoScheduler.html" "${docs_out}/style.css" "${docs_out}/Ufo.devhelp2" @@ -264,13 +253,12 @@ if(GTK_DOC_FOUND) COMMAND ${GTK_DOC_SCAN} --module=Ufo --source-dir=${CMAKE_CURRENT_SOURCE_DIR}/../src - --ignore-headers="${ufocore_NODOC_HDRS}" DEPENDS ${ufocore_SRCS} WORKING_DIRECTORY ${docs_out}) add_custom_command(OUTPUT ${docs_out}/Ufo.args COMMAND sh scangobj.sh - DEPENDS ${ufocore_SRCS} ${docs_out}/Ufo-decl.txt ${CMAKE_CURRENT_SOURCE_DIR}/Ufo.types + DEPENDS ${ufocore_SRCS} ${docs_out}/Ufo-decl.txt WORKING_DIRECTORY ${docs_out}) add_custom_command(OUTPUT ${docs_out}/sgml.stamp diff --git a/src/Ufo.types b/src/Ufo.types index 1c60b5a..e69de29 100644 --- a/src/Ufo.types +++ b/src/Ufo.types @@ -1,16 +0,0 @@ -ufo_scheduler_get_type -ufo_buffer_get_type -ufo_channel_get_type -ufo_configurable_get_type -ufo_configuration_get_type -ufo_filter_get_type -ufo_filter_source_get_type -ufo_filter_source_direct_get_type -ufo_filter_sink_get_type -ufo_filter_sink_direct_get_type -ufo_filter_reduce_get_type -ufo_filter_splitter_get_type -ufo_graph_get_type -ufo_plugin_manager_get_type -ufo_profiler_get_type -ufo_resource_manager_get_type diff --git a/src/ufo-arch-graph.c b/src/ufo-arch-graph.c new file mode 100644 index 0000000..e0d2232 --- /dev/null +++ b/src/ufo-arch-graph.c @@ -0,0 +1,204 @@ +/** + * SECTION:ufo-arch-graph + * @Short_description: Describe and hold #UfoGpuNode, #UfoCpuNode and + * #UfoRemoteNode + * @Title: UfoArchGraph + */ + +#define _GNU_SOURCE +#include <sys/sysinfo.h> +#include <sched.h> +#include <ufo-arch-graph.h> +#include <ufo-cpu-node.h> +#include <ufo-gpu-node.h> +#include <ufo-remote-node.h> + +G_DEFINE_TYPE (UfoArchGraph, ufo_arch_graph, UFO_TYPE_GRAPH) + +#define UFO_ARCH_GRAPH_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_ARCH_GRAPH, UfoArchGraphPrivate)) + +struct _UfoArchGraphPrivate { + gpointer zmq_context; + gpointer ocl_context; + guint n_cpus; + guint n_gpus; +}; + +/** + * ufo_arch_graph_new: + * @zmq_context: Context created with zmq_context_new(). + * @remote_addresses: (element-type utf8): A #GList containing address strings. + * @resources: An initialized #UfoResources object + * + * Returns: A new #UfoArchGraph. + */ +UfoGraph * +ufo_arch_graph_new (gpointer zmq_context, + GList *remote_addresses, + UfoResources *resources) +{ + UfoArchGraph *graph; + UfoArchGraphPrivate *priv; + GList *cmd_queues; + UfoNode **cpu_nodes; + UfoNode **gpu_nodes; + cpu_set_t mask; + UfoNode **remote_nodes = NULL; + guint n_remotes = 0; + + graph = UFO_ARCH_GRAPH (g_object_new (UFO_TYPE_ARCH_GRAPH, NULL)); + priv = graph->priv; + priv->ocl_context = ufo_resources_get_context (resources); + priv->zmq_context = zmq_context; + + /* Create CPU nodes */ + priv->n_cpus = (guint) get_nprocs (); + cpu_nodes = g_new0 (UfoNode *, priv->n_cpus); + + for (guint i = 0; i < priv->n_cpus; i++) { + CPU_ZERO (&mask); + CPU_SET (i, &mask); + cpu_nodes[i] = ufo_cpu_node_new (&mask); + } + + /* Create GPU nodes, each one is associated with its own command queue. */ + cmd_queues = ufo_resources_get_cmd_queues (resources); + priv->n_gpus = g_list_length (cmd_queues); + gpu_nodes = g_new0 (UfoNode *, priv->n_gpus); + + for (guint i = 0; i < priv->n_gpus; i++) { + gpu_nodes[i] = ufo_gpu_node_new (g_list_nth_data (cmd_queues, i)); + } + + /* Create remote nodes */ + if (zmq_context) { + n_remotes = g_list_length (remote_addresses); + remote_nodes = g_new0 (UfoNode *, n_remotes); + + for (guint i = 0; i < n_remotes; i++) + remote_nodes[i] = ufo_remote_node_new (zmq_context, + (gchar *) g_list_nth_data (remote_addresses, i)); + } + + /* + * Connect all CPUs to all GPUs. In the future this is the place for a + * NUMA-specific mapping. + */ + for (guint i = 0; i < priv->n_cpus; i++) { + for (guint j = 0; j < priv->n_gpus; j++) { + ufo_graph_connect_nodes (UFO_GRAPH (graph), + cpu_nodes[i], + gpu_nodes[j], + NULL); + } + + for (guint j = 0; j < n_remotes; j++) { + ufo_graph_connect_nodes (UFO_GRAPH (graph), + cpu_nodes[i], + remote_nodes[j], + NULL); + } + } + + g_free (cpu_nodes); + g_free (gpu_nodes); + g_free (remote_nodes); + g_list_free (cmd_queues); + return UFO_GRAPH (graph); +} + +/** + * ufo_arch_graph_get_context: + * @graph: A #UfoArchGraph object + * + * Returns: OpenCL context associated with @graph. + */ +gpointer +ufo_arch_graph_get_context (UfoArchGraph *graph) +{ + g_return_val_if_fail (UFO_IS_ARCH_GRAPH (graph), NULL); + return graph->priv->ocl_context; +} + +/** + * ufo_arch_graph_get_num_cpus: + * @graph: A #UfoArchGraph object + * + * Returns: Number of CPU nodes in @graph. + */ +guint +ufo_arch_graph_get_num_cpus (UfoArchGraph *graph) +{ + g_return_val_if_fail (UFO_IS_ARCH_GRAPH (graph), 0); + return graph->priv->n_cpus; +} + +/** + * ufo_arch_graph_get_num_gpus: + * @graph: A #UfoArchGraph object + * + * Returns: Number of GPU nodes in @graph. + */ +guint +ufo_arch_graph_get_num_gpus (UfoArchGraph *graph) +{ + g_return_val_if_fail (UFO_IS_ARCH_GRAPH (graph), 0); + return graph->priv->n_gpus; +} + +static gboolean +is_gpu_node (UfoNode *node) +{ + return UFO_IS_GPU_NODE (node); +} + +/** + * ufo_arch_graph_get_gpu_nodes: + * @graph: A #UfoArchGraph + * + * Returns: (element-type UfoGpuNode) (transfer container): A list of + * #UfoGpuNode elements in @graph. + */ +GList * +ufo_arch_graph_get_gpu_nodes (UfoArchGraph *graph) +{ + return ufo_graph_get_nodes_filtered (UFO_GRAPH (graph), + is_gpu_node); +} + +static gboolean +is_remote_node (UfoNode *node) +{ + return UFO_IS_REMOTE_NODE (node); +} + +/** + * ufo_arch_graph_get_remote_nodes: + * @graph: A #UfoArchGraph + * + * Returns: (element-type UfoGpuNode) (transfer container): A list of + * #UfoRemoteNode elements in @graph. + */ +GList * +ufo_arch_graph_get_remote_nodes (UfoArchGraph *graph) +{ + return ufo_graph_get_nodes_filtered (UFO_GRAPH (graph), + is_remote_node); +} + +static void +ufo_arch_graph_class_init (UfoArchGraphClass *klass) +{ + g_type_class_add_private(klass, sizeof(UfoArchGraphPrivate)); +} + +static void +ufo_arch_graph_init (UfoArchGraph *self) +{ + UfoArchGraphPrivate *priv; + self->priv = priv = UFO_ARCH_GRAPH_GET_PRIVATE (self); + + ufo_graph_register_node_type (UFO_GRAPH (self), UFO_TYPE_CPU_NODE); + ufo_graph_register_node_type (UFO_GRAPH (self), UFO_TYPE_GPU_NODE); + ufo_graph_register_node_type (UFO_GRAPH (self), UFO_TYPE_REMOTE_NODE); +} diff --git a/src/ufo-arch-graph.h b/src/ufo-arch-graph.h new file mode 100644 index 0000000..7ffef31 --- /dev/null +++ b/src/ufo-arch-graph.h @@ -0,0 +1,57 @@ +#ifndef __UFO_ARCH_GRAPH_H +#define __UFO_ARCH_GRAPH_H + +#include <glib-object.h> +#include <ufo-graph.h> +#include <ufo-resources.h> + +G_BEGIN_DECLS + +#define UFO_TYPE_ARCH_GRAPH (ufo_arch_graph_get_type()) +#define UFO_ARCH_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_ARCH_GRAPH, UfoArchGraph)) +#define UFO_IS_ARCH_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_ARCH_GRAPH)) +#define UFO_ARCH_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_ARCH_GRAPH, UfoArchGraphClass)) +#define UFO_IS_ARCH_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_ARCH_GRAPH)) +#define UFO_ARCH_GRAPH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_ARCH_GRAPH, UfoArchGraphClass)) + +typedef struct _UfoArchGraph UfoArchGraph; +typedef struct _UfoArchGraphClass UfoArchGraphClass; +typedef struct _UfoArchGraphPrivate UfoArchGraphPrivate; + +/** + * UfoArchGraph: + * + * Graph structure that describes the relation between hardware nodes. The + * contents of the #UfoArchGraph structure are private and should only be + * accessed via the provided API. + */ +struct _UfoArchGraph { + /*< private >*/ + UfoGraph parent_instance; + + UfoArchGraphPrivate *priv; +}; + +/** + * UfoArchGraphClass: + * + * #UfoArchGraph class + */ +struct _UfoArchGraphClass { + /*< private >*/ + UfoGraphClass parent_class; +}; + +UfoGraph *ufo_arch_graph_new (gpointer zmq_context, + GList *remote_addresses, + UfoResources *resources); +gpointer ufo_arch_graph_get_context (UfoArchGraph *graph); +guint ufo_arch_graph_get_num_cpus (UfoArchGraph *graph); +guint ufo_arch_graph_get_num_gpus (UfoArchGraph *graph); +GList *ufo_arch_graph_get_gpu_nodes (UfoArchGraph *graph); +GList *ufo_arch_graph_get_remote_nodes (UfoArchGraph *graph); +GType ufo_arch_graph_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-aux.c b/src/ufo-aux.c deleted file mode 100644 index de4959e..0000000 --- a/src/ufo-aux.c +++ /dev/null @@ -1,55 +0,0 @@ -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif -#include "ufo-aux.h" - -/** - * ufo_set_property_object: - * @storage: A place to store @object - * @object: An object that should be stored and referenced or %NULL - * - * Tries to store @object in @storage and references if @object is not %NULL. In - * case @storage contains already an object, the existing object is unreffed - * with g_object_unref(). - */ -void -ufo_set_property_object (GObject **storage, GObject *object) -{ - if (*storage != NULL) - g_object_unref (*storage); - - *storage = object; - - if (object != NULL) - g_object_ref (object); -} - -/** - * ufo_unref_stored_object: - * @storage: A place that could contain an object. - * - * If @storage contains an object it is unreffed with %NULL and the storage set - * to %NULL. - */ -void -ufo_unref_stored_object (GObject **storage) -{ - if (*storage != NULL) { - g_object_unref (*storage); - *storage = NULL; - } -} - -void -ufo_debug_cl (const gchar *format, ...) -{ - va_list args; - - va_start (args, format); - g_logv ("ocl", G_LOG_LEVEL_MESSAGE, format, args); - va_end (args); -} - - diff --git a/src/ufo-aux.h b/src/ufo-aux.h deleted file mode 100644 index 1e5ef0b..0000000 --- a/src/ufo-aux.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __UFO_AUX_H -#define __UFO_AUX_H - -#include <glib-object.h> - -G_BEGIN_DECLS - -void ufo_set_property_object (GObject **storage, - GObject *object); -void ufo_unref_stored_object (GObject **object); -void ufo_debug_cl (const gchar *format, - ...); - -G_END_DECLS - -#endif diff --git a/src/ufo-buffer.c b/src/ufo-buffer.c index 34a0f02..655b413 100644 --- a/src/ufo-buffer.c +++ b/src/ufo-buffer.c @@ -11,19 +11,13 @@ #include <CL/cl.h> #endif -#include "config.h" -#include "ufo-buffer.h" -#include "ufo-aux.h" -#include "ufo-resource-manager.h" -#include "ufo-enums.h" +#include <ufo-buffer.h> +#include <ufo-resources.h> G_DEFINE_TYPE(UfoBuffer, ufo_buffer, G_TYPE_OBJECT) #define UFO_BUFFER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_BUFFER, UfoBufferPrivate)) -#define UFO_BUFFER_ERROR ufo_buffer_error_quark() - - enum { PROP_0, PROP_ID, @@ -31,15 +25,6 @@ enum { N_PROPERTIES }; -static GParamSpec *buffer_properties[N_PROPERTIES] = { NULL, }; - - -typedef enum { - NO_DATA = 0, - HOST_ARRAY_VALID, - DEVICE_ARRAY_VALID -} data_location; - typedef struct { guint num_dims; gfloat *data; @@ -48,574 +33,360 @@ typedef struct { } nd_array; struct _UfoBufferPrivate { - nd_array host_array; - cl_mem device_array; - data_location location; - - gint id; /**< unique id that is passed to the transformed buffer */ - gsize size; /**< size of buffer in bytes */ - - cl_event *events; - cl_uint current_event_index; /**< index of currently available event position */ - cl_uint num_total_events; /**< total amount of events we can keep */ - - GTimer *timer; /**< holds elapsed time for up/download */ - cl_ulong time_upload; - cl_ulong time_download; + nd_array host_array; + cl_mem device_array; + cl_context context; + cl_command_queue last_queue; + gsize size; /**< size of buffer in bytes */ + UfoMemLocation location; + GTimer *timer; }; -/** - * UfoBufferError: - * @UFO_BUFFER_ERROR_WRONG_SIZE: Wrongly sized array passed to the buffer - * - * Possible errors when using a UfoBuffer. - */ -GQuark ufo_buffer_error_quark(void) -{ - return g_quark_from_static_string("ufo-buffer-error-quark"); -} - static void -ufo_buffer_set_dimensions(UfoBuffer *buffer, guint num_dims, const guint *dim_size) +alloc_mem (UfoBufferPrivate *priv, + UfoRequisition *requisition) { - g_return_if_fail (UFO_IS_BUFFER(buffer)); - g_return_if_fail ((num_dims > 0) && (num_dims <= UFO_BUFFER_MAX_NDIMS)); - g_return_if_fail (dim_size != NULL); + cl_int err; + + if (priv->host_array.data != NULL) + g_free (priv->host_array.data); + + if (priv->device_array != NULL) + clReleaseMemObject (priv->device_array); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); priv->size = sizeof(gfloat); - priv->host_array.num_dims = num_dims; + priv->host_array.num_dims = requisition->n_dims; - for (guint i = 0; i < num_dims; i++) { - priv->host_array.dim_size[i] = dim_size[i]; - priv->size *= dim_size[i]; + for (guint i = 0; i < requisition->n_dims; i++) { + priv->host_array.dim_size[i] = requisition->dims[i]; + priv->size *= requisition->dims[i]; } + + priv->host_array.data = g_malloc0 (priv->size); + priv->device_array = clCreateBuffer (priv->context, + CL_MEM_READ_WRITE, /* XXX: we _should_ evaluate USE_HOST_PTR */ + priv->size, + NULL, + &err); + UFO_RESOURCES_CHECK_CLERR (err); + priv->location = UFO_LOCATION_HOST; } /** * ufo_buffer_new: - * @num_dims: (in): Number of dimensions - * @dim_size: (in) (array): Size of each dimension - * - * Create a new buffer with the given dimensions. + * @requisition: (in): size requisition + * @context: (in): cl_context to use for creating the device array * * Return value: A new #UfoBuffer with the given dimensions. */ UfoBuffer * -ufo_buffer_new (guint num_dims, const guint *dim_size) +ufo_buffer_new (UfoRequisition *requisition, + gpointer context) { - g_return_val_if_fail ((num_dims <= UFO_BUFFER_MAX_NDIMS) && (dim_size != NULL), NULL); - UfoBuffer *buffer = UFO_BUFFER (g_object_new (UFO_TYPE_BUFFER, NULL)); - ufo_buffer_set_dimensions (buffer, num_dims, dim_size); + UfoBuffer *buffer; + + g_return_val_if_fail ((requisition->n_dims <= UFO_BUFFER_MAX_NDIMS), NULL); + buffer = UFO_BUFFER (g_object_new (UFO_TYPE_BUFFER, NULL)); + buffer->priv->context = context; + + alloc_mem (buffer->priv, requisition); return buffer; } -/** - * ufo_buffer_alloc_host_mem: - * @buffer: A #UfoBuffer object - * - * Allocate host memory for dimensions specified in ufo_buffer_new(). - * - * Since: 0.2 - */ -void -ufo_buffer_alloc_host_mem (UfoBuffer *buffer) +gsize +ufo_buffer_get_size (UfoBuffer *buffer) { - UfoBufferPrivate *priv; - - g_return_if_fail (UFO_IS_BUFFER (buffer)); - priv = UFO_BUFFER_GET_PRIVATE (buffer); - - if (priv->host_array.data != NULL) - g_free (priv->host_array.data); - - priv->host_array.data = g_malloc0(priv->size); + g_return_val_if_fail (UFO_IS_BUFFER (buffer), 0); + return buffer->priv->size; } -/** - * ufo_buffer_copy: - * @src: Source #UfoBuffer - * @dst: Destination #UfoBuffer - * - * Copy the contents of %src into %dst. - * - * Since: 0.2 - */ -void -ufo_buffer_copy (UfoBuffer *src, UfoBuffer *dst) +static void +copy_host_to_host (UfoBufferPrivate *src_priv, + UfoBufferPrivate *dst_priv) { - g_return_if_fail (UFO_IS_BUFFER (src) && UFO_IS_BUFFER (dst)); - g_return_if_fail (src->priv->size == dst->priv->size); + g_memmove (dst_priv->host_array.data, + src_priv->host_array.data, + src_priv->size); +} - if (src->priv->location != HOST_ARRAY_VALID) { - g_warning ("Copying source buffers with invalid or device memory not yet supported"); - return; - } +static void +copy_device_to_device (UfoBufferPrivate *src_priv, + UfoBufferPrivate *dst_priv) +{ + cl_event event; - if (dst->priv->host_array.data == NULL) - ufo_buffer_alloc_host_mem (dst); + clEnqueueCopyBuffer (NULL, + src_priv->device_array, + dst_priv->device_array, + 0, 0, /* offsets */ + src_priv->size, + 0, NULL, &event); - g_memmove (dst->priv->host_array.data, src->priv->host_array.data, src->priv->size); - dst->priv->location = HOST_ARRAY_VALID; + clWaitForEvents (1, &event); + clReleaseEvent (event); } -/** - * ufo_buffer_resize: - * @buffer: A #UfoBuffer - * @num_dims: New number of dimensions - * @dim_size: New dimension sizes - * - * Resize an existing buffer. - * Since: 0.2 - */ -void -ufo_buffer_resize (UfoBuffer *buffer, guint num_dims, const guint *dim_size) +static void +ufo_buffer_to_host (UfoBuffer *buffer, gpointer cmd_queue) { UfoBufferPrivate *priv; + cl_int cl_err; + cl_command_queue queue; - g_return_if_fail ((num_dims <= UFO_BUFFER_MAX_NDIMS) && (dim_size != NULL)); + g_return_if_fail (UFO_IS_BUFFER (buffer)); + priv = buffer->priv; - ufo_buffer_set_dimensions (buffer, num_dims, dim_size); - priv = UFO_BUFFER_GET_PRIVATE (buffer); + if (priv->location == UFO_LOCATION_HOST) + return; - if (priv->host_array.data != NULL) { - g_free (priv->host_array.data); - priv->host_array.data = NULL; - } + queue = cmd_queue == NULL ? priv->last_queue : cmd_queue; + priv->last_queue = cmd_queue; - if (priv->device_array != NULL) { - CHECK_OPENCL_ERROR (clReleaseMemObject (priv->device_array)); - priv->device_array = NULL; - } + cl_err = clEnqueueReadBuffer (queue, + priv->device_array, + CL_TRUE, + 0, priv->size, + priv->host_array.data, + 0, NULL, NULL); + + priv->location = UFO_LOCATION_HOST; + UFO_RESOURCES_CHECK_CLERR (cl_err); } -/** - * ufo_buffer_get_dimensions: - * @buffer: A #UfoBuffer - * @num_dims: (out): Location to store the number of dimensions. - * @dim_size: (out): Location to store the dimensions. If *dim_size is NULL - * enough space is allocated to hold num_dims elements and should be freed - * with g_free(). If *dim_size is NULL, the caller must provide enough - * memory. - * - * Retrieve dimensions of buffer. - */ -void -ufo_buffer_get_dimensions(UfoBuffer *buffer, guint *num_dims, guint **dim_size) +static void +ufo_buffer_to_device (UfoBuffer *buffer, gpointer cmd_queue) { - g_return_if_fail(UFO_IS_BUFFER(buffer) || (num_dims == NULL) || (dim_size == NULL)); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); + UfoBufferPrivate *priv; + cl_int cl_err; + cl_command_queue queue; - *num_dims = priv->host_array.num_dims; + g_return_if_fail (UFO_IS_BUFFER (buffer)); + priv = buffer->priv; - if (*dim_size == NULL) - *dim_size = g_malloc0(sizeof(guint) * (*num_dims)); + if (priv->location == UFO_LOCATION_DEVICE) + return; - g_memmove(*dim_size, priv->host_array.dim_size, sizeof(guint) * (*num_dims)); -} + queue = cmd_queue == NULL ? priv->last_queue : cmd_queue; + priv->last_queue = cmd_queue; -/** - * ufo_buffer_get_size: - * @buffer: A #UfoBuffer - * - * Get size of internal data in bytes. - * - * Return value: Size of data - */ -gsize -ufo_buffer_get_size(UfoBuffer *buffer) -{ - g_return_val_if_fail(UFO_IS_BUFFER(buffer), 0); - return buffer->priv->size; -} + cl_err = clEnqueueWriteBuffer ((cl_command_queue) queue, + priv->device_array, + CL_TRUE, + 0, priv->size, + priv->host_array.data, + 0, NULL, NULL); -/** - * ufo_buffer_get_id: - * @buffer: A #UfoBuffer - * - * Get internal identification. - * - * Return value: unique and monotone id - */ -gint -ufo_buffer_get_id(UfoBuffer *buffer) -{ - g_return_val_if_fail(UFO_IS_BUFFER(buffer), -1); - return buffer->priv->id; + priv->location = UFO_LOCATION_DEVICE; + UFO_RESOURCES_CHECK_CLERR (cl_err); } /** - * ufo_buffer_transfer_id: - * @from: A #UfoBuffer whose id is copied. - * @to: UfoBuffer who gets this id + * ufo_buffer_copy: + * @src: Source #UfoBuffer + * @dst: Destination #UfoBuffer * - * Transfer id from one buffer to another. + * Copy contents of @src to @dst. The final memory location is determined by the + * destination buffer. */ void -ufo_buffer_transfer_id(UfoBuffer *from, UfoBuffer *to) +ufo_buffer_copy (UfoBuffer *src, UfoBuffer *dst) { - g_return_if_fail(UFO_IS_BUFFER(from) || (UFO_IS_BUFFER(to))); - to->priv->id = from->priv->id; -} + g_return_if_fail (UFO_IS_BUFFER (src) && UFO_IS_BUFFER (dst)); + g_return_if_fail (src->priv->size == dst->priv->size); -/** - * ufo_buffer_get_2d_dimensions: - * @buffer: A #UfoBuffer. - * @width: (out): Location to store the width of the buffer - * @height: (out): Location to store the height of the buffer - * - * Convenience function to retrieve dimension of buffer. - */ -void -ufo_buffer_get_2d_dimensions(UfoBuffer *buffer, guint *width, guint *height) -{ - g_return_if_fail(UFO_IS_BUFFER(buffer) || (width != NULL) || (height != NULL)); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); - *width = priv->host_array.dim_size[0]; - *height = priv->host_array.dim_size[1]; + /* Copy depending on location */ + if (src->priv->location == dst->priv->location) { + switch (src->priv->location) { + case UFO_LOCATION_HOST: + copy_host_to_host (src->priv, dst->priv); + break; + case UFO_LOCATION_DEVICE: + copy_device_to_device (src->priv, dst->priv); + break; + default: + g_warning ("oops, we should not copy invalid data"); + } + } + else { + if (dst->priv->location == UFO_LOCATION_HOST) { + ufo_buffer_to_host (src, NULL); + copy_host_to_host (src->priv, dst->priv); + } + else { + ufo_buffer_to_device (src, NULL); + copy_device_to_device (src->priv, src->priv); + } + } } /** - * ufo_buffer_invalidate_gpu_data: - * @buffer: A #UfoBuffer. + * ufo_buffer_dup: + * @buffer: A #UfoBuffer * - * Invalidate state of a buffer so that Data won't be synchronized between CPU - * and GPU and must be re-set again with ufo_buffer_set_cpu_data. - */ -void -ufo_buffer_invalidate_gpu_data(UfoBuffer *buffer) -{ - g_return_if_fail(UFO_IS_BUFFER(buffer)); - buffer->priv->location = HOST_ARRAY_VALID; -} - -/** - * ufo_buffer_reinterpret: - * @buffer: A #UfoBuffer. - * @source_depth: The number of bits that make up the original integer data type. - * @num_pixels: Number of pixels to consider - * @normalize: Normalize image data to range [0.0, 1.0] + * Create a new buffer with the same requisition as @buffer. Note, that this is + * not a copy of @buffer! * - * The fundamental data type of a UfoBuffer is one single-precision floating - * point per pixel. To increase performance it is possible to load arbitrary - * integer into the host array returned by ufo_buffer_get_host_array() and - * convert that data with this method. + * Returns: A #UfoBuffer with the same size as @buffer. */ -void -ufo_buffer_reinterpret(UfoBuffer *buffer, gsize source_depth, gsize num_pixels, gboolean normalize) +UfoBuffer * +ufo_buffer_dup (UfoBuffer *buffer) { - g_return_if_fail (UFO_IS_BUFFER(buffer)); - gfloat *dst = buffer->priv->host_array.data; - - /* To save a memory allocation and several copies, we process data from back - * to front. This is possible if src bit depth is at most half as wide as - * the 32-bit target buffer. The processor cache should not be a problem. */ - if (source_depth == 8) { - guint8 *src = (guint8 *) buffer->priv->host_array.data; - const float scale = normalize ? 255.0f : 1.0f; - - for (gint index = (((gint) num_pixels) - 1); index >= 0; index--) - dst[index] = ((gfloat) src[index]) / scale; - } - else if (source_depth == 16) { - guint16 *src = (guint16 *) buffer->priv->host_array.data; - const float scale = normalize ? 65535.0f : 1.0f; + UfoBuffer *copy; + UfoRequisition requisition; - for (gint index = (((gint) num_pixels) - 1); index >= 0; index--) - dst[index] = ((gfloat) src[index]) / scale; - } + ufo_buffer_get_requisition (buffer, &requisition); + copy = ufo_buffer_new (&requisition, buffer->priv->context); + return copy; } /** - * ufo_buffer_fill_with_value: - * @buffer: A #UfoBuffer. - * @value: Buffer is filled with this value + * ufo_buffer_resize: + * @buffer: A #UfoBuffer + * @requisition: A #UfoRequisition structure * - * Fill buffer with the same value. + * Resize an existing buffer. If the new requisition has the same size as + * before, resizing is a no-op. + * + * Since: 0.2 */ -void ufo_buffer_fill_with_value (UfoBuffer* buffer, gfloat value) +void +ufo_buffer_resize (UfoBuffer *buffer, + UfoRequisition *requisition) { UfoBufferPrivate *priv; - gfloat *data; - guint n_elements = 1; - g_return_if_fail (UFO_IS_BUFFER(buffer)); + g_return_if_fail (UFO_IS_BUFFER (buffer)); priv = UFO_BUFFER_GET_PRIVATE (buffer); - data = ufo_buffer_get_host_array (buffer, NULL); - for (guint i = 0; i < priv->host_array.num_dims; i++) - n_elements *= priv->host_array.dim_size[i]; + if (priv->host_array.data != NULL) { + g_free (priv->host_array.data); + priv->host_array.data = NULL; + } - for (guint i = 0; i < n_elements; i++) - data[i] = value; + if (priv->device_array != NULL) { + UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->device_array)); + priv->device_array = NULL; + } - priv->location = HOST_ARRAY_VALID; + alloc_mem (priv, requisition); } /** - * ufo_buffer_set_cl_mem: - * @buffer: A #UfoBuffer. - * @mem: A cl_mem object. + * ufo_buffer_cmp_dimensions: + * @buffer: A #UfoBuffer + * @requisition: #UfoRequisition * - * Set OpenCL memory object that is used to up and download data. + * Compare the size of @buffer with a given @requisition. + * + * Returns: value < 0, 0 or > 0 if requisition is smaller, equal or larger. */ -void -ufo_buffer_set_cl_mem(UfoBuffer *buffer, gpointer mem) +gint +ufo_buffer_cmp_dimensions (UfoBuffer *buffer, + UfoRequisition *requisition) { - g_return_if_fail (UFO_IS_BUFFER(buffer) || (mem != NULL)); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE (buffer); - cl_mem mem_object = (cl_mem) mem; - gsize mem_size; + gint result; + g_return_val_if_fail (UFO_IS_BUFFER(buffer), FALSE); - CHECK_OPENCL_ERROR (clGetMemObjectInfo (mem_object, CL_MEM_SIZE, sizeof(gsize), &mem_size, NULL)); + result = 0; - if (mem_size != priv->size) - g_warning ("Buffer size is different from OpenCL memory object size"); - - priv->device_array = (cl_mem) mem_object; -} - -/** - * ufo_buffer_attach_event: - * @buffer: A #UfoBuffer. - * @event: A cl_event object. - * - * Attach an OpenCL event to a buffer that must be finished before anything else - * can be done with this buffer. - */ -void -ufo_buffer_attach_event(UfoBuffer *buffer, gpointer event) -{ - g_return_if_fail(UFO_IS_BUFFER(buffer) || (event != NULL)); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); - priv->events[priv->current_event_index++] = (cl_event) event; - - if (priv->current_event_index == priv->num_total_events) { - priv->num_total_events *= 2; - priv->events = g_realloc(priv->events, priv->num_total_events * sizeof(cl_event)); - g_debug("Reallocated event array to %i elements\n", priv->num_total_events); + for (guint i = 0; i < buffer->priv->host_array.num_dims; i++) { + gint req_dim = (gint) requisition->dims[i]; + gint host_dim = (gint) buffer->priv->host_array.dim_size[i]; + result += req_dim - host_dim; } -} -/** - * ufo_buffer_get_events: - * @buffer: A #UfoBuffer. - * @events: (out) (transfer none): Location to store pointer of events. - * @num_events: (out): Location to store the length of the event array. - * - * Return events currently associated with a buffer but don't release them from - * this buffer. - */ -void -ufo_buffer_get_events(UfoBuffer *buffer, gpointer **events, guint *num_events) -{ - g_return_if_fail(UFO_IS_BUFFER(buffer) || (events != NULL) || (num_events != NULL)); - *num_events = buffer->priv->current_event_index; - *events = (gpointer *) buffer->priv->events; + return result; } /** - * ufo_buffer_clear_events: - * @buffer: A #UfoBuffer. + * ufo_buffer_get_requisition: + * @buffer: A #UfoBuffer + * @requisition: (out): A location to store the requisition of @buffer * - * Clear and release events associated with a buffer + * Return the size of @buffer. */ void -ufo_buffer_clear_events(UfoBuffer *buffer) +ufo_buffer_get_requisition (UfoBuffer *buffer, + UfoRequisition *requisition) { - g_return_if_fail(UFO_IS_BUFFER(buffer)); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); + UfoBufferPrivate *priv; - for (guint i = 0; i < priv->current_event_index; i++) - clReleaseEvent(priv->events[i]); + g_return_if_fail (UFO_IS_BUFFER (buffer) && (requisition != NULL)); + priv = buffer->priv; + requisition->n_dims = priv->host_array.num_dims; - priv->current_event_index = 0; -} - -/** - * ufo_buffer_get_transfer_timer: (skip) - * @buffer: A #UfoBuffer. - * - * Each buffer has a timer object that measures time spent for transfering data - * between host and device. - * - * Returns: A #GTimer associated with this buffer - */ -GTimer * -ufo_buffer_get_transfer_timer(UfoBuffer *buffer) -{ - g_return_val_if_fail(UFO_IS_BUFFER(buffer), NULL); - return buffer->priv->timer; + for (guint i = 0; i < priv->host_array.num_dims; i++) + requisition->dims[i] = priv->host_array.dim_size[i]; } /** - * ufo_buffer_set_host_array: + * ufo_buffer_get_2d_dimensions: * @buffer: A #UfoBuffer. - * @data: User supplied data - * @num_bytes: Size of data in bytes - * @error: Pointer to GError* + * @width: (out): Location to store the width of the buffer + * @height: (out): Location to store the height of the buffer * - * Fill buffer with data. This method does not take ownership of data, it just - * copies the data off of it because we never know if there is enough memory to - * hold floats of that data. + * Convenience function to retrieve dimension of buffer. */ void -ufo_buffer_set_host_array(UfoBuffer *buffer, gfloat *data, gsize num_bytes, GError **error) +ufo_buffer_get_2d_dimensions (UfoBuffer *buffer, + guint *width, + guint *height) { - g_return_if_fail(UFO_IS_BUFFER(buffer) || (data != NULL)); - UfoBufferPrivate *priv = buffer->priv; - - if (num_bytes > priv->size) { - if (error != NULL) { - g_set_error(error, - UFO_BUFFER_ERROR, - UFO_BUFFER_ERROR_WRONG_SIZE, - "Trying to set more data than buffer dimensions allow"); - } - - return; - } - - if (priv->host_array.data == NULL) - ufo_buffer_alloc_host_mem (buffer); - - g_memmove(priv->host_array.data, data, num_bytes); - priv->location = HOST_ARRAY_VALID; + g_return_if_fail (UFO_IS_BUFFER(buffer) || (width != NULL) || (height != NULL)); + *width = buffer->priv->host_array.dim_size[0]; + *height = buffer->priv->host_array.dim_size[1]; } /** * ufo_buffer_get_host_array: * @buffer: A #UfoBuffer. - * @command_queue: A cl_command_queue object. + * @cmd_queue: (allow-none): A cl_command_queue object or %NULL. * * Returns a flat C-array containing the raw float data. * - * Return value: Float array. + * Returns: Float array. */ gfloat * -ufo_buffer_get_host_array(UfoBuffer *buffer, gpointer command_queue) +ufo_buffer_get_host_array (UfoBuffer *buffer, gpointer cmd_queue) { - g_return_val_if_fail(UFO_IS_BUFFER(buffer), NULL); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); - - switch (priv->location) { - case HOST_ARRAY_VALID: - /* This can be the case, when a buffer's device memory was invalidated - * but no host memory has been allocated before. */ - if (priv->host_array.data == NULL) - ufo_buffer_alloc_host_mem (buffer); - - break; - - case DEVICE_ARRAY_VALID: - if (priv->host_array.data == NULL) - ufo_buffer_alloc_host_mem (buffer); - - g_timer_start(priv->timer); - CHECK_OPENCL_ERROR(clEnqueueReadBuffer(command_queue, - priv->device_array, - CL_TRUE, - 0, priv->size, - priv->host_array.data, - 0, NULL, NULL)); - g_timer_stop(priv->timer); - /* TODO: Can we release the events here? */ - priv->current_event_index = 0; - priv->location = HOST_ARRAY_VALID; - break; - - case NO_DATA: - ufo_buffer_alloc_host_mem (buffer); - priv->location = HOST_ARRAY_VALID; - break; - } - - return priv->host_array.data; + g_return_val_if_fail (UFO_IS_BUFFER (buffer), NULL); + ufo_buffer_to_host (buffer, cmd_queue); + return buffer->priv->host_array.data; } /** - * ufo_buffer_get_device_array: (skip) - * @buffer: A #UfoBuffer - * @command_queue: A cl_command_queue object that is used to access the device - * memory. + * ufo_buffer_get_device_array: + * @buffer: A #UfoBuffer. + * @cmd_queue: (allow-none): A cl_command_queue object or %NULL. * - * Get OpenCL memory object that is used to up and download data. + * Return the current cl_mem object of @buffer. If the data is not yet in device + * memory, it is transfered via @cmd_queue to the object. If @cmd_queue is %NULL + * @cmd_queue, the last used command queue is used. * - * Return value: OpenCL memory object associated with this #UfoBuffer. + * Returns: A cl_mem object associated with @buffer. */ gpointer -ufo_buffer_get_device_array(UfoBuffer *buffer, gpointer command_queue) +ufo_buffer_get_device_array (UfoBuffer *buffer, gpointer cmd_queue) { - g_return_val_if_fail(UFO_IS_BUFFER(buffer) || (command_queue != NULL), NULL); - UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE(buffer); - cl_event event; - cl_int cl_err = CL_SUCCESS; - - switch (priv->location) { - case HOST_ARRAY_VALID: - if (priv->device_array == NULL) - priv->device_array = clCreateBuffer(NULL, CL_MEM_READ_WRITE, priv->size, NULL, &cl_err); - - CHECK_OPENCL_ERROR (cl_err); - - g_timer_start(priv->timer); - CHECK_OPENCL_ERROR(clEnqueueWriteBuffer((cl_command_queue) command_queue, - priv->device_array, - CL_TRUE, - 0, priv->size, - priv->host_array.data, - 0, NULL, &event)); - g_timer_stop(priv->timer); - priv->location = DEVICE_ARRAY_VALID; - break; - - case DEVICE_ARRAY_VALID: - break; - - case NO_DATA: - if (priv->device_array) { - priv->location = DEVICE_ARRAY_VALID; - break; - } - - return NULL; - } - - return priv->device_array; + g_return_val_if_fail (UFO_IS_BUFFER (buffer), NULL); + ufo_buffer_to_device (buffer, cmd_queue); + return buffer->priv->device_array; } /** - * ufo_buffer_swap_host_arrays: - * @a: A #UfoBuffer - * @b: A #UfoBuffer + * ufo_buffer_discard_location: + * @buffer: A #UfoBuffer + * @location: Location to discard * - * Swap host array pointers of @a and @b and mark host arrays valid. + * Discard @location and use "other" location without copying to it first. */ void -ufo_buffer_swap_host_arrays(UfoBuffer *a, UfoBuffer *b) +ufo_buffer_discard_location (UfoBuffer *buffer, + UfoMemLocation location) { - g_return_if_fail(UFO_IS_BUFFER(a) && UFO_IS_BUFFER(b)); - - UfoBufferPrivate *pa = a->priv; - UfoBufferPrivate *pb = b->priv; - - /* TODO: also check size of dimensions? */ - g_return_if_fail(pa->host_array.num_dims == pb->host_array.num_dims); - g_return_if_fail((pa->host_array.data != NULL) || (pb->host_array.data != NULL)); - - if (pa->host_array.data == NULL) - ufo_buffer_alloc_host_mem (a); - - if (pb->host_array.data == NULL) - ufo_buffer_alloc_host_mem (b); - - gfloat *tmp = pa->host_array.data; - pa->host_array.data = pb->host_array.data; - pb->host_array.data = tmp; - - pa->location = HOST_ARRAY_VALID; - pb->location = HOST_ARRAY_VALID; + g_return_if_fail (UFO_IS_BUFFER (buffer)); + buffer->priv->location = location == UFO_LOCATION_HOST ? UFO_LOCATION_DEVICE : UFO_LOCATION_HOST; } /** @@ -644,98 +415,54 @@ ufo_buffer_param_spec(const gchar *name, const gchar *nick, const gchar *blurb, return G_PARAM_SPEC(bspec); } - -static void -ufo_filter_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - UfoBuffer *buffer = UFO_BUFFER(object); - - switch (property_id) { - case PROP_ID: - buffer->priv->id = g_value_get_int(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -ufo_filter_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UfoBuffer *buffer = UFO_BUFFER(object); - - switch (property_id) { - case PROP_ID: - g_value_set_int(value, buffer->priv->id); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - static void -ufo_buffer_finalize(GObject *gobject) +ufo_buffer_finalize (GObject *gobject) { UfoBuffer *buffer = UFO_BUFFER (gobject); UfoBufferPrivate *priv = UFO_BUFFER_GET_PRIVATE (buffer); - if (priv->host_array.data != NULL) + if (priv->host_array.data != NULL) { g_free (priv->host_array.data); + priv->host_array.data = NULL; + } - if (priv->device_array != NULL) - CHECK_OPENCL_ERROR (clReleaseMemObject (priv->device_array)); - - priv->host_array.data = NULL; - priv->device_array = NULL; + if (priv->device_array != NULL) { + UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->device_array)); + priv->device_array = NULL; + } - g_timer_destroy(priv->timer); - g_free(priv->events); + if (priv->timer != NULL) { + g_timer_destroy (priv->timer); + priv->timer = NULL; + } G_OBJECT_CLASS(ufo_buffer_parent_class)->finalize(gobject); } static void -ufo_buffer_class_init(UfoBufferClass *klass) +ufo_buffer_class_init (UfoBufferClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->set_property = ufo_filter_set_property; - gobject_class->get_property = ufo_filter_get_property; gobject_class->finalize = ufo_buffer_finalize; - buffer_properties[PROP_ID] = - g_param_spec_int("id", - "ID of this buffer", - "ID of this buffer", - -1, G_MAXINT, 0, - G_PARAM_READWRITE); - - g_object_class_install_property(gobject_class, PROP_ID, buffer_properties[PROP_ID]); - g_type_class_add_private(klass, sizeof(UfoBufferPrivate)); } static void -ufo_buffer_init(UfoBuffer *buffer) +ufo_buffer_init (UfoBuffer *buffer) { UfoBufferPrivate *priv; buffer->priv = priv = UFO_BUFFER_GET_PRIVATE(buffer); - priv->id = -1; + priv->last_queue = NULL; priv->device_array = NULL; priv->host_array.data = NULL; priv->host_array.num_dims = 0; - priv->location = NO_DATA; - priv->current_event_index = 0; - priv->num_total_events = 8; - priv->events = g_malloc0(priv->num_total_events * sizeof(cl_event)); - priv->time_upload = 0; - priv->time_download = 0; - priv->timer = g_timer_new(); + priv->timer = g_timer_new (); + g_timer_stop (priv->timer); } static void -ufo_buffer_param_init(GParamSpec *pspec) +ufo_buffer_param_init (GParamSpec *pspec) { UfoBufferParamSpec *bspec = UFO_BUFFER_PARAM_SPEC(pspec); @@ -743,7 +470,7 @@ ufo_buffer_param_init(GParamSpec *pspec) } static void -ufo_buffer_param_set_default(GParamSpec *pspec, GValue *value) +ufo_buffer_param_set_default (GParamSpec *pspec, GValue *value) { UfoBufferParamSpec *bspec = UFO_BUFFER_PARAM_SPEC(pspec); diff --git a/src/ufo-buffer.h b/src/ufo-buffer.h index c9faeed..d0d504e 100644 --- a/src/ufo-buffer.h +++ b/src/ufo-buffer.h @@ -17,14 +17,22 @@ G_BEGIN_DECLS #define UFO_BUFFER_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_CAST((pspec), UFO_TYPE_PARAM_BUFFER, UfoBufferParamSpec)) #define UFO_BUFFER_ERROR ufo_buffer_error_quark() + typedef enum { UFO_BUFFER_ERROR_WRONG_SIZE } UfoBufferError; +typedef enum { + UFO_LOCATION_INVALID, + UFO_LOCATION_HOST, + UFO_LOCATION_DEVICE +} UfoMemLocation; + typedef struct _UfoBuffer UfoBuffer; typedef struct _UfoBufferClass UfoBufferClass; typedef struct _UfoBufferPrivate UfoBufferPrivate; typedef struct _UfoBufferParamSpec UfoBufferParamSpec; +typedef struct _UfoRequisition UfoRequisition; /** * UfoBuffer: @@ -46,7 +54,7 @@ struct _UfoBuffer { * of const variable because of <ulink * url="http://c-faq.com/ansi/constasconst.html">C constraints</ulink>. */ -#define UFO_BUFFER_MAX_NDIMS 32 +#define UFO_BUFFER_MAX_NDIMS 8 /** * UfoBufferClass: @@ -59,6 +67,18 @@ struct _UfoBufferClass { }; /** + * UfoRequisition: + * @n_dims: Number of dimensions + * @dims: Size of dimension + * + * Used to specify buffer size requirements. + */ +struct _UfoRequisition { + guint n_dims; + guint dims[UFO_BUFFER_MAX_NDIMS]; +}; + +/** * UfoBufferParamSpec: * * UfoBufferParamSpec class @@ -70,50 +90,27 @@ struct _UfoBufferParamSpec { UfoBuffer *default_value; }; -UfoBuffer* ufo_buffer_new (guint num_dims, - const guint *dim_size); -void ufo_buffer_alloc_host_mem (UfoBuffer *buffer); -void ufo_buffer_resize (UfoBuffer *buffer, - guint num_dims, - const guint *dim_size); -void ufo_buffer_copy (UfoBuffer *src, - UfoBuffer *dst); -void ufo_buffer_transfer_id (UfoBuffer *from, - UfoBuffer *to); -gsize ufo_buffer_get_size (UfoBuffer *buffer); -gint ufo_buffer_get_id (UfoBuffer *buffer); -void ufo_buffer_get_dimensions (UfoBuffer *buffer, - guint* num_dims, - guint** dim_size); -void ufo_buffer_get_2d_dimensions (UfoBuffer* buffer, - guint* width, - guint* height); -void ufo_buffer_reinterpret (UfoBuffer* buffer, - gsize source_depth, - gsize num_pixels, - gboolean normalize); -void ufo_buffer_fill_with_value (UfoBuffer* buffer, - gfloat value); -void ufo_buffer_set_host_array (UfoBuffer* buffer, - gfloat* data, - gsize num_bytes, - GError** error); -gfloat* ufo_buffer_get_host_array (UfoBuffer *buffer, - gpointer command_queue); -GTimer* ufo_buffer_get_transfer_timer (UfoBuffer *buffer); -void ufo_buffer_swap_host_arrays (UfoBuffer *a, - UfoBuffer *b); -gpointer ufo_buffer_get_device_array (UfoBuffer *buffer, - gpointer command_queue); -void ufo_buffer_invalidate_gpu_data (UfoBuffer* buffer); -void ufo_buffer_set_cl_mem (UfoBuffer* buffer, - gpointer mem); -void ufo_buffer_attach_event (UfoBuffer* buffer, - gpointer event); -void ufo_buffer_get_events (UfoBuffer* buffer, - gpointer** events, - guint* num_events); -void ufo_buffer_clear_events (UfoBuffer* buffer); +UfoBuffer* ufo_buffer_new (UfoRequisition *requisition, + gpointer context); +void ufo_buffer_resize (UfoBuffer *buffer, + UfoRequisition *requisition); +gint ufo_buffer_cmp_dimensions (UfoBuffer *buffer, + UfoRequisition *requisition); +void ufo_buffer_get_requisition (UfoBuffer *buffer, + UfoRequisition *requisition); +gsize ufo_buffer_get_size (UfoBuffer *buffer); +void ufo_buffer_get_2d_dimensions (UfoBuffer *buffer, + guint *width, + guint *height); +void ufo_buffer_copy (UfoBuffer *src, + UfoBuffer *dst); +UfoBuffer *ufo_buffer_dup (UfoBuffer *buffer); +gfloat* ufo_buffer_get_host_array (UfoBuffer *buffer, + gpointer cmd_queue); +gpointer ufo_buffer_get_device_array (UfoBuffer *buffer, + gpointer cmd_queue); +void ufo_buffer_discard_location (UfoBuffer *buffer, + UfoMemLocation location); GType ufo_buffer_get_type (void); GQuark ufo_buffer_error_quark (void); diff --git a/src/ufo-channel.c b/src/ufo-channel.c deleted file mode 100644 index df5d0d6..0000000 --- a/src/ufo-channel.c +++ /dev/null @@ -1,259 +0,0 @@ -/** - * SECTION:ufo-channel - * @Short_description: Data transport between two UfoFilters - * @Title: UfoChannel - * - * A channel encapsulates the data transfer from one filter that outputs data to - * one that receives that as an input. Channels can be daisy-chained so that the - * second channel receives the same data as the first one. - */ - -#include <string.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-resource-manager.h" -#include "ufo-channel.h" - -G_DEFINE_TYPE(UfoChannel, ufo_channel, G_TYPE_OBJECT) - -#define UFO_CHANNEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_CHANNEL, UfoChannelPrivate)) - -struct _UfoChannelPrivate { - gint ref_count; - GAsyncQueue *input_queue; - GAsyncQueue *output_queue; - UfoChannel *next; -}; - -/** - * ufo_channel_new: - * - * Creates a new #UfoChannel. - * - * Return value: A new #UfoChannel - */ -UfoChannel * -ufo_channel_new (void) -{ - UfoChannel *channel = UFO_CHANNEL (g_object_new (UFO_TYPE_CHANNEL, NULL)); - return channel; -} - -/** - * ufo_channel_ref: - * @channel: A #UfoChannel - * - * Reference a channel if to be used as an output. - */ -void -ufo_channel_ref (UfoChannel *channel) -{ - g_return_if_fail (UFO_IS_CHANNEL (channel)); - g_atomic_int_inc (&channel->priv->ref_count); -} - -/** - * ufo_channel_finish: - * @channel: A #UfoChannel - * - * Finish using this channel and notify subsequent filters that no more - * data can be expected. - */ -void -ufo_channel_finish (UfoChannel *channel) -{ - UfoChannelPrivate *priv; - - g_return_if_fail (UFO_IS_CHANNEL (channel)); - priv = UFO_CHANNEL_GET_PRIVATE (channel); - - for (gint i = 0; i < priv->ref_count; i++) - g_async_queue_push (priv->input_queue, GINT_TO_POINTER (1)); -} - -/** - * ufo_channel_finish_next: - * @channel: A #UfoChannel - * - * Finish using this channel. If @channel has a daisy-chained channel, it will - * also be finished. - */ -void -ufo_channel_finish_next (UfoChannel *channel) -{ - UfoChannelPrivate *priv; - - g_return_if_fail (UFO_IS_CHANNEL (channel)); - priv = UFO_CHANNEL_GET_PRIVATE (channel); - - ufo_channel_finish (channel); - - if (priv->next != NULL) - ufo_channel_finish (priv->next); -} - -/** - * ufo_channel_insert: - * @channel: A #UfoChannel - * @buffer: A #UfoBuffer to be inserted - * - * Inserts an initial @buffer that can be consumed with - * ufo_channel_fetch_output(). - */ -void -ufo_channel_insert (UfoChannel *channel, - UfoBuffer *buffer) -{ - g_return_if_fail (UFO_IS_CHANNEL (channel)); - - if (channel->priv->next != NULL) { - UfoChannel *next = channel->priv->next; - - while (next->priv->next != NULL) - next = next->priv->next; - - g_async_queue_push (next->priv->output_queue, buffer); - } - else - g_async_queue_push (channel->priv->output_queue, buffer); -} - -/** - * ufo_channel_fetch_input: (skip) - * @channel: A #UfoChannel - * - * Get a new buffer from the channel that can be consumed as an input. This - * method blocks execution as long as no new input buffer the available from the - * preceding filter. Use ufo_channel_release_input() to return the buffer to the - * channel. - * - * Return value: The next #UfoBuffer input - */ -UfoBuffer * -ufo_channel_fetch_input (UfoChannel *channel) -{ - g_return_val_if_fail (UFO_IS_CHANNEL (channel), NULL); - return g_async_queue_pop (channel->priv->input_queue); -} - -/** - * ufo_channel_release_input: - * @channel: A #UfoChannel - * @buffer: A #UfoBuffer acquired with ufo_channel_fetch_input() - * - * Release a buffer that was acquired with ufo_channel_fetch_input(). - */ -void -ufo_channel_release_input (UfoChannel *channel, UfoBuffer *buffer) -{ - g_return_if_fail (UFO_IS_CHANNEL (channel)); - - if (channel->priv->next != NULL) - g_async_queue_push (channel->priv->next->priv->input_queue, buffer); - else - g_async_queue_push (channel->priv->output_queue, buffer); -} - -/** - * ufo_channel_fetch_output: (skip) - * @channel: A #UfoChannel - * - * Get a new buffer from the channel that can be consumed as an output. This - * method blocks execution as long as no new input buffer the available from the - * successing filter. Use ufo_channel_release_output() to return the buffer to - * the channel. - * - * Return value: The next #UfoBuffer for output - */ -UfoBuffer * -ufo_channel_fetch_output (UfoChannel *channel) -{ - UfoChannel *next; - - g_return_val_if_fail (UFO_IS_CHANNEL (channel), NULL); - - next = channel->priv->next; - - if (next == NULL) { - return g_async_queue_pop (channel->priv->output_queue); - } - else { - while (next->priv->next != NULL) - next = next->priv->next; - - return g_async_queue_pop (next->priv->output_queue); - } -} - -/** - * ufo_channel_release_output: - * @channel: A #UfoChannel - * @buffer: A #UfoBuffer acquired with ufo_channel_fetch_output() - * - * Release a buffer that was acquired with ufo_channel_fetch_output(). - */ -void -ufo_channel_release_output (UfoChannel *channel, UfoBuffer *buffer) -{ - g_return_if_fail (UFO_IS_CHANNEL (channel) && UFO_IS_BUFFER (buffer)); - g_async_queue_push (channel->priv->input_queue, buffer); -} - -/** - * ufo_channel_daisy_chain: - * @channel: A #UfoChannel - * @next: A #UfoChannel that is appended to @channel - * - * Appends @next to @channel, so that both become siblings and share the same - * input. You should not use this function directly as it makes most sense for - * the scheduler when connecting to filters. - */ -void ufo_channel_daisy_chain (UfoChannel *channel, - UfoChannel *next) -{ - g_return_if_fail (UFO_IS_CHANNEL (channel) && UFO_IS_CHANNEL (next)); - channel->priv->next = next; -} - -static void -ufo_channel_dispose (GObject *object) -{ - G_OBJECT_CLASS (ufo_channel_parent_class)->dispose (object); -} - -static void -ufo_channel_finalize (GObject *object) -{ - UfoChannelPrivate *priv = UFO_CHANNEL_GET_PRIVATE (object); - - g_async_queue_unref (priv->input_queue); - g_async_queue_unref (priv->output_queue); - - G_OBJECT_CLASS (ufo_channel_parent_class)->finalize (object); -} - -static void -ufo_channel_class_init (UfoChannelClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->dispose = ufo_channel_dispose; - gobject_class->finalize = ufo_channel_finalize; - g_type_class_add_private (klass, sizeof (UfoChannelPrivate)); -} - -static void -ufo_channel_init (UfoChannel *channel) -{ - UfoChannelPrivate *priv; - channel->priv = priv = UFO_CHANNEL_GET_PRIVATE (channel); - - priv->ref_count = 0; - priv->input_queue = g_async_queue_new (); - priv->output_queue = g_async_queue_new (); - priv->next = NULL; -} diff --git a/src/ufo-channel.h b/src/ufo-channel.h deleted file mode 100644 index 2d14b1b..0000000 --- a/src/ufo-channel.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __UFO_CHANNEL_H -#define __UFO_CHANNEL_H - -#include <glib-object.h> -#include "ufo-buffer.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_CHANNEL (ufo_channel_get_type()) -#define UFO_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_CHANNEL, UfoChannel)) -#define UFO_IS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_CHANNEL)) -#define UFO_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_CHANNEL, UfoChannelClass)) -#define UFO_IS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_CHANNEL)) -#define UFO_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_CHANNEL, UfoChannelClass)) - -typedef struct _UfoChannel UfoChannel; -typedef struct _UfoChannelClass UfoChannelClass; -typedef struct _UfoChannelPrivate UfoChannelPrivate; - -/** - * UfoChannel: - * - * Data transport channel between two #UfoFilter objects. The contents of the - * #UfoChannel structure are private and should only be accessed via the - * provided API. - */ -struct _UfoChannel { - /*< private >*/ - GObject parent_instance; - - UfoChannelPrivate *priv; -}; - -/** - * UfoChannelClass: - * - * #UfoChannel class - */ -struct _UfoChannelClass { - /*< private >*/ - GObjectClass parent_class; -}; - -UfoChannel *ufo_channel_new (void); -void ufo_channel_ref (UfoChannel *channel); -void ufo_channel_finish (UfoChannel *channel); -void ufo_channel_finish_next (UfoChannel *channel); -void ufo_channel_insert (UfoChannel *channel, - UfoBuffer *buffer); -UfoBuffer * ufo_channel_fetch_input (UfoChannel *channel); -void ufo_channel_release_input (UfoChannel *channel, - UfoBuffer *buffer); -UfoBuffer * ufo_channel_fetch_output (UfoChannel *channel); -void ufo_channel_release_output (UfoChannel *channel, - UfoBuffer *buffer); -void ufo_channel_daisy_chain (UfoChannel *channel, - UfoChannel *next); -GType ufo_channel_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-configuration.c b/src/ufo-config.c index cf5c766..fac2e32 100644 --- a/src/ufo-configuration.c +++ b/src/ufo-config.c @@ -1,23 +1,22 @@ /** - * SECTION:ufo-configuration + * SECTION:ufo-config * @Short_description: Access run-time specific settings - * @Title: UfoConfiguration + * @Title: UfoConfig * - * A #UfoConfiguration object is used to keep settings that affect the run-time + * A #UfoConfig object is used to keep settings that affect the run-time * rather than the parameters of the filter graph. Each object that implements - * the #UfoConfigurable interface can receive a #UfoConfiguration object and use + * the #UfoConfigurable interface can receive a #UfoConfig object and use * the information stored in it. */ -#include "ufo-configuration.h" -#include "ufo-profiler.h" -#include "ufo-enums.h" +#include <ufo-config.h> +#include <ufo-profiler.h> +#include <ufo-enums.h> #include "config.h" +G_DEFINE_TYPE(UfoConfig, ufo_config, G_TYPE_OBJECT) -G_DEFINE_TYPE(UfoConfiguration, ufo_configuration, G_TYPE_OBJECT) - -#define UFO_CONFIGURATION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_CONFIGURATION, UfoConfigurationPrivate)) +#define UFO_CONFIG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_CONFIG, UfoConfigPrivate)) enum { PROP_0, @@ -27,7 +26,7 @@ enum { N_PROPERTIES }; -struct _UfoConfigurationPrivate { +struct _UfoConfigPrivate { GValueArray *path_array; UfoProfilerLevel profile_level; gchar *profile_output_prefix; @@ -36,21 +35,21 @@ struct _UfoConfigurationPrivate { static GParamSpec *config_properties[N_PROPERTIES] = { NULL, }; /** - * ufo_configuration_new: + * ufo_config_new: * - * Create a configuration object. + * Create a config object. * - * Return value: A new configuration object. + * Return value: A new config object. */ -UfoConfiguration * -ufo_configuration_new (void) +UfoConfig * +ufo_config_new (void) { - return UFO_CONFIGURATION (g_object_new (UFO_TYPE_CONFIGURATION, NULL)); + return UFO_CONFIG (g_object_new (UFO_TYPE_CONFIG, NULL)); } /** - * ufo_configuration_get_paths: - * @config: A #UfoConfiguration object + * ufo_config_get_paths: + * @config: A #UfoConfig object * * Get an array of path strings. * @@ -59,13 +58,13 @@ ufo_configuration_new (void) * g_strfreev() to free it. */ gchar ** -ufo_configuration_get_paths (UfoConfiguration *config) +ufo_config_get_paths (UfoConfig *config) { GValueArray *path_array; gchar **paths; guint n_paths; - g_return_val_if_fail (UFO_IS_CONFIGURATION (config), NULL); + g_return_val_if_fail (UFO_IS_CONFIG (config), NULL); path_array = config->priv->path_array; n_paths = path_array->n_values; @@ -79,20 +78,20 @@ ufo_configuration_get_paths (UfoConfiguration *config) } /** - * ufo_configuration_add_path: - * @config: A #UfoConfiguration object + * ufo_config_add_path: + * @config: A #UfoConfig object * @path: A %NULL-terminated string denoting a path * * Add a path to the list of paths that are searched by #UfoPluginManager and * #UfoResourceManager. */ static void -ufo_configuration_add_path (UfoConfiguration *config, +ufo_config_add_path (UfoConfig *config, const gchar *path) { GValue path_value = {0}; - g_return_if_fail (UFO_IS_CONFIGURATION (config)); + g_return_if_fail (UFO_IS_CONFIG (config)); g_value_init (&path_value, G_TYPE_STRING); g_value_set_string (&path_value, path); @@ -101,12 +100,12 @@ ufo_configuration_add_path (UfoConfiguration *config, } static void -ufo_configuration_set_property(GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +ufo_config_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - UfoConfigurationPrivate *priv = UFO_CONFIGURATION_GET_PRIVATE (object); + UfoConfigPrivate *priv = UFO_CONFIG_GET_PRIVATE (object); switch (property_id) { case PROP_PATHS: @@ -139,12 +138,12 @@ ufo_configuration_set_property(GObject *object, } static void -ufo_configuration_get_property(GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) +ufo_config_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - UfoConfigurationPrivate *priv = UFO_CONFIGURATION_GET_PRIVATE (object); + UfoConfigPrivate *priv = UFO_CONFIG_GET_PRIVATE (object); switch (property_id) { case PROP_PATHS: @@ -166,34 +165,34 @@ ufo_configuration_get_property(GObject *object, } static void -ufo_configuration_dispose (GObject *object) +ufo_config_dispose (GObject *object) { - G_OBJECT_CLASS (ufo_configuration_parent_class)->finalize (object); - g_message ("UfoConfiguration: disposed"); + G_OBJECT_CLASS (ufo_config_parent_class)->finalize (object); + g_message ("UfoConfig: disposed"); } static void -ufo_configuration_finalize (GObject *object) +ufo_config_finalize (GObject *object) { - UfoConfigurationPrivate *priv = UFO_CONFIGURATION_GET_PRIVATE (object); + UfoConfigPrivate *priv = UFO_CONFIG_GET_PRIVATE (object); g_value_array_free (priv->path_array); - G_OBJECT_CLASS (ufo_configuration_parent_class)->finalize (object); - g_message ("UfoConfiguration: finalized"); + G_OBJECT_CLASS (ufo_config_parent_class)->finalize (object); + g_message ("UfoConfig: finalized"); } static void -ufo_configuration_class_init (UfoConfigurationClass *klass) +ufo_config_class_init (UfoConfigClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->set_property = ufo_configuration_set_property; - gobject_class->get_property = ufo_configuration_get_property; - gobject_class->dispose = ufo_configuration_dispose; - gobject_class->finalize = ufo_configuration_finalize; + gobject_class->set_property = ufo_config_set_property; + gobject_class->get_property = ufo_config_get_property; + gobject_class->dispose = ufo_config_dispose; + gobject_class->finalize = ufo_config_finalize; /** - * UfoConfiguration:paths: + * UfoConfig:paths: * * An array of strings with paths pointing to possible filter and kernel * file locations. @@ -210,7 +209,7 @@ ufo_configuration_class_init (UfoConfigurationClass *klass) G_PARAM_READWRITE); /** - * UfoConfiguration:profile-level: + * UfoConfig:profile-level: * * Controls the amount of profiling. * @@ -235,20 +234,20 @@ ufo_configuration_class_init (UfoConfigurationClass *klass) g_object_class_install_property (gobject_class, PROP_PROFILE_LEVEL, config_properties[PROP_PROFILE_LEVEL]); g_object_class_install_property (gobject_class, PROP_PROFILE_OUTPUT_PREFIX, config_properties[PROP_PROFILE_OUTPUT_PREFIX]); - g_type_class_add_private(klass, sizeof (UfoConfigurationPrivate)); + g_type_class_add_private(klass, sizeof (UfoConfigPrivate)); } static void -ufo_configuration_init (UfoConfiguration *config) +ufo_config_init (UfoConfig *config) { - config->priv = UFO_CONFIGURATION_GET_PRIVATE (config); + config->priv = UFO_CONFIG_GET_PRIVATE (config); config->priv->path_array = g_value_array_new (0); config->priv->profile_level = UFO_PROFILER_LEVEL_NONE; config->priv->profile_output_prefix = NULL; - ufo_configuration_add_path (config, LIB_FILTER_DIR); - ufo_configuration_add_path (config, "/usr/lib/ufo"); - ufo_configuration_add_path (config, "/usr/lib64/ufo"); - ufo_configuration_add_path (config, "/usr/local/lib/ufo"); - ufo_configuration_add_path (config, "/usr/local/lib64/ufo"); + ufo_config_add_path (config, LIB_FILTER_DIR); + ufo_config_add_path (config, "/usr/lib/ufo"); + ufo_config_add_path (config, "/usr/lib64/ufo"); + ufo_config_add_path (config, "/usr/local/lib/ufo"); + ufo_config_add_path (config, "/usr/local/lib64/ufo"); } diff --git a/src/ufo-config.h b/src/ufo-config.h new file mode 100644 index 0000000..caeeeca --- /dev/null +++ b/src/ufo-config.h @@ -0,0 +1,47 @@ +#ifndef __UFO_CONFIG_H +#define __UFO_CONFIG_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define UFO_TYPE_CONFIG (ufo_config_get_type()) +#define UFO_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_CONFIG, UfoConfig)) +#define UFO_IS_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_CONFIG)) +#define UFO_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_CONFIG, UfoConfigClass)) +#define UFO_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_CONFIG)) +#define UFO_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_CONFIG, UfoConfigClass)) + +typedef struct _UfoConfig UfoConfig; +typedef struct _UfoConfigClass UfoConfigClass; +typedef struct _UfoConfigPrivate UfoConfigPrivate; + +/** + * UfoConfig: + * + * A #UfoConfig provides access to run-time specific settings. + */ +struct _UfoConfig { + /*< private >*/ + GObject parent_instance; + + UfoConfigPrivate *priv; +}; + +/** + * UfoConfigClass: + * + * #UfoConfig class + */ +struct _UfoConfigClass { + /*< private >*/ + GObjectClass parent_class; +}; + +UfoConfig * ufo_config_new (void); +gchar ** ufo_config_get_paths (UfoConfig *config); +GType ufo_config_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-configurable.c b/src/ufo-configurable.c index fad31da..129af07 100644 --- a/src/ufo-configurable.c +++ b/src/ufo-configurable.c @@ -8,7 +8,7 @@ */ #include "ufo-configurable.h" -#include "ufo-configuration.h" +#include "ufo-config.h" typedef UfoConfigurableIface UfoConfigurableInterface; @@ -25,10 +25,10 @@ ufo_configurable_default_init (UfoConfigurableInterface *iface) * The #UfoConfiguration object that can be passed to all objects that * implement the #UfoConfigurable interface. */ - config_spec = g_param_spec_object ("configuration", - "A UfoConfiguration object", - "A UfoConfiguration object", - UFO_TYPE_CONFIGURATION, + config_spec = g_param_spec_object ("config", + "A UfoConfig object", + "A UfoConfig object", + UFO_TYPE_CONFIG, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); g_object_interface_install_property (iface, config_spec); diff --git a/src/ufo-configuration.h b/src/ufo-configuration.h deleted file mode 100644 index 97df392..0000000 --- a/src/ufo-configuration.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __UFO_CONFIGURATION_H -#define __UFO_CONFIGURATION_H - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define UFO_TYPE_CONFIGURATION (ufo_configuration_get_type()) -#define UFO_CONFIGURATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_CONFIGURATION, UfoConfiguration)) -#define UFO_IS_CONFIGURATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_CONFIGURATION)) -#define UFO_CONFIGURATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_CONFIGURATION, UfoConfigurationClass)) -#define UFO_IS_CONFIGURATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_CONFIGURATION)) -#define UFO_CONFIGURATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_CONFIGURATION, UfoConfigurationClass)) - -typedef struct _UfoConfiguration UfoConfiguration; -typedef struct _UfoConfigurationClass UfoConfigurationClass; -typedef struct _UfoConfigurationPrivate UfoConfigurationPrivate; - -/** - * UfoConfiguration: - * - * A #UfoConfiguration provides access to run-time specific settings. - */ -struct _UfoConfiguration { - /*< private >*/ - GObject parent_instance; - - UfoConfigurationPrivate *priv; -}; - -/** - * UfoConfigurationClass: - * - * #UfoConfiguration class - */ -struct _UfoConfigurationClass { - /*< private >*/ - GObjectClass parent_class; -}; - -UfoConfiguration * ufo_configuration_new (void); -gchar ** ufo_configuration_get_paths (UfoConfiguration *config); -GType ufo_configuration_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-cpu-node.c b/src/ufo-cpu-node.c new file mode 100644 index 0000000..05bb358 --- /dev/null +++ b/src/ufo-cpu-node.c @@ -0,0 +1,93 @@ +#define _GNU_SOURCE +#include <sched.h> +#include <ufo-cpu-node.h> + +G_DEFINE_TYPE (UfoCpuNode, ufo_cpu_node, UFO_TYPE_NODE) + +#define UFO_CPU_NODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_CPU_NODE, UfoCpuNodePrivate)) + + +struct _UfoCpuNodePrivate { + cpu_set_t *mask; +}; + +UfoNode * +ufo_cpu_node_new (gpointer mask) +{ + UfoCpuNode *node; + + g_return_val_if_fail (mask != NULL, NULL); + node = UFO_CPU_NODE (g_object_new (UFO_TYPE_CPU_NODE, NULL)); + node->priv->mask = g_memdup (mask, sizeof(cpu_set_t)); + return UFO_NODE (node); +} + +gpointer +ufo_cpu_node_get_affinity (UfoCpuNode *cpu_node) +{ + g_return_val_if_fail (UFO_IS_CPU_NODE (cpu_node), NULL); + return cpu_node->priv->mask; +} + +static void +ufo_cpu_node_finalize (GObject *object) +{ + UfoCpuNodePrivate *priv; + + priv = UFO_CPU_NODE_GET_PRIVATE (object); + + if (priv->mask) { + g_free (priv->mask); + priv->mask = NULL; + } + + G_OBJECT_CLASS (ufo_cpu_node_parent_class)->finalize (object); +} + +static UfoNode * +ufo_cpu_node_copy_real (UfoNode *node, + GError **error) +{ + return UFO_NODE (ufo_cpu_node_new (UFO_CPU_NODE (node)->priv->mask)); +} + +static gboolean +ufo_cpu_node_equal_real (UfoNode *n1, + UfoNode *n2) +{ + UfoCpuNodePrivate *priv1; + UfoCpuNodePrivate *priv2; + const gsize MAX_CPUS = MIN (16, CPU_SETSIZE); + + g_return_val_if_fail (UFO_IS_CPU_NODE (n1) && UFO_IS_CPU_NODE (n2), FALSE); + priv1 = UFO_CPU_NODE_GET_PRIVATE (n1); + priv2 = UFO_CPU_NODE_GET_PRIVATE (n2); + + for (gsize i = 0; i < MAX_CPUS; i++) { + if (CPU_ISSET (i, priv1->mask) != CPU_ISSET (i, priv2->mask)) + return FALSE; + } + + return TRUE; +} + +static void +ufo_cpu_node_class_init (UfoCpuNodeClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + UfoNodeClass *node_class = UFO_NODE_CLASS (klass); + + object_class->finalize = ufo_cpu_node_finalize; + node_class->copy = ufo_cpu_node_copy_real; + node_class->equal = ufo_cpu_node_equal_real; + + g_type_class_add_private(klass, sizeof(UfoCpuNodePrivate)); +} + +static void +ufo_cpu_node_init (UfoCpuNode *self) +{ + UfoCpuNodePrivate *priv; + self->priv = priv = UFO_CPU_NODE_GET_PRIVATE (self); + priv->mask = NULL; +} diff --git a/src/ufo-cpu-node.h b/src/ufo-cpu-node.h new file mode 100644 index 0000000..673c1ec --- /dev/null +++ b/src/ufo-cpu-node.h @@ -0,0 +1,49 @@ +#ifndef __UFO_CPU_NODE_H +#define __UFO_CPU_NODE_H + +#include <glib-object.h> +#include <ufo-node.h> + +G_BEGIN_DECLS + +#define UFO_TYPE_CPU_NODE (ufo_cpu_node_get_type()) +#define UFO_CPU_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_CPU_NODE, UfoCpuNode)) +#define UFO_IS_CPU_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_CPU_NODE)) +#define UFO_CPU_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_CPU_NODE, UfoCpuNodeClass)) +#define UFO_IS_CPU_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_CPU_NODE)) +#define UFO_CPU_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_CPU_NODE, UfoCpuNodeClass)) + +typedef struct _UfoCpuNode UfoCpuNode; +typedef struct _UfoCpuNodeClass UfoCpuNodeClass; +typedef struct _UfoCpuNodePrivate UfoCpuNodePrivate; + +/** + * UfoCpuNode: + * + * Main object for organizing filters. The contents of the #UfoCpuNode structure + * are private and should only be accessed via the provided API. + */ +struct _UfoCpuNode { + /*< private >*/ + UfoNode parent_instance; + + UfoCpuNodePrivate *priv; +}; + +/** + * UfoCpuNodeClass: + * + * #UfoCpuNode class + */ +struct _UfoCpuNodeClass { + /*< private >*/ + UfoNodeClass parent_class; +}; + +UfoNode *ufo_cpu_node_new (gpointer mask); +gpointer ufo_cpu_node_get_affinity (UfoCpuNode *cpu_node); +GType ufo_cpu_node_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-cpu-task-iface.c b/src/ufo-cpu-task-iface.c new file mode 100644 index 0000000..d0b6e38 --- /dev/null +++ b/src/ufo-cpu-task-iface.c @@ -0,0 +1,31 @@ +#include "ufo-cpu-task-iface.h" + +typedef UfoCpuTaskIface UfoCpuTaskInterface; + +G_DEFINE_INTERFACE (UfoCpuTask, ufo_cpu_task, UFO_TYPE_TASK) + + +gboolean +ufo_cpu_task_process (UfoCpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition) +{ + return UFO_CPU_TASK_GET_IFACE (task)->process (task, inputs, output, requisition); +} + +static gboolean +ufo_cpu_task_process_real (UfoCpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition) +{ + g_warning ("`process' of UfoCpuTaskInterface not implemented"); + return FALSE; +} + +static void +ufo_cpu_task_default_init (UfoCpuTaskInterface *iface) +{ + iface->process = ufo_cpu_task_process_real; +} diff --git a/src/ufo-cpu-task-iface.h b/src/ufo-cpu-task-iface.h new file mode 100644 index 0000000..3aa8712 --- /dev/null +++ b/src/ufo-cpu-task-iface.h @@ -0,0 +1,35 @@ +#ifndef UFO_CPU_TASK_IFACE_H +#define UFO_CPU_TASK_IFACE_H + +#include <glib-object.h> +#include "ufo-task-iface.h" +#include "ufo-buffer.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_CPU_TASK (ufo_cpu_task_get_type()) +#define UFO_CPU_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_CPU_TASK, UfoCpuTask)) +#define UFO_CPU_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_CPU_TASK, UfoCpuTaskIface)) +#define UFO_IS_CPU_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_CPU_TASK)) +#define UFO_IS_CPU_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_CPU_TASK)) +#define UFO_CPU_TASK_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), UFO_TYPE_CPU_TASK, UfoCpuTaskIface)) + +typedef struct _UfoCpuTask UfoCpuTask; +typedef struct _UfoCpuTaskIface UfoCpuTaskIface; + +struct _UfoCpuTaskIface { + UfoTaskIface parent_iface; + + gboolean (*process) (UfoCpuTask *task, UfoBuffer **inputs, UfoBuffer *output, UfoRequisition *requisition); +}; + +gboolean ufo_cpu_task_process (UfoCpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition); + +GType ufo_cpu_task_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-filter-reduce.c b/src/ufo-filter-reduce.c deleted file mode 100644 index a577c6c..0000000 --- a/src/ufo-filter-reduce.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * SECTION:ufo-filter-reduce - * @Short_description: A reduction filter accumulates one output from all inputs - * @Title: UfoFilterReduce - * - * A reduction filter takes an arbitrary number of data input and produces one - * output when the stream has finished. This scheme is useful for averaging the - * data stream or producing a volume from a series of projections. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-reduce.h" - -G_DEFINE_TYPE (UfoFilterReduce, ufo_filter_reduce, UFO_TYPE_FILTER) - -#define UFO_FILTER_REDUCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_REDUCE, UfoFilterReducePrivate)) - -/** - * ufo_filter_reduce_initialize: - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @output_dims: The size of each dimension for each output - * @default_value: The value to fill the output buffer - * @error: Location for #GError. - * - * This function calls the implementation for the virtual initialize method. The - * filter can use the input buffers as a hint to setup its own internal - * structures. Moreover, it needs to return size of each output dimension in - * each port as specified with ufo_filter_register_outputs(): - * <programlisting> - * // register a 1-dimensional and a 2-dimensional output in object::init - * ufo_filter_register_outputs (self, 1, 2, NULL); - * - * // specify sizes in object::initialize - * output_dim_sizes[0][0] = 1024; - * - * output_dim_sizes[1][0] = 640; - * output_dim_sizes[1][1] = 480; - * </programlisting> - * - * It also has to set a valid default value with which the output buffer is - * initialized. - * - * Since: 0.2 - */ -void -ufo_filter_reduce_initialize (UfoFilterReduce *filter, UfoBuffer *input[], guint **output_dims, gfloat *default_value, GError **error) -{ - g_return_if_fail (UFO_IS_FILTER_REDUCE (filter)); - UFO_FILTER_REDUCE_GET_CLASS (filter)->initialize (filter, input, output_dims, default_value, error); -} - -/** - * ufo_filter_reduce_collect: - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @output: An array of buffers for each output port - * @error: Location for #GError. - * - * Process input data. The output buffer array contains the same buffers on each - * method invocation and can be used to store accumulated values. - * - * Since: 0.2 - */ -void -ufo_filter_reduce_collect (UfoFilterReduce *filter, UfoBuffer *input[], UfoBuffer *output[], GError **error) -{ - g_return_if_fail (UFO_IS_FILTER_REDUCE (filter)); - UFO_FILTER_REDUCE_GET_CLASS (filter)->collect (filter, input, output, error); -} - -/** - * ufo_filter_reduce_reduce: - * @filter: A #UfoFilter. - * @output: An array of buffers for each output port - * @error: Location for #GError. - * - * This method calls the virtual reduce method and is called itself, when the - * input data stream has finished. The reduce method can be used to finalize - * work on the output buffers. - * - * Returns: TRUE if data is produced or FALSE if reduction has stopped - * - * Since: 0.2 - */ -gboolean -ufo_filter_reduce_reduce (UfoFilterReduce *filter, UfoBuffer *output[], GError **error) -{ - g_return_val_if_fail (UFO_IS_FILTER_REDUCE (filter), FALSE); - return UFO_FILTER_REDUCE_GET_CLASS (filter)->reduce (filter, output, error); -} - -static void -ufo_filter_reduce_initialize_real (UfoFilterReduce *filter, UfoBuffer *input[], guint **output_dims, gfloat *default_value, GError **error) -{ - g_debug ("%s->initialize not implemented", ufo_filter_get_plugin_name (UFO_FILTER (filter))); -} - -static void -ufo_filter_reduce_collect_real (UfoFilterReduce *filter, UfoBuffer *input[], UfoBuffer *output[], GError **error) -{ - g_set_error (error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_METHOD_NOT_IMPLEMENTED, - "Virtual method `collect' of %s is not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); -} - -static gboolean -ufo_filter_reduce_reduce_real (UfoFilterReduce *filter, UfoBuffer *output[], GError **error) -{ - g_set_error (error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_METHOD_NOT_IMPLEMENTED, - "Virtual method `reduce' of %s is not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); - - return FALSE; -} - -static void -ufo_filter_reduce_class_init (UfoFilterReduceClass *klass) -{ - klass->initialize = ufo_filter_reduce_initialize_real; - klass->collect = ufo_filter_reduce_collect_real; - klass->reduce = ufo_filter_reduce_reduce_real; -} - -static void -ufo_filter_reduce_init (UfoFilterReduce *self) -{ -} diff --git a/src/ufo-filter-reduce.h b/src/ufo-filter-reduce.h deleted file mode 100644 index 9d01b71..0000000 --- a/src/ufo-filter-reduce.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __UFO_FILTER_REDUCE_H -#define __UFO_FILTER_REDUCE_H - -#include <glib-object.h> - -#include "ufo-buffer.h" -#include "ufo-filter.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_REDUCE (ufo_filter_reduce_get_type()) -#define UFO_FILTER_REDUCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_REDUCE, UfoFilterReduce)) -#define UFO_IS_FILTER_REDUCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_REDUCE)) -#define UFO_FILTER_REDUCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_REDUCE, UfoFilterReduceClass)) -#define UFO_IS_FILTER_REDUCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_REDUCE)) -#define UFO_FILTER_REDUCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_REDUCE, UfoFilterReduceClass)) - -typedef struct _UfoFilterReduce UfoFilterReduce; -typedef struct _UfoFilterReduceClass UfoFilterReduceClass; -typedef struct _UfoFilterReducePrivate UfoFilterReducePrivate; - -/** - * UfoFilterReduce: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterReduce { - /*< private >*/ - UfoFilter parent; -}; - -/** - * UfoFilterReduceClass: - * @parent: the parent class - * @initialize: the @initialize function is called by an UfoBaseScheduler to set - * up a filter before actual execution happens. It receives the first input - * data to which the filter can get adjust. The reduce filter should return - * the default value that is used to fill the output buffer. - * @collect: the @collect function is called for each new input. The output - * buffer will be the same for all invocations and can be used to - * accumulate results. - * @reduce: the @reduce function is called after the data stream end. It is used - * to finish any remaining work on the output. - */ -struct _UfoFilterReduceClass { - UfoFilterClass parent; - - /* overridable */ - void (*initialize) (UfoFilterReduce *filter, - UfoBuffer *input[], - guint **output_dims, - gfloat *default_value, - GError **error); - void (*collect) (UfoFilterReduce *filter, - UfoBuffer *input[], - UfoBuffer *output[], - GError **error); - gboolean (*reduce) (UfoFilterReduce *filter, - UfoBuffer *output[], - GError **error); -}; - -void ufo_filter_reduce_initialize (UfoFilterReduce *filter, - UfoBuffer *input[], - guint **output_dims, - gfloat *default_value, - GError **error); -void ufo_filter_reduce_collect (UfoFilterReduce *filter, - UfoBuffer *input[], - UfoBuffer *output[], - GError **error); -gboolean ufo_filter_reduce_reduce (UfoFilterReduce *filter, - UfoBuffer *output[], - GError **error); -GType ufo_filter_reduce_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter-repeater.c b/src/ufo-filter-repeater.c deleted file mode 100644 index 8b57942..0000000 --- a/src/ufo-filter-repeater.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * SECTION:ufo-filter-repeater - * @Short_description: The repeater filter repeats its input on the output - * @Title: UfoFilterRepeater - * - * In case you want to subtract a constant image from a series of input images, - * you would need to repeat the constant image as often as you have other - * images. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-repeater.h" - -G_DEFINE_TYPE (UfoFilterRepeater, ufo_filter_repeater, UFO_TYPE_FILTER) - -#define UFO_FILTER_REPEATER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_REPEATER, UfoFilterRepeaterPrivate)) - -struct _UfoFilterRepeaterPrivate { - guint count; -}; - -enum { - PROP_0, - PROP_COUNT, - N_PROPERTIES -}; - -static GParamSpec *repeater_properties[N_PROPERTIES] = { NULL, }; - -static void -ufo_filter_repeater_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - UfoFilterRepeaterPrivate *priv = UFO_FILTER_REPEATER_GET_PRIVATE (object); - - switch (property_id) { - case PROP_COUNT: - priv->count = g_value_get_uint (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -ufo_filter_repeater_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - UfoFilterRepeaterPrivate *priv = UFO_FILTER_REPEATER_GET_PRIVATE (object); - - switch (property_id) { - case PROP_COUNT: - g_value_set_uint (value, priv->count); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -ufo_filter_repeater_class_init (UfoFilterRepeaterClass *klass) -{ - GObjectClass *oclass; - - oclass = G_OBJECT_CLASS (klass); - oclass->set_property = ufo_filter_repeater_set_property; - oclass->get_property = ufo_filter_repeater_get_property; - - repeater_properties[PROP_COUNT] = - g_param_spec_uint ("count", - "Number of repetitions", - "Number of repetitions", - 1, G_MAXUINT, 1, - G_PARAM_READWRITE); - - g_object_class_install_property (oclass, PROP_COUNT, repeater_properties[PROP_COUNT]); - g_type_class_add_private (klass, sizeof (UfoFilterRepeaterPrivate)); -} - -static void -ufo_filter_repeater_init (UfoFilterRepeater *self) -{ - UfoInputParameter input_param; - UfoOutputParameter output_params; - - self->priv = UFO_FILTER_REPEATER_GET_PRIVATE (self); - self->priv->count = 1; - - input_param.n_dims = 2; - input_param.n_expected_items = 1; - output_params.n_dims = 2; - - ufo_filter_register_inputs (UFO_FILTER (self), 1, &input_param); - ufo_filter_register_outputs (UFO_FILTER (self), 1, &output_params); - ufo_filter_set_plugin_name (UFO_FILTER (self), "repeater"); -} diff --git a/src/ufo-filter-repeater.h b/src/ufo-filter-repeater.h deleted file mode 100644 index 63ab1dd..0000000 --- a/src/ufo-filter-repeater.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __UFO_FILTER_REPEATER_H -#define __UFO_FILTER_REPEATER_H - -#include <glib-object.h> - -#include "ufo-filter.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_REPEATER (ufo_filter_repeater_get_type()) -#define UFO_FILTER_REPEATER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_REPEATER, UfoFilterRepeater)) -#define UFO_IS_FILTER_REPEATER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_REPEATER)) -#define UFO_FILTER_REPEATER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_REPEATER, UfoFilterRepeaterClass)) -#define UFO_IS_FILTER_REPEATER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_REPEATER)) -#define UFO_FILTER_REPEATER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_REPEATER, UfoFilterRepeaterClass)) - -typedef struct _UfoFilterRepeater UfoFilterRepeater; -typedef struct _UfoFilterRepeaterClass UfoFilterRepeaterClass; -typedef struct _UfoFilterRepeaterPrivate UfoFilterRepeaterPrivate; - -/** - * UfoFilterRepeater: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterRepeater { - /*< private >*/ - UfoFilter parent; - - UfoFilterRepeaterPrivate *priv; -}; - -/** - * UfoFilterRepeaterClass: - * @parent: the parent class - */ -struct _UfoFilterRepeaterClass { - UfoFilterClass parent; -}; - -GType ufo_filter_repeater_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter-sink-direct.c b/src/ufo-filter-sink-direct.c deleted file mode 100644 index d3cf239..0000000 --- a/src/ufo-filter-sink-direct.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * SECTION:ufo-filter-sink-direct - * @Short_description: A direct sink filter outputs data coming from a processing pipeline - * @Title: UfoFilterSinkDirect - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-sink-direct.h" - -G_DEFINE_TYPE (UfoFilterSinkDirect, ufo_filter_sink_direct, UFO_TYPE_FILTER_SINK) - -#define UFO_FILTER_SINK_DIRECT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_SINK_DIRECT, UfoFilterSinkDirectPrivate)) - -struct _UfoFilterSinkDirectPrivate { - GAsyncQueue *outgoing_queue; - GAsyncQueue *incoming_queue; -}; - -static void -ufo_filter_sink_direct_initialize (UfoFilterSink *filter, UfoBuffer *input[], GError **error) -{ - g_debug ("Virtual method `initialize' of %s not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); -} - -static void -ufo_filter_sink_direct_consume (UfoFilterSink *filter, UfoBuffer *input[], GError **error) -{ - UfoFilterSinkDirectPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER_SINK_DIRECT (filter)); - - priv = UFO_FILTER_SINK_DIRECT_GET_PRIVATE (filter); - g_async_queue_push (priv->outgoing_queue, input[0]); - g_async_queue_pop (priv->incoming_queue); -} - -/** - * ufo_filter_sink_direct_pop: - * @filter: A #UfoFilterSinkDirect object - * - * Get the buffer from this node. After processing the data, the buffer needs to - * be released with ufo_filter_sink_direct_release(). - * - * Returns: (transfer none): A #UfoBuffer to be processed directly. - */ -UfoBuffer * -ufo_filter_sink_direct_pop (UfoFilterSinkDirect *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER_SINK_DIRECT (filter), NULL); - return g_async_queue_pop (filter->priv->outgoing_queue); -} - -/** - * ufo_filter_sink_direct_release: - * @filter: A #UfoFilterSinkDirect object - * @buffer: A #UfoBuffer acquired with ufo_filter_sink_direct_pop(). - * - * Release a buffer acquired with ufo_filter_sink_direct_pop(). - * - * Note: If the buffer is not released, the processing pipeline will dead-lock. - */ -void -ufo_filter_sink_direct_release (UfoFilterSinkDirect *filter, UfoBuffer *buffer) -{ - g_return_if_fail (UFO_IS_FILTER_SINK_DIRECT (filter)); - g_async_queue_push (filter->priv->incoming_queue, buffer); -} - -static void -ufo_filter_sink_direct_finalize (GObject *object) -{ - UfoFilterSinkDirectPrivate *priv; - - priv = UFO_FILTER_SINK_DIRECT_GET_PRIVATE (object); - g_async_queue_unref (priv->outgoing_queue); - g_async_queue_unref (priv->incoming_queue); -} - -static void -ufo_filter_sink_direct_class_init (UfoFilterSinkDirectClass *klass) -{ - GObjectClass *oclass = G_OBJECT_CLASS (klass); - UfoFilterSinkClass *filter_class = UFO_FILTER_SINK_CLASS (klass); - - filter_class->initialize = ufo_filter_sink_direct_initialize; - filter_class->consume = ufo_filter_sink_direct_consume; - oclass->finalize = ufo_filter_sink_direct_finalize; - - g_type_class_add_private (klass, sizeof (UfoFilterSinkDirectPrivate)); -} - -static void -ufo_filter_sink_direct_init (UfoFilterSinkDirect *self) { - UfoFilterSinkDirectPrivate *priv; - UfoInputParameter input_params[] = {{2, UFO_FILTER_INFINITE_INPUT}}; - - self->priv = priv = UFO_FILTER_SINK_DIRECT_GET_PRIVATE (self); - priv->outgoing_queue = g_async_queue_new (); - priv->incoming_queue = g_async_queue_new (); - - ufo_filter_set_plugin_name (UFO_FILTER (self), "direct-sink"); - ufo_filter_register_inputs (UFO_FILTER (self), 1, input_params); -} diff --git a/src/ufo-filter-sink-direct.h b/src/ufo-filter-sink-direct.h deleted file mode 100644 index ff394ec..0000000 --- a/src/ufo-filter-sink-direct.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __UFO_FILTER_SINK_DIRECT_H -#define __UFO_FILTER_SINK_DIRECT_H - -#include <glib-object.h> - -#include "ufo-buffer.h" -#include "ufo-filter-sink.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_SINK_DIRECT (ufo_filter_sink_direct_get_type()) -#define UFO_FILTER_SINK_DIRECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_SINK_DIRECT, UfoFilterSinkDirect)) -#define UFO_IS_FILTER_SINK_DIRECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_SINK_DIRECT)) -#define UFO_FILTER_SINK_DIRECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_SINK_DIRECT, UfoFilterSinkDirectClass)) -#define UFO_IS_FILTER_SINK_DIRECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_SINK_DIRECT)) -#define UFO_FILTER_SINK_DIRECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_SINK_DIRECT, UfoFilterSinkDirectClass)) - -typedef struct _UfoFilterSinkDirect UfoFilterSinkDirect; -typedef struct _UfoFilterSinkDirectClass UfoFilterSinkDirectClass; -typedef struct _UfoFilterSinkDirectPrivate UfoFilterSinkDirectPrivate; - -/** - * UfoFilterSinkDirect: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterSinkDirect { - /*< private >*/ - UfoFilterSink parent; - - UfoFilterSinkDirectPrivate *priv; -}; - -/** - * UfoFilterSinkDirectClass: - * - * @parent: the parent class - */ -struct _UfoFilterSinkDirectClass { - UfoFilterSinkClass parent; -}; - -UfoBuffer * ufo_filter_sink_direct_pop (UfoFilterSinkDirect *filter); -void ufo_filter_sink_direct_release (UfoFilterSinkDirect *filter, - UfoBuffer *buffer); -GType ufo_filter_sink_direct_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter-sink.c b/src/ufo-filter-sink.c deleted file mode 100644 index cd44890..0000000 --- a/src/ufo-filter-sink.c +++ /dev/null @@ -1,85 +0,0 @@ -/** - * SECTION:ufo-filter-sink - * @Short_description: A sink filter consumes data only - * @Title: UfoFilterSink - * - * A sink does not produce an output from its inputs. This kind of filter is - * necessary to implement file writers or display nodes. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-sink.h" - -G_DEFINE_TYPE (UfoFilterSink, ufo_filter_sink, UFO_TYPE_FILTER) - -#define UFO_FILTER_SINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_SINK, UfoFilterSinkPrivate)) - -/** - * ufo_filter_sink_initialize: - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @error: Location for #GError. - * - * This function calls the implementation for the virtual initialize method. The - * filter can use the input buffers as a hint to setup its own internal - * structures. - * - * Since: 0.2 - */ -void -ufo_filter_sink_initialize (UfoFilterSink *filter, UfoBuffer *input[], GError **error) -{ - g_return_if_fail (UFO_IS_FILTER_SINK (filter)); - UFO_FILTER_SINK_GET_CLASS (filter)->initialize (filter, input, error); -} - -/** - * ufo_filter_sink_consume: - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @error: Location for #GError. - * - * Process input data from a buffer array. - * - * Since: 0.2 - */ -void -ufo_filter_sink_consume (UfoFilterSink *filter, UfoBuffer *input[], GError **error) -{ - g_return_if_fail (UFO_IS_FILTER_SINK (filter)); - UFO_FILTER_SINK_GET_CLASS (filter)->consume (filter, input, error); -} - -static void -ufo_filter_sink_initialize_real (UfoFilterSink *filter, UfoBuffer *input[], GError **error) -{ - g_return_if_fail (UFO_IS_FILTER_SINK (filter)); -} - -static void -ufo_filter_sink_consume_real (UfoFilterSink *filter, UfoBuffer *input[], GError **error) -{ - g_set_error (error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_METHOD_NOT_IMPLEMENTED, - "Virtual method `consume' of %s is not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); -} - -static void -ufo_filter_sink_class_init (UfoFilterSinkClass *klass) -{ - klass->initialize = ufo_filter_sink_initialize_real; - klass->consume = ufo_filter_sink_consume_real; -} - -static void -ufo_filter_sink_init (UfoFilterSink *self) -{ -} diff --git a/src/ufo-filter-sink.h b/src/ufo-filter-sink.h deleted file mode 100644 index b3f2bc5..0000000 --- a/src/ufo-filter-sink.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __UFO_FILTER_SINK_H -#define __UFO_FILTER_SINK_H - -#include <glib-object.h> - -#include "ufo-buffer.h" -#include "ufo-filter.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_SINK (ufo_filter_sink_get_type()) -#define UFO_FILTER_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_SINK, UfoFilterSink)) -#define UFO_IS_FILTER_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_SINK)) -#define UFO_FILTER_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_SINK, UfoFilterSinkClass)) -#define UFO_IS_FILTER_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_SINK)) -#define UFO_FILTER_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_SINK, UfoFilterSinkClass)) - -typedef struct _UfoFilterSink UfoFilterSink; -typedef struct _UfoFilterSinkClass UfoFilterSinkClass; -typedef struct _UfoFilterSinkPrivate UfoFilterSinkPrivate; - -/** - * UfoFilterSink: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterSink { - /*< private >*/ - UfoFilter parent; -}; - -/** - * UfoFilterSinkClass: - * @parent: the parent class - * @initialize: the @initialize function is called by an UfoBaseScheduler to set - * up a filter before actual execution happens. It receives the first input - * data to which the filter can get adjust. - * @consume: the @consume function implements what is going to happen with the - * input. - */ -struct _UfoFilterSinkClass { - UfoFilterClass parent; - - /* overridable methods */ - void (*initialize) (UfoFilterSink *filter, - UfoBuffer *input[], - GError **error); - void (*consume) (UfoFilterSink *filter, - UfoBuffer *input[], - GError **error); -}; - -void ufo_filter_sink_initialize (UfoFilterSink *filter, - UfoBuffer *input[], - GError **error); -void ufo_filter_sink_consume (UfoFilterSink *filter, - UfoBuffer *input[], - GError **error); -GType ufo_filter_sink_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter-source-direct.c b/src/ufo-filter-source-direct.c deleted file mode 100644 index 0b295e4..0000000 --- a/src/ufo-filter-source-direct.c +++ /dev/null @@ -1,127 +0,0 @@ -/** - * SECTION:ufo-filter-source-direct - * @Short_description: A source filter provides in-process data but does not consume any - * @Title: UfoFilterSourceDirect - * - * A direct source filter pushes in-process data into the processing pipeline to - * interface with modules that are not part of the pipeline. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-source-direct.h" - -G_DEFINE_TYPE (UfoFilterSourceDirect, ufo_filter_source_direct, UFO_TYPE_FILTER_SOURCE) - -#define UFO_FILTER_SOURCE_DIRECT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_SOURCE_DIRECT, UfoFilterSourceDirectPrivate)) - -static UfoBuffer *END_OF_STREAM = GINT_TO_POINTER (1); - -struct _UfoFilterSourceDirectPrivate { - GAsyncQueue *incoming_queue; - GAsyncQueue *outgoing_queue; -}; - -static void -ufo_filter_source_direct_initialize (UfoFilterSource *filter, guint **output_dim_sizes, GError **error) -{ - g_debug ("Virtual method `initialize' of %s not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); -} - -static gboolean -ufo_filter_source_direct_generate (UfoFilterSource *filter, UfoBuffer *output[], GError **error) -{ - UfoFilterSourceDirectPrivate *priv; - UfoBuffer *buffer; - - g_return_val_if_fail (UFO_IS_FILTER_SOURCE_DIRECT (filter), FALSE); - - priv = UFO_FILTER_SOURCE_DIRECT_GET_PRIVATE (filter); - - g_async_queue_push (priv->outgoing_queue, output[0]); - buffer = g_async_queue_pop (priv->incoming_queue); - - return buffer == END_OF_STREAM; -} - -/** - * ufo_filter_source_direct_push: - * @filter: A #UfoFilterSourceDirect object - * @buffer: A #UfoBuffer to be pushed into this node - * - * Pushes a #UfoBuffer into this node to be processed by subsequent, connected - * filters. To stop iterating, call ufo_filter_source_direct_stop(). - */ -void -ufo_filter_source_direct_push (UfoFilterSourceDirect *filter, - UfoBuffer *buffer) -{ - UfoFilterSourceDirectPrivate *priv; - UfoBuffer *output; - - g_return_if_fail (UFO_IS_FILTER_SOURCE_DIRECT (filter)); - - priv = UFO_FILTER_SOURCE_DIRECT_GET_PRIVATE (filter); - output = g_async_queue_pop (priv->outgoing_queue); - ufo_buffer_copy (buffer, output); - g_async_queue_push (priv->incoming_queue, output); -} - -/** - * ufo_filter_source_direct_stop: - * @filter: A #UfoFilterSourceDirect object - * - * Stop execution. This node cannot accept anymore and subsequent nodes will be - * notified, that data generation has stopped. - */ -void -ufo_filter_source_direct_stop (UfoFilterSourceDirect *filter) -{ - g_return_if_fail (UFO_IS_FILTER_SOURCE_DIRECT (filter)); - g_async_queue_push (filter->priv->incoming_queue, END_OF_STREAM); -} - -static void -ufo_filter_source_direct_finalize (GObject *object) -{ - UfoFilterSourceDirectPrivate *priv; - - priv = UFO_FILTER_SOURCE_DIRECT_GET_PRIVATE (object); - g_async_queue_unref (priv->outgoing_queue); - g_async_queue_unref (priv->incoming_queue); -} - -static void -ufo_filter_source_direct_class_init (UfoFilterSourceDirectClass *klass) -{ - GObjectClass *oclass = G_OBJECT_CLASS (klass); - UfoFilterSourceClass *source_class = UFO_FILTER_SOURCE_CLASS (klass); - - source_class->initialize = ufo_filter_source_direct_initialize; - source_class->generate = ufo_filter_source_direct_generate; - oclass->finalize = ufo_filter_source_direct_finalize; - - g_type_class_add_private (klass, sizeof (UfoFilterSourceDirectPrivate)); -} - -static void -ufo_filter_source_direct_init (UfoFilterSourceDirect *self) -{ - UfoFilterSourceDirectPrivate *priv; - UfoOutputParameter output_params[] = {{2}}; - - self->priv = priv = UFO_FILTER_SOURCE_DIRECT_GET_PRIVATE (self); - priv->incoming_queue = g_async_queue_new (); - priv->outgoing_queue = g_async_queue_new (); - - ufo_filter_set_plugin_name (UFO_FILTER (self), "direct-source"); - ufo_filter_register_outputs (UFO_FILTER (self), 1, output_params); -} diff --git a/src/ufo-filter-source-direct.h b/src/ufo-filter-source-direct.h deleted file mode 100644 index 7a0ba37..0000000 --- a/src/ufo-filter-source-direct.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __UFO_FILTER_SOURCE_DIRECT_H -#define __UFO_FILTER_SOURCE_DIRECT_H - -#include <glib-object.h> - -#include "ufo-buffer.h" -#include "ufo-filter-source.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_SOURCE_DIRECT (ufo_filter_source_direct_get_type()) -#define UFO_FILTER_SOURCE_DIRECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_SOURCE_DIRECT, UfoFilterSourceDirect)) -#define UFO_IS_FILTER_SOURCE_DIRECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_SOURCE_DIRECT)) -#define UFO_FILTER_SOURCE_DIRECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_SOURCE_DIRECT, UfoFilterSourceDirectClass)) -#define UFO_IS_FILTER_SOURCE_DIRECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_SOURCE_DIRECT)) -#define UFO_FILTER_SOURCE_DIRECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_SOURCE_DIRECT, UfoFilterSourceDirectClass)) - -typedef struct _UfoFilterSourceDirect UfoFilterSourceDirect; -typedef struct _UfoFilterSourceDirectClass UfoFilterSourceDirectClass; -typedef struct _UfoFilterSourceDirectPrivate UfoFilterSourceDirectPrivate; - -/** - * UfoFilterSourceDirect: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterSourceDirect { - /*< private >*/ - UfoFilterSource parent; - - UfoFilterSourceDirectPrivate *priv; -}; - -/** - * UfoFilterSourceDirectClass: - * - * @parent: the parent class - */ -struct _UfoFilterSourceDirectClass { - UfoFilterSourceClass parent; -}; - -void ufo_filter_source_direct_push (UfoFilterSourceDirect *filter, - UfoBuffer *buffer); -void ufo_filter_source_direct_stop (UfoFilterSourceDirect *filter); -GType ufo_filter_source_direct_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter-source.c b/src/ufo-filter-source.c deleted file mode 100644 index 29ce454..0000000 --- a/src/ufo-filter-source.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - * SECTION:ufo-filter-source - * @Short_description: A source filter provides data but does not consume any - * @Title: UfoFilterSource - * - * A source filter produces data but does not accept any inputs. This can be - * used to implement file readers or acquisition devices. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-source.h" - -G_DEFINE_TYPE (UfoFilterSource, ufo_filter_source, UFO_TYPE_FILTER) - -#define UFO_FILTER_SOURCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_SOURCE, UfoFilterSourcePrivate)) - -/** - * ufo_filter_source_initialize: - * @filter: A #UfoFilter. - * @output_dim_sizes: The size of each dimension for each output - * @error: Location for #GError. - * - * This function calls the implementation for the virtual initialize method. It - * needs to return size of each output dimension in each port as specified with - * ufo_filter_register_outputs(): - * <programlisting> - * // register a 1-dimensional and a 2-dimensional output in object::init - * ufo_filter_register_outputs (self, 1, 2, NULL); - * - * // specify sizes in object::initialize - * output_dim_sizes[0][0] = 1024; - * - * output_dim_sizes[1][0] = 640; - * output_dim_sizes[1][1] = 480; - * </programlisting> - * - * Since: 0.2 - */ -void -ufo_filter_source_initialize (UfoFilterSource *filter, guint **output_dim_sizes, GError **error) -{ - g_return_if_fail (UFO_IS_FILTER_SOURCE (filter)); - UFO_FILTER_SOURCE_GET_CLASS (filter)->initialize (filter, output_dim_sizes, error); -} - -/** - * ufo_filter_source_generate: - * @filter: A #UfoFilter. - * @output: An array of buffers for each output port - * @error: Location for #GError. - * - * This function calls the implementation for the virtual generate method. It - * should produce one set of outputs for each time it is called. If no more data - * is produced it must return %FALSE. - * - * Returns: %TRUE if data is produced, otherwise %FALSE. - * Since: 0.2 - */ -gboolean -ufo_filter_source_generate (UfoFilterSource *filter, UfoBuffer *output[], GError **error) -{ - g_return_val_if_fail (UFO_IS_FILTER_SOURCE (filter), FALSE); - return UFO_FILTER_SOURCE_GET_CLASS (filter)->generate (filter, output, error); -} - -static void -ufo_filter_source_initialize_real (UfoFilterSource *filter, guint **output_dim_sizes, GError **error) -{ - g_debug ("Virtual method `initialize' of %s not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); -} - -static gboolean -ufo_filter_source_generate_real (UfoFilterSource *filter, UfoBuffer *output[], GError **error) -{ - g_set_error (error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_METHOD_NOT_IMPLEMENTED, - "Virtual method `generate' of %s is not implemented", - ufo_filter_get_plugin_name (UFO_FILTER (filter))); - - return FALSE; -} - -static void -ufo_filter_source_class_init (UfoFilterSourceClass *klass) -{ - klass->initialize = ufo_filter_source_initialize_real; - klass->generate = ufo_filter_source_generate_real; -} - -static void -ufo_filter_source_init (UfoFilterSource *self) -{ -} diff --git a/src/ufo-filter-source.h b/src/ufo-filter-source.h deleted file mode 100644 index 1d6f15d..0000000 --- a/src/ufo-filter-source.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __UFO_FILTER_SOURCE_H -#define __UFO_FILTER_SOURCE_H - -#include <glib-object.h> - -#include "ufo-buffer.h" -#include "ufo-filter.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_SOURCE (ufo_filter_source_get_type()) -#define UFO_FILTER_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_SOURCE, UfoFilterSource)) -#define UFO_IS_FILTER_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_SOURCE)) -#define UFO_FILTER_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_SOURCE, UfoFilterSourceClass)) -#define UFO_IS_FILTER_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_SOURCE)) -#define UFO_FILTER_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_SOURCE, UfoFilterSourceClass)) - -typedef struct _UfoFilterSource UfoFilterSource; -typedef struct _UfoFilterSourceClass UfoFilterSourceClass; -typedef struct _UfoFilterSourcePrivate UfoFilterSourcePrivate; - -/** - * UfoFilterSource: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterSource { - /*< private >*/ - UfoFilter parent; -}; - -/** - * UfoFilterSourceClass: - * @parent: the parent class - * @initialize: the @initialize function is called by an UfoBaseScheduler to set - * up a filter before actual execution happens. - * @generate: the @generate function produces data for subsequent filters. It - * returns TRUE if is produced. - */ -struct _UfoFilterSourceClass { - UfoFilterClass parent; - - /* overridable */ - void (*initialize) (UfoFilterSource *filter, - guint **output_dim_sizes, - GError **error); - gboolean (*generate) (UfoFilterSource *filter, - UfoBuffer *output[], - GError **error); -}; - -void ufo_filter_source_initialize (UfoFilterSource *filter, - guint **output_dim_sizes, - GError **error); -gboolean ufo_filter_source_generate (UfoFilterSource *filter, - UfoBuffer *output[], - GError **error); -GType ufo_filter_source_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter-splitter.c b/src/ufo-filter-splitter.c deleted file mode 100644 index f4524a4..0000000 --- a/src/ufo-filter-splitter.c +++ /dev/null @@ -1,155 +0,0 @@ -/** - * SECTION:ufo-filter-splitter - * @Short_description: Splitter filters control diverging data flows - * @Title: UfoFilterSplitter - * - * The splitter filter is used to split the incoming data stream into - * consecutive, linear sub-streams. For example, this allows you to to route - * the first ten items to the first node, the next to items to the second and - * the remaining to the last node. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-filter-splitter.h" - -G_DEFINE_TYPE (UfoFilterSplitter, ufo_filter_splitter, UFO_TYPE_FILTER) - -#define UFO_FILTER_SPLITTER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_SPLITTER, UfoFilterSplitterPrivate)) - -struct _UfoFilterSplitterPrivate { - guint n_splits; - guint *splits; - GValueArray *counts; -}; - -enum { - PROP_0, - PROP_COUNTS, - N_PROPERTIES -}; - -static GParamSpec *splitter_properties[N_PROPERTIES] = { NULL, }; - -static void -ufo_filter_splitter_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - UfoFilterSplitterPrivate *priv = UFO_FILTER_SPLITTER_GET_PRIVATE (object); - - switch (property_id) { - case PROP_COUNTS: - { - GValueArray *array; - - if (priv->counts != NULL) - g_value_array_free (priv->counts); - - array = g_value_get_boxed (value); - - if (array != NULL) { - priv->counts = g_value_array_copy (array); - priv->n_splits = priv->counts->n_values; - } - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -ufo_filter_splitter_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - UfoFilterSplitterPrivate *priv = UFO_FILTER_SPLITTER_GET_PRIVATE (object); - - switch (property_id) { - case PROP_COUNTS: - g_value_set_boxed (value, priv->counts); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -ufo_filter_splitter_constructed (GObject *object) -{ - UfoInputParameter input_param; - UfoOutputParameter *output_params; - UfoFilterSplitter *splitter; - UfoFilterSplitterPrivate *priv; - guint n_outputs; - - splitter = UFO_FILTER_SPLITTER (object); - priv = splitter->priv; - - input_param.n_dims = 2; - input_param.n_expected_items = UFO_FILTER_INFINITE_INPUT; - ufo_filter_register_inputs (UFO_FILTER (splitter), 1, &input_param); - - n_outputs = priv->n_splits + 1; - output_params = g_new0 (UfoOutputParameter, n_outputs); - - for (guint i = 0; i < n_outputs; i++) - output_params[i].n_dims = 2; - - ufo_filter_register_outputs (UFO_FILTER (splitter), n_outputs, output_params); - g_free (output_params); - - if (G_OBJECT_CLASS (ufo_filter_splitter_parent_class)->constructed != NULL) - G_OBJECT_CLASS (ufo_filter_splitter_parent_class)->constructed (object); -} - -static void -ufo_filter_splitter_class_init (UfoFilterSplitterClass *klass) -{ - GObjectClass *oclass; - - oclass = G_OBJECT_CLASS (klass); - oclass->set_property = ufo_filter_splitter_set_property; - oclass->get_property = ufo_filter_splitter_get_property; - oclass->constructed = ufo_filter_splitter_constructed; - - splitter_properties[PROP_COUNTS] = - g_param_spec_value_array ("counts", - "Array of counts for splitting the stream", - "Array of counts for splitting the stream", - g_param_spec_int ("count", - "Number of items to push", - "Number of items to push", - -G_MAXINT, G_MAXINT, -1, - G_PARAM_READWRITE), - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (oclass, PROP_COUNTS, splitter_properties[PROP_COUNTS]); - - g_type_class_add_private (klass, sizeof (UfoFilterSplitterPrivate)); -} - -static void -ufo_filter_splitter_init (UfoFilterSplitter *self) -{ - self->priv = UFO_FILTER_SPLITTER_GET_PRIVATE (self); - - self->priv->n_splits = 0; - self->priv->counts = NULL; - - ufo_filter_set_plugin_name (UFO_FILTER (self), "splitter"); -} diff --git a/src/ufo-filter-splitter.h b/src/ufo-filter-splitter.h deleted file mode 100644 index 2764a1f..0000000 --- a/src/ufo-filter-splitter.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __UFO_FILTER_SPLITTER_H -#define __UFO_FILTER_SPLITTER_H - -#include <glib-object.h> - -#include "ufo-filter.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER_SPLITTER (ufo_filter_splitter_get_type()) -#define UFO_FILTER_SPLITTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER_SPLITTER, UfoFilterSplitter)) -#define UFO_IS_FILTER_SPLITTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER_SPLITTER)) -#define UFO_FILTER_SPLITTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER_SPLITTER, UfoFilterSplitterClass)) -#define UFO_IS_FILTER_SPLITTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER_SPLITTER)) -#define UFO_FILTER_SPLITTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER_SPLITTER, UfoFilterSplitterClass)) - -typedef struct _UfoFilterSplitter UfoFilterSplitter; -typedef struct _UfoFilterSplitterClass UfoFilterSplitterClass; -typedef struct _UfoFilterSplitterPrivate UfoFilterSplitterPrivate; - -/** - * UfoFilterSplitter: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilterSplitter { - /*< private >*/ - UfoFilter parent; - - UfoFilterSplitterPrivate *priv; -}; - -/** - * UfoFilterSplitterClass: - * @parent: the parent class - */ -struct _UfoFilterSplitterClass { - UfoFilterClass parent; -}; - -GType ufo_filter_splitter_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-filter.c b/src/ufo-filter.c deleted file mode 100644 index d27bf25..0000000 --- a/src/ufo-filter.c +++ /dev/null @@ -1,640 +0,0 @@ -/** - * SECTION:ufo-filter - * @Short_description: Single unit of computation - * @Title: UfoFilter - * - * The base class for processing nodes. - */ - -#include <glib.h> -#include <gmodule.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif -#include <string.h> - -#include "config.h" -#include "ufo-filter.h" -#include "ufo-filter-source.h" -#include "ufo-filter-sink.h" - -G_DEFINE_TYPE(UfoFilter, ufo_filter, G_TYPE_OBJECT) - -#define UFO_FILTER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER, UfoFilterPrivate)) - -struct _UfoFilterPrivate { - gchar *plugin_name; - gchar *unique_name; - - guint n_inputs; - guint n_outputs; - - UfoResourceManager *manager; - UfoProfiler *profiler; - UfoInputParameter *input_parameters; - UfoOutputParameter *output_parameters; - UfoChannel **input_channels; - UfoChannel **output_channels; - - cl_command_queue command_queue; - gboolean finished; -}; - -/** - * UfoFilterError: - * @UFO_FILTER_ERROR_INSUFFICIENTINPUTS: Filter does not provide enough inputs. - * @UFO_FILTER_ERROR_INSUFFICIENTOUTPUTS: Filter does not provide enough - * outputs. - * @UFO_FILTER_ERROR_NUMDIMSMISMATCH: Mismatch between number of dimensions of - * given input and output. - * @UFO_FILTER_ERROR_NOSUCHINPUT: Filter does not provide an input with that - * name. - * @UFO_FILTER_ERROR_NOSUCHOUTPUT: Filter does not provide an output with that - * name. - * @UFO_FILTER_ERROR_INITIALIZATION: Filter could not be initialized. - * @UFO_FILTER_ERROR_METHOD_NOT_IMPLEMENTED: A method, further specified in the - * message, is not implemented. - * - * Possible errors that ufo_filter_connect_to() and ufo_filter_connect_by_name() - * can return. - */ -GQuark -ufo_filter_error_quark(void) -{ - return g_quark_from_static_string ("ufo-filter-error-quark"); -} - -/** - * ufo_filter_initialize: - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @output_dim_sizes: The size of each dimension for each output - * @error: Location for #GError. - * - * This function calls the implementation for the virtual initialize method. The - * filter can use the input buffers as a hint to setup its own internal - * structures. Moreover, it needs to return size of each output dimension in - * each port as specified with ufo_filter_register_outputs(): - * <programlisting> - * // register a 1-dimensional and a 2-dimensional output in object::init - * ufo_filter_register_outputs (self, 1, 2, NULL); - * - * // specify sizes in object::initialize - * output_dim_sizes[0][0] = 1024; - * - * output_dim_sizes[1][0] = 640; - * output_dim_sizes[1][1] = 480; - * </programlisting> - * - * Since: 0.2 - */ -void -ufo_filter_initialize (UfoFilter *filter, UfoBuffer *input[], guint **output_dim_sizes, GError **error) -{ - g_return_if_fail (UFO_IS_FILTER (filter)); - UFO_FILTER_GET_CLASS (filter)->initialize (filter, input, output_dim_sizes, error); -} - -/** - * ufo_filter_set_resource_manager: - * @filter: A #UfoFilter. - * @manager: A #UfoResourceManager - * - * Set the resource manager that this filter uses for requesting resources. - * - * Since: 0.2 - */ -void ufo_filter_set_resource_manager (UfoFilter *filter, - UfoResourceManager *manager) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter) && UFO_IS_RESOURCE_MANAGER (manager)); - priv = filter->priv; - priv->manager = manager; -} - -/** - * ufo_filter_get_resource_manager: - * @filter: A #UfoFilter. - * - * Get the resource manager that this filter uses for requesting resources. - * - * Returns: (transfer full): A #UfoResourceManager - * Since: 0.2 - */ -UfoResourceManager *ufo_filter_get_resource_manager (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->manager; -} - -/** - * ufo_filter_set_profiler: - * @filter: A #UfoFilter. - * @profiler: A #UfoProfiler - * - * Set this filter's profiler. - * - * Since: 0.2 - */ -void ufo_filter_set_profiler (UfoFilter *filter, - UfoProfiler *profiler) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter) && UFO_IS_PROFILER (profiler)); - priv = filter->priv; - - if (priv->profiler != NULL) - g_object_unref (priv->profiler); - - g_object_ref (profiler); - priv->profiler = profiler; -} - -/** - * ufo_filter_get_profiler: - * @filter: A #UfoFilter. - * - * Get this filter's profiler. - * - * Returns: (transfer full): A #UfoProfiler - * Since: 0.2 - */ -UfoProfiler *ufo_filter_get_profiler (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->profiler; -} - -/** - * ufo_filter_process_cpu: - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @output: An array of buffers for each output port - * @error: Location for #GError. - * - * Process input data from a buffer array on the CPU and put the results into - * buffers in the #output array. - * - * Since: 0.2 - */ -void -ufo_filter_process_cpu (UfoFilter *filter, UfoBuffer *input[], UfoBuffer *output[], GError **error) -{ - g_return_if_fail (UFO_IS_FILTER (filter)); - UFO_FILTER_GET_CLASS (filter)->process_cpu (filter, input, output, error); -} - -/** - * ufo_filter_process_gpu: (skip) - * @filter: A #UfoFilter. - * @input: An array of buffers for each input port - * @output: An array of buffers for each output port - * @error: Location for an error. - * - * Process input data from a buffer array on the GPU and put the results into - * buffers in the #output array. For each enqueue command, a %cl_event object - * should be created and put into a #UfoEventList that is returned at the end: - * <programlisting> - * UfoEventList *event_list = ufo_event_list_new (2); - * cl_event *events = ufo_event_list_get_event_array (event_list); - * - * clEnqueueNDRangeKernel(..., 0, NULL, &events[0]); - * - * return event_list; - * </programlisting> - * - * Since: 0.2 - */ -void -ufo_filter_process_gpu (UfoFilter *filter, UfoBuffer *input[], UfoBuffer *output[], GError **error) -{ - g_return_if_fail (UFO_IS_FILTER (filter)); - UFO_FILTER_GET_CLASS (filter)->process_gpu (filter, input, output, error); -} - -/** - * ufo_filter_set_plugin_name: - * @filter: A #UfoFilter. - * @plugin_name: The name of this filter. - * - * Set the name of filter. - */ -void -ufo_filter_set_plugin_name (UfoFilter *filter, const gchar *plugin_name) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter)); - - priv = filter->priv; - priv->plugin_name = g_strdup (plugin_name); - priv->unique_name = g_strdup_printf ("%s-%p", - plugin_name, - (gpointer) filter); -} - -/** - * ufo_filter_register_inputs: (skip) - * @filter: A #UfoFilter. - * @n_inputs: Number of inputs - * @input_parameters: An array of #UfoInputParameter structures - * - * Specifies the number of dimensions and expected number of data elements for - * each input. - * - * Since: 0.2 - */ -void -ufo_filter_register_inputs (UfoFilter *filter, guint n_inputs, UfoInputParameter *parameters) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter)); - g_return_if_fail (parameters != NULL); - - priv = UFO_FILTER_GET_PRIVATE (filter); - - if (UFO_IS_FILTER_SOURCE (filter)) { - g_warning ("%s is a source filter and cannot receive any inputs", - priv->plugin_name); - return; - } - - priv->n_inputs = n_inputs; - priv->input_channels = g_new0 (UfoChannel *, n_inputs); - priv->input_parameters = g_new0 (UfoInputParameter, n_inputs); - g_memmove (priv->input_parameters, parameters, n_inputs * sizeof(UfoInputParameter)); -} - -/** - * ufo_filter_register_outputs: (skip) - * @filter: A #UfoFilter. - * @n_outputs: Number of outputs - * @output_parameters: An array of #UfoOutputParameter structures - * - * Specifies the number of dimensions for each output. - * - * Since: 0.2 - */ -void -ufo_filter_register_outputs (UfoFilter *filter, guint n_outputs, UfoOutputParameter *parameters) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter)); - g_return_if_fail (parameters != NULL); - - priv = UFO_FILTER_GET_PRIVATE (filter); - - if (UFO_IS_FILTER_SINK (filter)) { - g_warning ("%s is a sink filter and cannnot output any data", - priv->plugin_name); - return; - } - - priv->n_outputs = n_outputs; - priv->output_channels = g_new0 (UfoChannel *, n_outputs); - priv->output_parameters = g_new0 (UfoOutputParameter, n_outputs); - g_memmove (priv->output_parameters, parameters, n_outputs * sizeof(UfoOutputParameter)); -} - -/** - * ufo_filter_get_input_parameters: (skip) - * @filter: A #UfoFilter. - * - * Get input parameters. - * - * Return: An array of #UfoInputParameter structures. This array must not be - * freed. - */ -UfoInputParameter * -ufo_filter_get_input_parameters (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->input_parameters; -} - -/** - * ufo_filter_get_output_parameters: (skip) - * @filter: A #UfoFilter. - * - * Get ouput parameters. - * - * Return: An array of #UfoOuputParameter structures. This array must not be - * freed. - */ -UfoOutputParameter * -ufo_filter_get_output_parameters (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->output_parameters; -} - -/** - * ufo_filter_get_num_inputs: - * @filter: A #UfoFilter. - * - * Return the number of input ports. - * - * Returns: Number of input ports. - * Since: 0.2 - */ -guint -ufo_filter_get_num_inputs (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), 0); - return filter->priv->n_inputs; -} - -/** - * ufo_filter_get_num_outputs: - * @filter: A #UfoFilter. - * - * Return the number of output ports. - * - * Returns: Number of output ports. - * Since: 0.2 - */ -guint -ufo_filter_get_num_outputs (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), 0); - return filter->priv->n_outputs; -} - -/** - * ufo_filter_get_plugin_name: - * @filter: A #UfoFilter. - * - * Get canonical name of @filter. - * - * Returns: (transfer none): %NULL-terminated string owned by the filter. - */ -const gchar * -ufo_filter_get_plugin_name (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->plugin_name; -} - -/** - * ufo_filter_get_unique_name: - * @filter: A #UfoFilter - * - * Get unique filter name consisting of the plugin name as returned by - * ufo_filter_get_plugin_name(), a dash `-' and the address of the filter - * object. This can be useful to differentiate between several instances of the - * same filter. - * - * Returns: (transfer none): %NULL-terminated string owned by the filter. - */ -const gchar* -ufo_filter_get_unique_name (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->unique_name; -} - -/** - * ufo_filter_set_output_channel: - * @filter: A #UfoFilter. - * @port: Output port number - * @channel: A #UfoChannel. - * - * Set a filter's output channel for a certain output port. - * - * Since: 0.2 - */ -void -ufo_filter_set_output_channel (UfoFilter *filter, guint port, UfoChannel *channel) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter) && UFO_IS_CHANNEL (channel)); - g_return_if_fail (port < filter->priv->n_outputs); - - priv = filter->priv; - - if (priv->output_channels[port] != NULL) - g_object_unref (priv->output_channels[port]); - - g_object_ref (channel); - priv->output_channels[port] = channel; -} - -/** - * ufo_filter_get_output_channel: - * @filter: A #UfoFilter. - * @port: Output port number - * - * Return a filter's output channel for a certain output port. - * - * Returns: (transfer none) (allow-none): The associated output channel. - * Since: 0.2 - */ -UfoChannel * -ufo_filter_get_output_channel (UfoFilter *filter, guint port) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - g_return_val_if_fail (port < filter->priv->n_outputs, NULL); - return filter->priv->output_channels[port]; -} - -/** - * ufo_filter_set_input_channel: - * @filter: A #UfoFilter. - * @port: input port number - * @channel: A #UfoChannel. - * - * Set a filter's input channel for a certain input port. - * - * Since: 0.2 - */ -void -ufo_filter_set_input_channel (UfoFilter *filter, guint port, UfoChannel *channel) -{ - UfoFilterPrivate *priv; - - g_return_if_fail (UFO_IS_FILTER (filter) && UFO_IS_CHANNEL (channel)); - g_return_if_fail (port < filter->priv->n_inputs); - - priv = filter->priv; - - if (priv->input_channels[port] != NULL) - g_object_unref (priv->input_channels[port]); - - g_object_ref (channel); - filter->priv->input_channels[port] = channel; -} - -/** - * ufo_filter_get_input_channel: - * @filter: A #UfoFilter. - * @port: input port number - * - * Return a filter's input channel for a certain input port. - * - * Returns: (transfer none) (allow-none): The associated input channel. - * Since: 0.2 - */ -UfoChannel * -ufo_filter_get_input_channel (UfoFilter *filter, guint port) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - - if (port >= filter->priv->n_inputs) { - g_warning ("Requested port %i of `%s' but has only %i inputs\n", - port, ufo_filter_get_plugin_name (filter), - filter->priv->n_inputs); - return NULL; - } - - return filter->priv->input_channels[port]; -} - -/** - * ufo_filter_set_command_queue: - * @filter: A #UfoFilter. - * @cmd_queue: A %cl_command_queue to be used for computation and data transfer - * - * Set the associated command queue. - * Since: 0.2 - */ -void -ufo_filter_set_command_queue (UfoFilter *filter, - gpointer cmd_queue) -{ - g_return_if_fail (UFO_IS_FILTER (filter)); - filter->priv->command_queue = cmd_queue; -} - -/** - * ufo_filter_get_command_queue: - * @filter: A #UfoFilter. - * - * Get the associated command queue. - * - * Returns: (transfer none): A %cl_command_queue or %NULL - * Since: 0.2 - */ -gpointer -ufo_filter_get_command_queue (UfoFilter *filter) -{ - g_return_val_if_fail (UFO_IS_FILTER (filter), NULL); - return filter->priv->command_queue; -} - -/** - * ufo_filter_wait_until: (skip) - * @filter: A #UfoFilter - * @pspec: The specification of the property - * @condition: A condition function to wait until it is satisfied - * @user_data: User data passed to the condition func - * - * Wait until a property specified by @pspec fulfills @condition. - */ -void -ufo_filter_wait_until (UfoFilter *filter, GParamSpec *pspec, UfoFilterConditionFunc condition, gpointer user_data) -{ - GValue val = {0,}; - g_value_init (&val, pspec->value_type); - - while (1) { - g_object_get_property (G_OBJECT (filter), pspec->name, &val); - - if (condition (&val, user_data)) - break; - - g_usleep (10000); - } - - g_value_unset (&val); -} - -static void -ufo_filter_initialize_real (UfoFilter *filter, UfoBuffer *input[], guint **output_dim_sizes, GError **error) -{ - g_debug ("Virtual method `initialize' of %s not implemented\n", - filter->priv->plugin_name); -} - -static void -ufo_filter_dispose (GObject *object) -{ - UfoFilterPrivate *priv; - - priv = UFO_FILTER_GET_PRIVATE (object); - - if (priv->profiler != NULL) { - g_object_unref (priv->profiler); - priv->profiler = NULL; - } - - for (guint port = 0; port < priv->n_inputs; port++) { - if (priv->input_channels[port] != NULL) - g_object_unref (priv->input_channels[port]); - } - - for (guint port = 0; port < priv->n_outputs; port++) { - if (priv->output_channels[port] != NULL) - g_object_unref (priv->output_channels[port]); - } - - G_OBJECT_CLASS (ufo_filter_parent_class)->dispose(object); - g_message ("UfoFilter (%p): disposed", (gpointer) object); -} - -static void -ufo_filter_finalize (GObject *object) -{ - UfoFilterPrivate *priv = UFO_FILTER_GET_PRIVATE (object); - - g_free (priv->input_parameters); - g_free (priv->output_parameters); - g_free (priv->input_channels); - g_free (priv->output_channels); - g_free (priv->plugin_name); - g_free (priv->unique_name); - - G_OBJECT_CLASS (ufo_filter_parent_class)->finalize (object); - g_message ("UfoFilter (%p): finalized", (gpointer) object); -} - -static void -ufo_filter_class_init (UfoFilterClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = ufo_filter_finalize; - gobject_class->dispose = ufo_filter_dispose; - - klass->initialize = ufo_filter_initialize_real; - klass->process_cpu = NULL; - klass->process_gpu = NULL; - - g_type_class_add_private (klass, sizeof (UfoFilterPrivate)); -} - -static void -ufo_filter_init (UfoFilter *self) -{ - UfoFilterPrivate *priv; - self->priv = priv = UFO_FILTER_GET_PRIVATE (self); - priv->finished = FALSE; - priv->n_inputs = 0; - priv->n_outputs = 0; - priv->input_parameters = NULL; - priv->output_parameters = NULL; - priv->input_channels = NULL; - priv->output_channels = NULL; - priv->profiler = NULL; - priv->command_queue = NULL; - priv->plugin_name = NULL; - priv->unique_name = NULL; -} - diff --git a/src/ufo-filter.h b/src/ufo-filter.h deleted file mode 100644 index b9da081..0000000 --- a/src/ufo-filter.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef __UFO_FILTER_H -#define __UFO_FILTER_H - -#include <glib-object.h> - -#include "ufo-profiler.h" -#include "ufo-resource-manager.h" -#include "ufo-buffer.h" -#include "ufo-channel.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_FILTER (ufo_filter_get_type()) -#define UFO_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FILTER, UfoFilter)) -#define UFO_IS_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FILTER)) -#define UFO_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FILTER, UfoFilterClass)) -#define UFO_IS_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FILTER)) -#define UFO_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FILTER, UfoFilterClass)) - -/** - * UFO_FILTER_INFINITE_INPUT: - * - * Use this to specify that you accept an infinite data stream on an input for - * #UfoInputParameter and ufo_filter_register_inputs(). - */ -#define UFO_FILTER_INFINITE_INPUT -1 - -#define UFO_FILTER_ERROR ufo_filter_error_quark() -GQuark ufo_filter_error_quark(void); - -typedef enum { - UFO_FILTER_ERROR_INSUFFICIENTINPUTS, - UFO_FILTER_ERROR_INSUFFICIENTOUTPUTS, - UFO_FILTER_ERROR_NUMDIMSMISMATCH, - UFO_FILTER_ERROR_NOSUCHINPUT, - UFO_FILTER_ERROR_NOSUCHOUTPUT, - UFO_FILTER_ERROR_INITIALIZATION, - UFO_FILTER_ERROR_METHOD_NOT_IMPLEMENTED -} UfoFilterError; - -typedef struct _UfoFilter UfoFilter; -typedef struct _UfoFilterClass UfoFilterClass; -typedef struct _UfoFilterPrivate UfoFilterPrivate; -typedef struct _UfoInputParameter UfoInputParameter; -typedef struct _UfoOutputParameter UfoOutputParameter; - -/** - * UfoFilterConditionFunc: - * @value: Property value that should be checked - * @user_data: user data passed to the function - * - * A function that returns a boolean value depending on the input property. - * - * Returns: %TRUE if property satisfies condition else %FALSE - * - * Since: 0.2 - */ -typedef gboolean (*UfoFilterConditionFunc) (GValue *value, gpointer user_data); - -/** - * UfoInputParameter: - * @n_dims: Number of dimension the input accept - * @n_expected_items: Number of expected items. Use UFO_FILTER_INFINITE_INPUT to - * accept a data stream. - * @n_fetched_items: Number of fetched items. - * - * Data structure for describing the parameters of an input as used by - * ufo_filter_register_inputs(). - */ -struct _UfoInputParameter { - /* To be initialized by filter implementation */ - guint n_dims; - gint n_expected_items; - - /* Do not have to be set */ - gint n_fetched_items; -}; - -/** - * UfoOutputParameter: - * @n_dims: Number of dimension the input accept - * - * Data structure for describing the parameters of an output as used by - * ufo_filter_register_outputs(). - */ -struct _UfoOutputParameter { - guint n_dims; -}; - -/** - * UfoFilter: - * - * The contents of this object is opaque to the user. - */ -struct _UfoFilter { - /*< private >*/ - GObject parent; - - UfoFilterPrivate *priv; -}; - -/** - * UfoFilterClass: - * @parent: the parent class - * @initialize: the @initialize function is called by an UfoBaseScheduler to set - * up a filter before actual execution happens. It receives the first input - * data to which the filter can get adjust. - * @process_cpu: this method implements data processing on CPU. - * @process_gpu: this method implements data processing on GPU. - * - * The class structure for the UfoFilter type. - */ -struct _UfoFilterClass { - GObjectClass parent; - - void (*initialize) (UfoFilter *filter, - UfoBuffer *input[], - guint **output_dim_sizes, - GError **error); - void (*process_cpu) (UfoFilter *filter, - UfoBuffer *input[], - UfoBuffer *output[], - GError **error); - void (*process_gpu) (UfoFilter *filter, - UfoBuffer *input[], - UfoBuffer *output[], - GError **error); -}; - -void ufo_filter_initialize (UfoFilter *filter, - UfoBuffer *input[], - guint **output_dim_sizes, - GError **error); -void ufo_filter_set_resource_manager (UfoFilter *filter, - UfoResourceManager *manager); -UfoResourceManager *ufo_filter_get_resource_manager (UfoFilter *filter); -void ufo_filter_set_profiler (UfoFilter *filter, - UfoProfiler *profiler); -UfoProfiler * ufo_filter_get_profiler (UfoFilter *filter); -void ufo_filter_process_cpu (UfoFilter *filter, - UfoBuffer *input[], - UfoBuffer *output[], - GError **error); -void ufo_filter_process_gpu (UfoFilter *filter, - UfoBuffer *input[], - UfoBuffer *output[], - GError **error); -void ufo_filter_set_plugin_name (UfoFilter *filter, - const gchar *plugin_name); -const gchar* ufo_filter_get_plugin_name (UfoFilter *filter); -const gchar* ufo_filter_get_unique_name (UfoFilter *filter); -void ufo_filter_register_inputs (UfoFilter *filter, - guint n_inputs, - UfoInputParameter *input_parameters); -void ufo_filter_register_outputs (UfoFilter *filter, - guint n_outputs, - UfoOutputParameter *output_parameters); -UfoInputParameter *ufo_filter_get_input_parameters (UfoFilter *filter); -UfoOutputParameter *ufo_filter_get_output_parameters (UfoFilter *filter); -guint ufo_filter_get_num_inputs (UfoFilter *filter); -guint ufo_filter_get_num_outputs (UfoFilter *filter); -void ufo_filter_set_output_channel (UfoFilter *filter, - guint port, - UfoChannel *channel); -UfoChannel * ufo_filter_get_output_channel (UfoFilter *filter, - guint port); -void ufo_filter_set_input_channel (UfoFilter *filter, - guint port, - UfoChannel *channel); -void ufo_filter_set_command_queue (UfoFilter *filter, - gpointer cmd_queue); -gpointer ufo_filter_get_command_queue (UfoFilter *filter); -UfoChannel * ufo_filter_get_input_channel (UfoFilter *filter, - guint port); -void ufo_filter_wait_until (UfoFilter *filter, - GParamSpec *pspec, - UfoFilterConditionFunc condition, - gpointer user_data); -GType ufo_filter_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-gpu-node.c b/src/ufo-gpu-node.c new file mode 100644 index 0000000..b0d377d --- /dev/null +++ b/src/ufo-gpu-node.c @@ -0,0 +1,78 @@ +#include <CL/cl.h> +#include "ufo-gpu-node.h" + +G_DEFINE_TYPE (UfoGpuNode, ufo_gpu_node, UFO_TYPE_NODE) + +#define UFO_GPU_NODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_GPU_NODE, UfoGpuNodePrivate)) + + +struct _UfoGpuNodePrivate { + gpointer cmd_queue; +}; + +UfoNode * +ufo_gpu_node_new (gpointer cmd_queue) +{ + UfoGpuNode *node; + + g_return_val_if_fail (cmd_queue != NULL, NULL); + node = UFO_GPU_NODE (g_object_new (UFO_TYPE_GPU_NODE, NULL)); + node->priv->cmd_queue = cmd_queue; + clRetainCommandQueue (cmd_queue); + + return UFO_NODE (node); +} + +gpointer +ufo_gpu_node_get_cmd_queue (UfoGpuNode *node) +{ + g_return_val_if_fail (UFO_IS_GPU_NODE (node), NULL); + return node->priv->cmd_queue; +} + +static UfoNode * +ufo_gpu_node_copy_real (UfoNode *node, + GError **error) +{ + return UFO_NODE (ufo_gpu_node_new (UFO_GPU_NODE (node)->priv->cmd_queue)); +} + +static gboolean +ufo_gpu_node_equal_real (UfoNode *n1, + UfoNode *n2) +{ + g_return_val_if_fail (UFO_IS_GPU_NODE (n1) && UFO_IS_GPU_NODE (n2), FALSE); + return UFO_GPU_NODE (n1)->priv->cmd_queue == UFO_GPU_NODE (n2)->priv->cmd_queue; +} + +static void +ufo_gpu_node_dispose (GObject *object) +{ + UfoGpuNodePrivate *priv; + + priv = UFO_GPU_NODE_GET_PRIVATE (object); + clReleaseCommandQueue (priv->cmd_queue); + priv->cmd_queue = NULL; + G_OBJECT_CLASS (ufo_gpu_node_parent_class)->dispose (object); +} + +static void +ufo_gpu_node_class_init (UfoGpuNodeClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + UfoNodeClass *node_class = UFO_NODE_CLASS (klass); + + oclass->dispose = ufo_gpu_node_dispose; + node_class->copy = ufo_gpu_node_copy_real; + node_class->equal = ufo_gpu_node_equal_real; + + g_type_class_add_private (klass, sizeof (UfoGpuNodePrivate)); +} + +static void +ufo_gpu_node_init (UfoGpuNode *self) +{ + UfoGpuNodePrivate *priv; + self->priv = priv = UFO_GPU_NODE_GET_PRIVATE (self); + priv->cmd_queue = NULL; +} diff --git a/src/ufo-gpu-node.h b/src/ufo-gpu-node.h new file mode 100644 index 0000000..4e65520 --- /dev/null +++ b/src/ufo-gpu-node.h @@ -0,0 +1,49 @@ +#ifndef __UFO_GPU_NODE_H +#define __UFO_GPU_NODE_H + +#include <glib-object.h> +#include "ufo-node.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_GPU_NODE (ufo_gpu_node_get_type()) +#define UFO_GPU_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_GPU_NODE, UfoGpuNode)) +#define UFO_IS_GPU_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_GPU_NODE)) +#define UFO_GPU_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_GPU_NODE, UfoGpuNodeClass)) +#define UFO_IS_GPU_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_GPU_NODE)) +#define UFO_GPU_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_GPU_NODE, UfoGpuNodeClass)) + +typedef struct _UfoGpuNode UfoGpuNode; +typedef struct _UfoGpuNodeClass UfoGpuNodeClass; +typedef struct _UfoGpuNodePrivate UfoGpuNodePrivate; + +/** + * UfoGpuNode: + * + * Main object for organizing filters. The contents of the #UfoGpuNode structure + * are private and should only be accessed via the provided API. + */ +struct _UfoGpuNode { + /*< private >*/ + UfoNode parent_instance; + + UfoGpuNodePrivate *priv; +}; + +/** + * UfoGpuNodeClass: + * + * #UfoGpuNode class + */ +struct _UfoGpuNodeClass { + /*< private >*/ + UfoNodeClass parent_class; +}; + +UfoNode *ufo_gpu_node_new (gpointer cmd_queue); +gpointer ufo_gpu_node_get_cmd_queue (UfoGpuNode *gpu_node); +GType ufo_gpu_node_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-gpu-task-iface.c b/src/ufo-gpu-task-iface.c new file mode 100644 index 0000000..d830dfa --- /dev/null +++ b/src/ufo-gpu-task-iface.c @@ -0,0 +1,32 @@ +#include "ufo-gpu-task-iface.h" + +typedef UfoGpuTaskIface UfoGpuTaskInterface; + +G_DEFINE_INTERFACE (UfoGpuTask, ufo_gpu_task, UFO_TYPE_TASK) + +gboolean +ufo_gpu_task_process (UfoGpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition, + UfoGpuNode *node) +{ + return UFO_GPU_TASK_GET_IFACE (task)->process (task, inputs, output, requisition, node); +} + +static gboolean +ufo_gpu_task_process_real (UfoGpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition, + UfoGpuNode *node) +{ + g_warning ("`process' of UfoGpuTaskInterface not implemented"); + return FALSE; +} + +static void +ufo_gpu_task_default_init (UfoGpuTaskInterface *iface) +{ + iface->process = ufo_gpu_task_process_real; +} diff --git a/src/ufo-gpu-task-iface.h b/src/ufo-gpu-task-iface.h new file mode 100644 index 0000000..9a718f4 --- /dev/null +++ b/src/ufo-gpu-task-iface.h @@ -0,0 +1,37 @@ +#ifndef UFO_GPU_TASK_IFACE_H +#define UFO_GPU_TASK_IFACE_H + +#include <glib-object.h> +#include "ufo-gpu-node.h" +#include "ufo-task-iface.h" +#include "ufo-buffer.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_GPU_TASK (ufo_gpu_task_get_type()) +#define UFO_GPU_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_GPU_TASK, UfoGpuTask)) +#define UFO_GPU_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_GPU_TASK, UfoGpuTaskIface)) +#define UFO_IS_GPU_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_GPU_TASK)) +#define UFO_IS_GPU_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_GPU_TASK)) +#define UFO_GPU_TASK_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), UFO_TYPE_GPU_TASK, UfoGpuTaskIface)) + +typedef struct _UfoGpuTask UfoGpuTask; +typedef struct _UfoGpuTaskIface UfoGpuTaskIface; + +struct _UfoGpuTaskIface { + UfoTaskIface parent_iface; + + gboolean (*process) (UfoGpuTask *task, UfoBuffer **inputs, UfoBuffer *output, UfoRequisition *requisition, UfoGpuNode *node); +}; + +gboolean ufo_gpu_task_process (UfoGpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition, + UfoGpuNode *node); + +GType ufo_gpu_task_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-graph.c b/src/ufo-graph.c index 549fea3..bffdbb1 100644 --- a/src/ufo-graph.c +++ b/src/ufo-graph.c @@ -1,70 +1,21 @@ -/** - * SECTION:ufo-graph - * @Short_description: Organize filters - * @Title: UfoGraph - * - * A graph object represents the logical relationship between different filter - * nodes, i.e. how they are connected. Graphs can be constructed from - * free-standing #UfoFilter objects with ufo_graph_connect_filters() and - * ufo_graph_connect_filters_full() or load from a JSON description via - * ufo_graph_read_from_json(). - * - * A #UfoScheduler object is then used to "execute" the graph. - */ - -#include <glib.h> -#include <json-glib/json-glib.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-graph.h" -#include "ufo-aux.h" -#include "ufo-filter-source.h" -#include "ufo-plugin-manager.h" +#include <stdio.h> +#include <ufo-node.h> +#include <ufo-graph.h> G_DEFINE_TYPE (UfoGraph, ufo_graph, G_TYPE_OBJECT) #define UFO_GRAPH_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_GRAPH, UfoGraphPrivate)) -/** - * UfoTransferMode: - * @UFO_TRANSFER_MODE_DISTRIBUTE: Distribute data among connected filters. - * @UFO_TRANSFER_MODE_COPY: Re-use the same input data for all connected - * filters. - * - * The transfer mode specifies how the data is moved from one source filter to - * multiple sink filters when using ufo_graph_connect_filters_full(). - */ - -/** - * UfoGraphError: - * @UFO_GRAPH_ERROR_ALREADY_LOAD: Graph is already loaded - * @UFO_GRAPH_ERROR_JSON_KEY: Specified key not found in JSON file - * - * Possible errors when loading the graph from JSON. - */ -GQuark -ufo_graph_error_quark(void) -{ - return g_quark_from_static_string("ufo-graph-error-quark"); -} - typedef struct { - UfoFilter *to; - guint to_port; - guint from_port; -} Connection; + UfoNode *target; + gpointer label; +} UfoEdge; struct _UfoGraphPrivate { - UfoPluginManager *plugin_manager; - GHashTable *prop_sets; /**< maps from gchar* to JsonNode */ - GHashTable *connections; - GHashTable *filters; - GHashTable *json_filters; + GHashTable *adjacency; + GList *node_types; + GList *nodes; + guint n_edges; }; enum { @@ -72,657 +23,494 @@ enum { N_PROPERTIES }; -/* static GParamSpec *graph_properties[N_PROPERTIES] = { NULL, }; */ +UfoGraph * +ufo_graph_new (void) +{ + return UFO_GRAPH (g_object_new (UFO_TYPE_GRAPH, NULL)); +} -static void -handle_json_prop_set (JsonObject *object, - const gchar *name, - JsonNode *node, - gpointer user) +void +ufo_graph_register_node_type (UfoGraph *graph, + GType type) { UfoGraphPrivate *priv; - JsonObject *properties; - priv = (UfoGraphPrivate *) user; - properties = json_object_get_object_member (object, name); - json_object_ref (properties); - g_hash_table_insert (priv->prop_sets, g_strdup (name), properties); + g_return_if_fail (UFO_IS_GRAPH (graph)); + + /* Make sure type is at least a node type */ + g_return_if_fail (g_type_is_a (type, UFO_TYPE_NODE)); + + priv = graph->priv; + priv->node_types = g_list_append (priv->node_types, GINT_TO_POINTER (type)); } -static void -handle_json_single_prop (JsonObject *object, - const gchar *name, - JsonNode *node, - gpointer user) +/** + * ufo_graph_get_registered_node_types: + * @graph: A #UfoGraph + * + * Returns: (element-type GType) (transfer container): A list of #GType + * identifiers that can be added to @graph. + */ +GList * +ufo_graph_get_registered_node_types (UfoGraph *graph) { - GValue val = {0,}; - json_node_get_value (node, &val); - g_object_set_property (G_OBJECT(user), name, &val); + g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); + return g_list_copy (graph->priv->node_types); } -static gboolean -handle_json_filter_node (JsonNode *element, - UfoGraphPrivate *priv, - GError **error) +gboolean +ufo_graph_is_connected (UfoGraph *graph, + UfoNode *from, + UfoNode *to) { - UfoFilter *plugin; - JsonObject *object; - GError *tmp_error = NULL; - const gchar *name; - const gchar *plugin_name; - - object = json_node_get_object (element); - - if (!json_object_has_member (object, "plugin") || - !json_object_has_member (object, "name")) { - g_set_error (error, UFO_GRAPH_ERROR, UFO_GRAPH_ERROR_JSON_KEY, - "Node does not have `plugin' or `name' key"); - return FALSE; - } - - plugin_name = json_object_get_string_member (object, "plugin"); - plugin = ufo_plugin_manager_get_filter (priv->plugin_manager, plugin_name, &tmp_error); - - if (tmp_error != NULL) { - g_propagate_error (error, tmp_error); - return FALSE; - } - - name = json_object_get_string_member (object, "name"); - - if (g_hash_table_lookup (priv->json_filters, name) != NULL) - g_error ("Duplicate name `%s' found", name); - - g_hash_table_insert (priv->json_filters, g_strdup (name), plugin); - - if (json_object_has_member (object, "properties")) { - JsonObject *prop_object = json_object_get_object_member (object, "properties"); - json_object_foreach_member (prop_object, handle_json_single_prop, plugin); - } + UfoGraphPrivate *priv; + GList *successors; + gboolean found = FALSE; - if (json_object_has_member (object, "prop-refs")) { - JsonArray *prop_refs; + g_return_val_if_fail (UFO_IS_GRAPH (graph), FALSE); - prop_refs = json_object_get_array_member (object, "prop-refs"); + priv = graph->priv; + successors = g_hash_table_lookup (priv->adjacency, from); - for (guint i = 0; i < json_array_get_length (prop_refs); i++) { - const gchar *ref_name = json_array_get_string_element (prop_refs, i); - JsonObject *prop_set = g_hash_table_lookup (priv->prop_sets, ref_name); + for (GList *it = g_list_first (successors); it != NULL; it = g_list_next (it)) { + UfoEdge *edge = (UfoEdge *) it->data; - if (prop_set == NULL) { - g_warning ("No property set `%s' found in `prop-sets'", ref_name); - } - else { - json_object_foreach_member (prop_set, - handle_json_single_prop, - plugin); - } + if (edge->target == to) { + found = TRUE; + break; } } - return TRUE; + return found; } -static void -handle_json_filter_edge (JsonArray *array, - guint index, - JsonNode *element, - gpointer user) +static gboolean +is_valid_node_type (UfoGraphPrivate *priv, + UfoNode *node) { - UfoGraph *graph = user; - UfoGraphPrivate *priv = graph->priv; - JsonObject *edge; - UfoFilter *from_filter, *to_filter; - JsonObject *from_object, *to_object; - guint from_port, to_port; - const gchar *from_name; - const gchar *to_name; - GError *error = NULL; - - edge = json_node_get_object (element); - - if (!json_object_has_member (edge, "from") || - !json_object_has_member (edge, "to")) { - g_error ("Edge does not have `from' or `to' key"); - return; - } - - /* Get from details */ - from_object = json_object_get_object_member (edge, "from"); - - if (!json_object_has_member (from_object, "name")) { - g_error ("From node does not have `name' key"); - return; - } - - from_name = json_object_get_string_member (from_object, "name"); - from_port = 0; - - if (json_object_has_member (from_object, "output")) - from_port = (guint) json_object_get_int_member (from_object, "output"); - - /* Get to details */ - to_object = json_object_get_object_member (edge, "to"); + for (GList *it = g_list_first (priv->node_types); it != NULL; it = g_list_next (it)) { + GType type = (GType) GPOINTER_TO_INT (it->data); - if (!json_object_has_member (to_object, "name")) { - g_error ("To node does not have `name' key"); - return; + if (G_TYPE_CHECK_INSTANCE_TYPE (node, type)) + return TRUE; } - to_name = json_object_get_string_member (to_object, "name"); - to_port = 0; - - if (json_object_has_member (to_object, "input")) - to_port = (guint) json_object_get_int_member (to_object, "input"); - - /* Get actual filters and connect them */ - from_filter = g_hash_table_lookup (priv->json_filters, from_name); - to_filter = g_hash_table_lookup (priv->json_filters, to_name); - - ufo_graph_connect_filters_full (graph, - from_filter, from_port, - to_filter, to_port, - UFO_TRANSFER_MODE_DISTRIBUTE, - &error); - - if (error != NULL) - g_warning ("%s", error->message); + return FALSE; } static void -graph_build (UfoGraph *graph, JsonNode *root, GError **error) +add_node_if_not_found (UfoGraphPrivate *priv, + UfoNode *node) { - JsonObject *root_object = json_node_get_object(root); + if (!g_list_find (priv->nodes, node)) + priv->nodes = g_list_append (priv->nodes, node); +} - if (json_object_has_member(root_object, "prop-sets")) { - JsonObject *sets = json_object_get_object_member (root_object, "prop-sets"); - json_object_foreach_member (sets, handle_json_prop_set, graph->priv); - } +void +ufo_graph_connect_nodes (UfoGraph *graph, + UfoNode *source, + UfoNode *target, + gpointer edge_label) +{ + UfoGraphPrivate *priv; + UfoEdge *edge; + GList *successors; - if (json_object_has_member (root_object, "nodes")) { - JsonArray *nodes = json_object_get_array_member (root_object, "nodes"); - GList *elements = json_array_get_elements (nodes); + g_return_if_fail (UFO_IS_GRAPH (graph)); + priv = graph->priv; - for (GList *it = g_list_first (elements); it != NULL; it = g_list_next (it)) { - if (!handle_json_filter_node (it->data, graph->priv, error)) { - g_list_free (elements); - return; - } - } + g_return_if_fail (is_valid_node_type (priv, source) && is_valid_node_type (priv, target)); - g_list_free (elements); + edge = g_new0 (UfoEdge, 1); + edge->target = target; + edge->label = edge_label; - /* - * We only check edges if we have nodes, anything else doesn't make much - * sense. - */ - if (json_object_has_member (root_object, "edges")) { - JsonArray *edges = json_object_get_array_member (root_object, "edges"); - json_array_foreach_element (edges, handle_json_filter_edge, graph); - } - } -} + successors = g_hash_table_lookup (priv->adjacency, source); + successors = g_list_append (successors, edge); + g_hash_table_insert (priv->adjacency, source, successors); -static JsonObject * -json_object_from_ufo_filter (UfoFilter *filter) -{ - JsonObject *object = json_object_new (); + add_node_if_not_found (priv, source); + add_node_if_not_found (priv, target); - json_object_set_string_member (object, "name", ufo_filter_get_unique_name (filter)); - return object; + priv->n_edges++; } -static void -graph_add_filter_to_json_array(gpointer data, gpointer user_data) +guint +ufo_graph_get_num_nodes (UfoGraph *graph) { - g_return_if_fail (UFO_IS_FILTER (data)); - - UfoFilter *filter = UFO_FILTER (data); - JsonArray *array = (JsonArray *) user_data; - JsonObject *node_object = json_object_new (); - - const gchar *plugin_name = ufo_filter_get_plugin_name (filter); - json_object_set_string_member (node_object, "plugin", plugin_name); - - json_object_set_string_member (node_object, "name", ufo_filter_get_unique_name (filter)); - - JsonNode *prop_node = json_gobject_serialize (G_OBJECT (filter)); - json_object_set_member (node_object, "properties", prop_node); + g_return_val_if_fail (UFO_IS_GRAPH (graph), 0); + return g_list_length (graph->priv->nodes); +} - json_array_add_object_element (array, node_object); +guint +ufo_graph_get_num_edges (UfoGraph *graph) +{ + g_return_val_if_fail (UFO_IS_GRAPH (graph), 0); + return graph->priv->n_edges; } /** - * ufo_graph_new: - * - * Create a new #UfoGraph. + * ufo_graph_get_nodes: + * @graph: A #UfoGraph * - * Return value: A #UfoGraph. + * Returns: (element-type UfoNode) (transfer container): A list of all nodes + * added to @graph. */ -UfoGraph * -ufo_graph_new (void) +GList * +ufo_graph_get_nodes (UfoGraph *graph) { - return UFO_GRAPH (g_object_new (UFO_TYPE_GRAPH, NULL)); + g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); + return graph->priv->nodes; } /** - * ufo_graph_read_from_json: - * @graph: A #UfoGraph. - * @manager: A #UfoPluginManager used to load the filters - * @filename: Path and filename to the JSON file - * @error: Indicates error in case of failed file loading or parsing + * ufo_graph_get_nodes_filtered: + * @graph: A #UfoGraph + * @func: Predicate function to filter out nodes * - * Read a JSON configuration file to fill the filter structure of @graph. + * Returns: (element-type UfoNode) (transfer container): A list of all nodes + * that are marked as true by the predicate function @func. */ -void -ufo_graph_read_from_json (UfoGraph *graph, UfoPluginManager *manager, const gchar *filename, GError **error) +GList * +ufo_graph_get_nodes_filtered (UfoGraph *graph, + UfoFilterPredicate func) { - g_return_if_fail (UFO_IS_GRAPH(graph) && UFO_IS_PLUGIN_MANAGER (manager) && (filename != NULL)); - JsonParser *json_parser = json_parser_new (); - GError *tmp_error = NULL; + UfoGraphPrivate *priv; + GList *result = NULL; - if (!json_parser_load_from_file (json_parser, filename, &tmp_error)) { - g_propagate_prefixed_error (error, tmp_error, "Parsing JSON: "); - return; - } + g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); + priv = graph->priv; - graph->priv->plugin_manager = manager; - g_object_ref (manager); + for (GList *it = g_list_first (priv->nodes); it != NULL; it = g_list_next (it)) { + UfoNode *node = UFO_NODE (it->data); + + if (func (node)) + result = g_list_append (result, node); + } - graph_build (graph, json_parser_get_root (json_parser), error); - g_object_unref (json_parser); + return result; } -/** - * ufo_graph_save_to_json: - * @graph: A #UfoGraph. - * @filename: Path and filename to the JSON file - * @error: Indicates error in case of failed file saving - * - * Save a JSON configuration file with the filter structure of @graph. - */ void -ufo_graph_save_to_json (UfoGraph *graph, const gchar *filename, GError **error) +ufo_graph_remove_edge (UfoGraph *graph, + UfoNode *source, + UfoNode *target) { UfoGraphPrivate *priv; - GList *filters; - GList *sources; - GError *tmp_error = NULL; - - g_return_if_fail (UFO_IS_GRAPH (graph) && (filename != NULL)); + GList *edges; - priv = UFO_GRAPH_GET_PRIVATE (graph); - - JsonGenerator *json_generator = json_generator_new (); - JsonNode *root_node = json_node_new (JSON_NODE_OBJECT); - JsonObject *root_object = json_object_new (); - JsonArray *nodes = json_array_new (); - JsonArray *edges = json_array_new (); + g_return_if_fail (UFO_IS_GRAPH (graph)); + priv = graph->priv; - filters = g_hash_table_get_keys (priv->filters); - g_list_foreach (filters, graph_add_filter_to_json_array, nodes); - g_list_free (filters); + edges = g_hash_table_lookup (priv->adjacency, source); - sources = g_hash_table_get_keys (priv->connections); + if (edges != NULL) { + UfoEdge *edge = NULL; - for (GList *it = g_list_first (sources); it != NULL; it = g_list_next (it)) { - UfoFilter *from; - GList *connections; + for (GList *it = g_list_first (edges); it != NULL; it = g_list_next (it)) { + UfoEdge *candidate = (UfoEdge *) it->data; - from = UFO_FILTER (it->data); - connections = g_hash_table_lookup (priv->connections, from); + if (candidate->target == target) { + edge = candidate; + break; + } + } - for (GList *jt = g_list_first (connections); jt != NULL; jt = g_list_next (jt)) { - Connection *c = (Connection *) jt->data; + if (edge != NULL) { + priv->nodes = g_list_remove (priv->nodes, source); + g_object_unref (source); - JsonObject *to_object = json_object_from_ufo_filter (c->to); - JsonObject *from_object = json_object_from_ufo_filter (from); - JsonObject *edge_object = json_object_new (); + priv->nodes = g_list_remove (priv->nodes, edge->target); + g_object_unref (edge->target); - json_object_set_int_member (to_object, "input", c->to_port); - json_object_set_int_member (from_object, "output", c->from_port); - json_object_set_object_member (edge_object, "to", to_object); - json_object_set_object_member (edge_object, "from", from_object); - json_array_add_object_element (edges, edge_object); + edges = g_list_remove (edges, edge); + g_hash_table_insert (priv->adjacency, source, edges); } - - g_list_free (connections); } - g_list_free (sources); + priv->n_edges--; +} - json_object_set_array_member(root_object, "nodes", nodes); - json_object_set_array_member(root_object, "edges", edges); - json_node_set_object(root_node, root_object); - json_generator_set_root(json_generator, root_node); +gpointer +ufo_graph_get_edge_label (UfoGraph *graph, + UfoNode *source, + UfoNode *target) +{ + UfoGraphPrivate *priv; + GList *edges; - if (!json_generator_to_file(json_generator, filename, &tmp_error)) { - g_propagate_error(error, tmp_error); - return; - } + g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); + priv = graph->priv; + edges = g_hash_table_lookup (priv->adjacency, source); - g_object_unref(json_generator); -} + for (GList *it = g_list_first (edges); it != NULL; it = g_list_next (it)) { + UfoEdge *edge = (UfoEdge *) it->data; -/** - * ufo_graph_connect_filters: - * @graph: A #UfoGraph - * @from: Source filter - * @to: Destination filter - * @error: return location for error - * - * Connect to filters using their default input and output ports. - */ -void -ufo_graph_connect_filters (UfoGraph *graph, UfoFilter *from, UfoFilter *to, GError **error) -{ - ufo_graph_connect_filters_full (graph, from, 0, to, 0, UFO_TRANSFER_MODE_DISTRIBUTE, error); -} + if (edge->target == target) { + gpointer label = edge->label; + return label; + } + } -static void -add_connection (UfoGraphPrivate *priv, - UfoFilter *from, - guint from_port, - UfoFilter *to, - guint to_port) -{ - GList *connections; - Connection *c; - - c = g_new0 (Connection, 1); - c->from_port = from_port; - c->to = to; - c->to_port = to_port; - - connections = g_hash_table_lookup (priv->connections, from); - connections = g_list_append (connections, c); - g_hash_table_insert (priv->connections, from, connections); - g_hash_table_insert (priv->filters, from, NULL); - g_hash_table_insert (priv->filters, to, NULL); + g_warning ("target not found"); + return NULL; } -static GList * -get_connected_set (UfoGraphPrivate *priv, - UfoFilter *from, - guint from_port) +static gboolean +has_predecessor (UfoGraph *graph, + UfoNode *node) { - GList *connections; - GList *set = NULL; - - connections = g_hash_table_lookup (priv->connections, from); - - for (GList *it = g_list_first (connections); it != NULL; it = g_list_next (it)) { - Connection *c = (Connection *) it->data; + for (GList *it = g_list_first (graph->priv->nodes); it != NULL; it = g_list_next (it)) { + UfoNode *source = (UfoNode *) it->data; - if (c->from_port == from_port) - set = g_list_append (set, c); + if (ufo_graph_is_connected (graph, source, node)) + return TRUE; } - return set; + return FALSE; } /** - * ufo_graph_connect_filters_full: + * ufo_graph_get_roots: * @graph: A #UfoGraph - * @from: Source filter - * @from_port: Source output port - * @to: Destination filter - * @to_port: Destination input port - * @mode: Transfer mode for multiple sinks - * @error: return location for error * - * Connect two filters with the specified input and output ports. + * Returns: (element-type UfoNode) (transfer container): A list of all nodes + * that do not have a predessor node. */ -void -ufo_graph_connect_filters_full (UfoGraph *graph, - UfoFilter *from, - guint from_port, - UfoFilter *to, - guint to_port, - UfoTransferMode mode, - GError **error) +GList * +ufo_graph_get_roots (UfoGraph *graph) { UfoGraphPrivate *priv; - UfoChannel *channel; + GList *result; - g_return_if_fail (UFO_IS_GRAPH (graph) && UFO_IS_FILTER (from) && UFO_IS_FILTER (to)); + g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); priv = graph->priv; + result = NULL; - channel = ufo_filter_get_input_channel (to, to_port); - - if (channel != NULL) { - g_warning ("Input %s:%i is already in use.", - ufo_filter_get_unique_name (to), - to_port); - } - - channel = ufo_filter_get_output_channel (from, from_port); - - if (mode == UFO_TRANSFER_MODE_DISTRIBUTE) { - if (channel == NULL) { - channel = ufo_filter_get_input_channel (to, to_port); - - if (channel == NULL) - channel = ufo_channel_new (); - } - - ufo_filter_set_output_channel (from, from_port, channel); - ufo_filter_set_input_channel (to, to_port, channel); - ufo_channel_ref (channel); - } - else if (mode == UFO_TRANSFER_MODE_COPY) { - if (channel == NULL) { - channel = ufo_filter_get_input_channel (to, to_port); - - if (channel == NULL) - channel = ufo_channel_new (); + for (GList *it = g_list_first (priv->nodes); it != NULL; it = g_list_next (it)) { + UfoNode *node = (UfoNode *) it->data; - ufo_filter_set_output_channel (from, from_port, channel); - ufo_filter_set_input_channel (to, to_port, channel); - ufo_channel_ref (channel); - } - else { - GList *set; - GList *last; - Connection *connection; - UfoChannel *new_channel; - - set = get_connected_set (priv, from, from_port); - last = g_list_last (set); - g_assert (last != NULL); - - connection = (Connection *) last->data; - channel = ufo_filter_get_input_channel (connection->to, connection->to_port); - g_assert (channel != NULL); - - new_channel = ufo_channel_new (); - ufo_channel_ref (new_channel); - ufo_channel_daisy_chain (channel, new_channel); - ufo_filter_set_input_channel (to, to_port, new_channel); - } + if (!has_predecessor (graph, node)) + result = g_list_append (result, node); } - add_connection (priv, from, from_port, to, to_port); - g_debug ("Connected %s:%i and %s:%i", - ufo_filter_get_unique_name (from), from_port, - ufo_filter_get_unique_name (to), to_port); + return result; } /** - * ufo_graph_get_filters: + * ufo_graph_get_successors: * @graph: A #UfoGraph * - * Return a list of all filter nodes of @graph. - * - * Returns: (element-type UfoFilter) (transfer full): List of filter nodes. Use - * g_list_free() when done using the list. + * Returns: (element-type UfoNode) (transfer container): All succeeding nodes of + * @node. */ GList * -ufo_graph_get_filters (UfoGraph *graph) +ufo_graph_get_successors (UfoGraph *graph, + UfoNode *node) { + UfoGraphPrivate *priv; + GList *edges; + GList *result; + g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); - return g_hash_table_get_keys (graph->priv->filters); + priv = graph->priv; + edges = g_hash_table_lookup (priv->adjacency, node); + result = NULL; + + for (GList *it = g_list_first (edges); it != NULL; it = g_list_next (it)) { + UfoEdge *edge = (UfoEdge *) it->data; + result = g_list_prepend (result, edge->target); + } + + return result; } /** - * ufo_graph_get_num_filters: + * ufo_graph_split: * @graph: A #UfoGraph + * @path: (element-type UfoNode): A path of nodes, preferably created with + * ufo_graph_get_paths(). * - * Return the number of filters connected in the graph. - * - * Returns: Number of filters. + * Duplicate nodes between head and tail of path and insert at the exact the + * position of where path started and ended. */ -guint -ufo_graph_get_num_filters (UfoGraph *graph) +void +ufo_graph_split (UfoGraph *graph, + GList *path) { - GList *filters; - guint n_filters; + GList *head; + GList *tail; + UfoNode *orig; + UfoNode *current; + GError *error = NULL; + + g_return_if_fail (UFO_IS_GRAPH (graph)); + + head = g_list_first (path); + tail = g_list_last (path); + g_assert (head != tail); + + orig = UFO_NODE (head->data); - filters = ufo_graph_get_filters (graph); - n_filters = g_list_length (filters); - g_list_free (filters); - return n_filters; + /* The first link goes from the original head */ + current = orig; + + for (GList *it = g_list_next (head); it != tail; it = g_list_next (it)) { + UfoNode *next; + UfoNode *copy; + gpointer label; + + next = UFO_NODE (it->data); + copy = ufo_node_copy (next, &error); + label = ufo_graph_get_edge_label (graph, orig, next); + ufo_graph_connect_nodes (graph, current, copy, label); + current = copy; + orig = next; + } + + if (tail->data != NULL) { + ufo_graph_connect_nodes (graph, current, UFO_NODE (tail->data), + ufo_graph_get_edge_label (graph, orig, UFO_NODE (tail->data))); + } } -/** - * ufo_graph_get_roots: - * @graph: A #UfoGraph - * - * Return a list of #UfoFilterSource nodes in @graph that do not have any - * parents. - * - * Returns: (element-type UfoFilter) (transfer none): List of filter nodes. Use - * g_list_free() when done using the list. - */ -GList * -ufo_graph_get_roots (UfoGraph *graph) +static void +pickup_paths (UfoGraph *graph, + UfoFilterPredicate pred, + UfoNode *current, + UfoNode *last, + GList *current_path, + GList **paths) { - GList *filters; - GList *roots = NULL; + GList *successors; - g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); - filters = ufo_graph_get_filters (graph); + if (pred (current)) { + if (!pred (last)) + current_path = g_list_append (current_path, last); + + current_path = g_list_append (current_path, current); + } + else { + if (current_path != NULL) { + current_path = g_list_append (current_path, current); + *paths = g_list_append (*paths, current_path); + } - for (GList *it = g_list_first (filters); it != NULL; it = g_list_next (it)) { - if (UFO_IS_FILTER_SOURCE (it->data)) - roots = g_list_append (roots, it->data); + current_path = NULL; } - g_list_free (filters); - return roots; + successors = ufo_graph_get_successors (graph, current); + + for (GList *it = g_list_first (successors); it != NULL; it = g_list_next (it)) + pickup_paths (graph, pred, it->data, current, g_list_copy (current_path), paths); + + g_list_free (successors); } /** - * ufo_graph_get_children: + * ufo_graph_get_paths: * @graph: A #UfoGraph - * @filter: A #UfoFilter + * @pred: A predicate function * - * Return a list of nodes in @graph that @filter connects to. + * Compute a list of lists that contain complete paths with nodes that match a + * predicate function. * - * Returns: (element-type UfoFilter) (transfer none): List of filter nodes. Use g_list_free() - * when done using the list. + * Returns: (element-type GLib.GList) (transfer full): A list of lists with paths + * that match @pred. */ GList * -ufo_graph_get_children (UfoGraph *graph, - UfoFilter *filter) +ufo_graph_get_paths (UfoGraph *graph, + UfoFilterPredicate pred) { - UfoGraphPrivate *priv; - GList *connections; - GList *result = NULL; + GList *roots; + GList *paths = NULL; - g_return_val_if_fail (UFO_IS_GRAPH (graph), NULL); - priv = graph->priv; - connections = g_hash_table_lookup (priv->connections, filter); + roots = ufo_graph_get_roots (graph); - for (GList *it = g_list_first (connections); it != NULL; it = g_list_next (it)) { - Connection *c = (Connection *) it->data; - result = g_list_append (result, c->to); + for (GList *it = g_list_first (roots); it != NULL; it = g_list_next (it)) { + UfoNode *node = UFO_NODE (it->data); + pickup_paths (graph, pred, node, node, NULL, &paths); } - return result; + g_list_free (roots); + return paths; } -static void -unref_list_elements (GList *l) +void +ufo_graph_dump_dot (UfoGraph *graph, + const gchar *filename) { - g_list_foreach (l, (GFunc) g_object_unref, NULL); -} + FILE *fp; + GList *nodes; -static void -ufo_graph_dispose(GObject *object) -{ - UfoGraph *graph = UFO_GRAPH (object); - UfoGraphPrivate *priv = UFO_GRAPH_GET_PRIVATE (graph); + fp = fopen (filename, "w"); + fprintf (fp, "digraph foo {\n"); - unref_list_elements (g_hash_table_get_values (priv->json_filters)); + nodes = ufo_graph_get_nodes (graph); - ufo_unref_stored_object ((GObject **) &priv->plugin_manager); + for (GList *it = g_list_first (nodes); it != NULL; it = g_list_next (it)) { + UfoNode *source; + GList *successors; - G_OBJECT_CLASS (ufo_graph_parent_class)->dispose (object); - g_message ("UfoGraph: disposed"); -} + source = UFO_NODE (it->data); + successors = ufo_graph_get_successors (graph, source); -static void -ufo_graph_finalize (GObject *object) -{ - UfoGraph *self = UFO_GRAPH (object); - UfoGraphPrivate *priv = UFO_GRAPH_GET_PRIVATE (self); + for (GList *jt = g_list_first (successors); jt != NULL; jt = g_list_next (jt)) { + UfoNode *target; - g_hash_table_destroy (priv->prop_sets); - g_hash_table_destroy (priv->json_filters); - g_hash_table_destroy (priv->filters); - g_hash_table_destroy (priv->connections); + target = UFO_NODE (jt->data); - priv->connections = NULL; - priv->prop_sets = NULL; + fprintf (fp, " %s_%p -> %s_%p;\n", + g_type_name (G_TYPE_FROM_INSTANCE (source)), (gpointer) source, + g_type_name (G_TYPE_FROM_INSTANCE (target)), (gpointer) target); + } - G_OBJECT_CLASS (ufo_graph_parent_class)->finalize (object); - g_message ("UfoGraph: finalized"); -} + g_list_free (successors); + } -static void -ufo_graph_constructed (GObject *object) -{ - if (G_OBJECT_CLASS (ufo_graph_parent_class)->constructed != NULL) - G_OBJECT_CLASS (ufo_graph_parent_class)->constructed (object); + fprintf (fp, "}\n"); + fclose (fp); } static void -ufo_graph_set_property(GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +ufo_graph_dispose (GObject *object) { - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; + UfoGraphPrivate *priv; + + priv = UFO_GRAPH_GET_PRIVATE (object); + + if (priv->adjacency != NULL) { + g_hash_table_destroy (priv->adjacency); + priv->adjacency = NULL; } + + g_list_foreach (priv->nodes, (GFunc) g_object_unref, NULL); + + G_OBJECT_CLASS (ufo_graph_parent_class)->dispose (object); } static void -ufo_graph_get_property(GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) +ufo_graph_finalize (GObject *object) { - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; + UfoGraphPrivate *priv; + + priv = UFO_GRAPH_GET_PRIVATE (object); + + if (priv->nodes) { + g_list_free (priv->nodes); + priv->nodes = NULL; } + + G_OBJECT_CLASS (ufo_graph_parent_class)->finalize (object); } static void ufo_graph_class_init (UfoGraphClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GObjectClass *oclass = G_OBJECT_CLASS (klass); - gobject_class->set_property = ufo_graph_set_property; - gobject_class->get_property = ufo_graph_get_property; - gobject_class->dispose = ufo_graph_dispose; - gobject_class->finalize = ufo_graph_finalize; - gobject_class->constructed = ufo_graph_constructed; + oclass->dispose = ufo_graph_dispose; + oclass->finalize = ufo_graph_finalize; g_type_class_add_private(klass, sizeof(UfoGraphPrivate)); } @@ -732,16 +520,8 @@ ufo_graph_init (UfoGraph *self) { UfoGraphPrivate *priv; self->priv = priv = UFO_GRAPH_GET_PRIVATE (self); - - priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, NULL); - priv->filters = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, NULL); - priv->prop_sets = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify) json_object_unref); - priv->json_filters = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - - g_thread_init (NULL); + priv->adjacency = g_hash_table_new (g_direct_hash, g_direct_equal); + priv->node_types = NULL; + priv->nodes = NULL; + priv->n_edges = 0; } - diff --git a/src/ufo-graph.h b/src/ufo-graph.h index 8067b2b..a8b6f89 100644 --- a/src/ufo-graph.h +++ b/src/ufo-graph.h @@ -2,8 +2,7 @@ #define __UFO_GRAPH_H #include <glib-object.h> -#include "ufo-plugin-manager.h" -#include "ufo-filter.h" +#include "ufo-node.h" G_BEGIN_DECLS @@ -14,21 +13,12 @@ G_BEGIN_DECLS #define UFO_IS_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_GRAPH)) #define UFO_GRAPH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_GRAPH, UfoGraphClass)) -#define UFO_GRAPH_ERROR ufo_graph_error_quark() -typedef enum { - UFO_GRAPH_ERROR_ALREADY_LOAD, - UFO_GRAPH_ERROR_JSON_KEY -} UfoGraphError; - -typedef enum { - UFO_TRANSFER_MODE_DISTRIBUTE, - UFO_TRANSFER_MODE_COPY -} UfoTransferMode; - typedef struct _UfoGraph UfoGraph; typedef struct _UfoGraphClass UfoGraphClass; typedef struct _UfoGraphPrivate UfoGraphPrivate; +typedef gboolean (*UfoFilterPredicate) (UfoNode *node); + /** * UfoGraph: * @@ -53,31 +43,38 @@ struct _UfoGraphClass { }; UfoGraph *ufo_graph_new (void); -void ufo_graph_read_from_json (UfoGraph *graph, - UfoPluginManager *manager, - const gchar *filename, - GError **error); -void ufo_graph_save_to_json (UfoGraph *graph, - const gchar *filename, - GError **error); -void ufo_graph_connect_filters (UfoGraph *graph, - UfoFilter *from, - UfoFilter *to, - GError **error); -void ufo_graph_connect_filters_full (UfoGraph *graph, - UfoFilter *from, - guint from_port, - UfoFilter *to, - guint to_port, - UfoTransferMode mode, - GError **error); -GList *ufo_graph_get_filters (UfoGraph *graph); -guint ufo_graph_get_num_filters (UfoGraph *graph); -GList *ufo_graph_get_roots (UfoGraph *graph); -GList *ufo_graph_get_children (UfoGraph *graph, - UfoFilter *filter); +void ufo_graph_register_node_type (UfoGraph *graph, + GType type); +GList *ufo_graph_get_registered_node_types + (UfoGraph *graph); +void ufo_graph_connect_nodes (UfoGraph *graph, + UfoNode *source, + UfoNode *target, + gpointer edge_label); +gboolean ufo_graph_is_connected (UfoGraph *graph, + UfoNode *from, + UfoNode *to); +void ufo_graph_remove_edge (UfoGraph *graph, + UfoNode *source, + UfoNode *target); +gpointer ufo_graph_get_edge_label (UfoGraph *graph, + UfoNode *source, + UfoNode *target); +guint ufo_graph_get_num_nodes (UfoGraph *graph); +guint ufo_graph_get_num_edges (UfoGraph *graph); +GList *ufo_graph_get_nodes (UfoGraph *graph); +GList *ufo_graph_get_nodes_filtered (UfoGraph *graph, + UfoFilterPredicate func); +GList *ufo_graph_get_roots (UfoGraph *graph); +GList *ufo_graph_get_successors (UfoGraph *graph, + UfoNode *node); +GList *ufo_graph_get_paths (UfoGraph *graph, + UfoFilterPredicate pred); +void ufo_graph_split (UfoGraph *graph, + GList *path); +void ufo_graph_dump_dot (UfoGraph *graph, + const gchar *filename); GType ufo_graph_get_type (void); -GQuark ufo_graph_error_quark (void); G_END_DECLS diff --git a/src/ufo-group.c b/src/ufo-group.c new file mode 100644 index 0000000..25b08fa --- /dev/null +++ b/src/ufo-group.c @@ -0,0 +1,233 @@ +#include <CL/cl.h> +#include "ufo-group.h" +#include "ufo-task-node.h" + +G_DEFINE_TYPE (UfoGroup, ufo_group, G_TYPE_OBJECT) + +#define UFO_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_GROUP, UfoGroupPrivate)) + +typedef struct { + GAsyncQueue *queues[2]; + guint capacity; +} UfoQueue; + +struct _UfoGroupPrivate { + GList *targets; + guint n_targets; + UfoQueue **queues; + gboolean *ready; + UfoSendPattern pattern; + guint current; + cl_context context; + GList *buffers; +}; + +enum { + PROP_0, + N_PROPERTIES +}; + +typedef enum { + UFO_QUEUE_PRODUCER = 0, + UFO_QUEUE_CONSUMER = 1 +} UfoQueueAccess; + +static UfoQueue *ufo_queue_new (void); +static gpointer ufo_queue_pop (UfoQueue *queue, UfoQueueAccess access); +static void ufo_queue_push (UfoQueue *queue, UfoQueueAccess access, gpointer data); +static void ufo_queue_insert (UfoQueue *queue, UfoQueueAccess access, gpointer data); +static guint ufo_queue_get_capacity (UfoQueue *queue); + +/** + * ufo_group_new: + * @targets: (element-type UfoNode): A list of #UfoNode targets + * @context: A cl_context on which the targets should operate on. + * + * Returns: A new #UfoGroup. + */ +UfoGroup * +ufo_group_new (GList *targets, + gpointer context) +{ + UfoGroup *group; + UfoGroupPrivate *priv; + + group = UFO_GROUP (g_object_new (UFO_TYPE_GROUP, NULL)); + priv = group->priv; + + priv->targets = targets; + priv->n_targets = g_list_length (targets); + priv->queues = g_new0 (UfoQueue *, priv->n_targets); + priv->pattern = UFO_SEND_SCATTER; + priv->current = 0; + priv->context = context; + + for (guint i = 0; i < priv->n_targets; i++) + priv->queues[i] = ufo_queue_new (); + + return group; +} + +UfoBuffer * +ufo_group_pop_output_buffer (UfoGroup *group, + UfoRequisition *requisition) +{ + UfoBuffer *output; + UfoGroupPrivate *priv; + + priv = group->priv; + + if (ufo_queue_get_capacity (priv->queues[priv->current]) < priv->n_targets) { + output = ufo_buffer_new (requisition, priv->context); + priv->buffers = g_list_append (priv->buffers, output); + ufo_queue_insert (priv->queues[priv->current], + UFO_QUEUE_PRODUCER, + output); + } + + output = ufo_queue_pop (priv->queues[priv->current], + UFO_QUEUE_PRODUCER); + + if (!ufo_buffer_cmp_dimensions (output, requisition)) + ufo_buffer_resize (output, requisition); + + return output; +} + +void +ufo_group_push_output_buffer (UfoGroup *group, + UfoBuffer *buffer) +{ + UfoGroupPrivate *priv; + + priv = group->priv; + + /* Copy or not depending on the send pattern */ + if (priv->pattern == UFO_SEND_SCATTER) { + ufo_queue_push (priv->queues[priv->current], + UFO_QUEUE_PRODUCER, + buffer); + + priv->current = (priv->current + 1) % priv->n_targets; + } + else + g_print ("Other send methods are not yet supported\n"); +} + +UfoBuffer * +ufo_group_pop_input_buffer (UfoGroup *group, + UfoTask *target) +{ + UfoGroupPrivate *priv; + UfoBuffer *input; + gint pos; + + priv = group->priv; + pos = g_list_index (priv->targets, target); + input = pos >= 0 ? ufo_queue_pop (priv->queues[pos], UFO_QUEUE_CONSUMER) : NULL; + + return input; +} + +void +ufo_group_push_input_buffer (UfoGroup *group, + UfoTask *target, + UfoBuffer *input) +{ + UfoGroupPrivate *priv; + gint pos; + + priv = group->priv; + pos = g_list_index (priv->targets, target); + + if (pos >= 0) + ufo_queue_push (priv->queues[pos], UFO_QUEUE_CONSUMER, input); +} + +void +ufo_group_finish (UfoGroup *group) +{ + UfoGroupPrivate *priv; + + priv = group->priv; + + for (guint i = 0; i < priv->n_targets; i++) { + ufo_queue_push (priv->queues[i], + UFO_QUEUE_PRODUCER, + UFO_END_OF_STREAM); + } +} + +static UfoQueue * +ufo_queue_new (void) +{ + UfoQueue *queue = g_new0 (UfoQueue, 1); + queue->queues[0] = g_async_queue_new (); + queue->queues[1] = g_async_queue_new (); + queue->capacity = 0; + return queue; +} + +static gpointer +ufo_queue_pop (UfoQueue *queue, UfoQueueAccess access) +{ + return g_async_queue_pop (queue->queues[access]); +} + +static void +ufo_queue_push (UfoQueue *queue, UfoQueueAccess access, gpointer data) +{ + g_async_queue_push (queue->queues[1-access], data); +} + +static void +ufo_queue_insert (UfoQueue *queue, UfoQueueAccess access, gpointer data) +{ + g_async_queue_push (queue->queues[access], data); + queue->capacity++; +} + +static guint +ufo_queue_get_capacity (UfoQueue *queue) +{ + return queue->capacity; +} + +static void +ufo_group_dispose(GObject *object) +{ + UfoGroupPrivate *priv; + + priv = UFO_GROUP_GET_PRIVATE (object); + g_list_foreach (priv->buffers, (GFunc) g_object_unref, NULL); + G_OBJECT_CLASS (ufo_group_parent_class)->dispose (object); +} + +static void +ufo_group_finalize (GObject *object) +{ + UfoGroupPrivate *priv; + + priv = UFO_GROUP_GET_PRIVATE (object); + g_list_free (priv->buffers); + G_OBJECT_CLASS (ufo_group_parent_class)->finalize (object); +} + +static void +ufo_group_class_init (UfoGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = ufo_group_dispose; + gobject_class->finalize = ufo_group_finalize; + + g_type_class_add_private(klass, sizeof(UfoGroupPrivate)); +} + +static void +ufo_group_init (UfoGroup *self) +{ + UfoGroupPrivate *priv; + self->priv = priv = UFO_GROUP_GET_PRIVATE (self); + priv->buffers = NULL; +} diff --git a/src/ufo-group.h b/src/ufo-group.h new file mode 100644 index 0000000..124e0b7 --- /dev/null +++ b/src/ufo-group.h @@ -0,0 +1,62 @@ +#ifndef __UFO_GROUP_H +#define __UFO_GROUP_H + +#include <glib-object.h> +#include "ufo-task-iface.h" +#include "ufo-buffer.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_GROUP (ufo_group_get_type()) +#define UFO_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_GROUP, UfoGroup)) +#define UFO_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_GROUP)) +#define UFO_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_GROUP, UfoGroupClass)) +#define UFO_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_GROUP)) +#define UFO_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_GROUP, UfoGroupClass)) + +typedef struct _UfoGroup UfoGroup; +typedef struct _UfoGroupClass UfoGroupClass; +typedef struct _UfoGroupPrivate UfoGroupPrivate; + +#define UFO_END_OF_STREAM (GINT_TO_POINTER(1)) + +/** + * UfoGroup: + * + * Main object for organizing filters. The contents of the #UfoGroup structure + * are private and should only be accessed via the provided API. + */ +struct _UfoGroup { + /*< private >*/ + GObject parent_instance; + + UfoGroupPrivate *priv; +}; + +/** + * UfoGroupClass: + * + * #UfoGroup class + */ +struct _UfoGroupClass { + /*< private >*/ + GObjectClass parent_class; +}; + +UfoGroup * ufo_group_new (GList *targets, + gpointer context); +UfoBuffer * ufo_group_pop_output_buffer (UfoGroup *group, + UfoRequisition *requisition); +void ufo_group_push_output_buffer (UfoGroup *group, + UfoBuffer *buffer); +UfoBuffer * ufo_group_pop_input_buffer (UfoGroup *group, + UfoTask *target); +void ufo_group_push_input_buffer (UfoGroup *group, + UfoTask *target, + UfoBuffer *input); +void ufo_group_finish (UfoGroup *group); +GType ufo_group_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-input-task.c b/src/ufo-input-task.c new file mode 100644 index 0000000..516f566 --- /dev/null +++ b/src/ufo-input-task.c @@ -0,0 +1,216 @@ +/** + * SECTION:ufo-input-task + * @Short_description: Write TIFF files + * @Title: Input task + * + * The writer node writes each incoming image as a TIFF using libtiff to disk. + * Each file is prefixed with #UfoInputTask:prefix and written into + * #UfoInputTask:path. + */ + +#ifdef __APPLE__ +#include <OpenCL/cl.h> +#else +#include <CL/cl.h> +#endif +#include <gmodule.h> +#include <tiffio.h> +#include <ufo-input-task.h> +#include <ufo-cpu-task-iface.h> +#include <ufo-gpu-task-iface.h> +#include <ufo-gpu-node.h> + +struct _UfoInputTaskPrivate { + GAsyncQueue **in_queues; + GAsyncQueue **out_queues; + UfoTask *wrapped; + UfoInputParameter *in_params; + gboolean active; + guint n_inputs; + UfoBuffer **inputs; +}; + +static void ufo_task_interface_init (UfoTaskIface *iface); +static void ufo_cpu_task_interface_init (UfoCpuTaskIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UfoInputTask, ufo_input_task, UFO_TYPE_TASK_NODE, + G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK, + ufo_task_interface_init) + G_IMPLEMENT_INTERFACE (UFO_TYPE_CPU_TASK, + ufo_cpu_task_interface_init)) + +#define UFO_INPUT_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_INPUT_TASK, UfoInputTaskPrivate)) + +enum { + PROP_0, + N_PROPERTIES +}; + +UfoNode * +ufo_input_task_new (UfoTask *wrapped) +{ + UfoInputTask *task; + UfoInputTaskPrivate *priv; + + task = UFO_INPUT_TASK (g_object_new (UFO_TYPE_INPUT_TASK, NULL)); + priv = task->priv; + priv->wrapped = wrapped; + + /* TODO: free in_params and queues */ + ufo_task_get_structure (wrapped, &priv->n_inputs, &priv->in_params); + priv->in_queues = g_new0 (GAsyncQueue *, priv->n_inputs); + priv->out_queues = g_new0 (GAsyncQueue *, priv->n_inputs); + priv->inputs = g_new0 (UfoBuffer *, priv->n_inputs); + + for (guint i = 0; i < priv->n_inputs; i++) { + priv->in_queues[i] = g_async_queue_new (); + priv->out_queues[i] = g_async_queue_new (); + } + + return UFO_NODE (task); +} + +void +ufo_input_task_stop (UfoInputTask *task) +{ + g_return_if_fail (UFO_IS_INPUT_TASK (task)); + task->priv->active = FALSE; +} + +void +ufo_input_task_release_input_buffer (UfoInputTask *task, + guint input, + UfoBuffer *buffer) +{ + g_return_if_fail (UFO_IS_INPUT_TASK (task)); + g_async_queue_push (task->priv->in_queues[input], buffer); +} + +UfoBuffer * +ufo_input_task_get_input_buffer (UfoInputTask *task, + gint input) +{ + g_return_val_if_fail (UFO_IS_INPUT_TASK (task), NULL); + return g_async_queue_pop (task->priv->out_queues[input]); +} + +static void +pop_all_inputs (UfoInputTaskPrivate *priv) +{ + for (guint i = 0; i < priv->n_inputs; i++) + priv->inputs[i] = g_async_queue_pop (priv->in_queues[i]); +} + +static void +push_all_inputs (UfoInputTaskPrivate *priv) +{ + for (guint i = 0; i < priv->n_inputs; i++) + g_async_queue_push (priv->out_queues[i], priv->inputs[i]); +} + +static void +ufo_input_task_setup (UfoTask *task, GError **error) +{ +} + +static void +ufo_input_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition) +{ + UfoInputTaskPrivate *priv; + + priv = UFO_INPUT_TASK_GET_PRIVATE (task); + pop_all_inputs (priv); + ufo_task_get_requisition (priv->wrapped, priv->inputs, requisition); +} + +static void +ufo_input_task_get_structure (UfoTask *task, + guint *n_inputs, + UfoInputParameter **in_params) +{ + *n_inputs = 0; +} + +static gboolean +ufo_input_task_process (UfoCpuTask *task, + UfoBuffer **none, + UfoBuffer *output, + UfoRequisition *requisition) +{ + UfoInputTaskPrivate *priv; + gboolean active; + + g_return_val_if_fail (UFO_IS_INPUT_TASK (task), FALSE); + + priv = UFO_INPUT_TASK_GET_PRIVATE (task); + + if (UFO_IS_CPU_TASK (priv->wrapped)) { + active = ufo_cpu_task_process (UFO_CPU_TASK (priv->wrapped), + priv->inputs, output, + requisition); + } + else if (UFO_IS_GPU_TASK (priv->wrapped)) { + UfoGpuNode *gpu; + + gpu = UFO_GPU_NODE (ufo_task_node_get_proc_node (UFO_TASK_NODE (task))); + active = ufo_gpu_task_process (UFO_GPU_TASK (priv->wrapped), + priv->inputs, output, + requisition, gpu); + } + + push_all_inputs (priv); + return active; +} + +static void +ufo_input_task_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_input_task_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_task_interface_init (UfoTaskIface *iface) +{ + iface->setup = ufo_input_task_setup; + iface->get_structure = ufo_input_task_get_structure; + iface->get_requisition = ufo_input_task_get_requisition; +} + +static void +ufo_cpu_task_interface_init (UfoCpuTaskIface *iface) +{ + iface->process = ufo_input_task_process; +} + +static void +ufo_input_task_class_init (UfoInputTaskClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = ufo_input_task_set_property; + gobject_class->get_property = ufo_input_task_get_property; + + g_type_class_add_private (gobject_class, sizeof(UfoInputTaskPrivate)); +} + +static void +ufo_input_task_init(UfoInputTask *self) +{ + self->priv = UFO_INPUT_TASK_GET_PRIVATE(self); +} diff --git a/src/ufo-input-task.h b/src/ufo-input-task.h new file mode 100644 index 0000000..c259c3e --- /dev/null +++ b/src/ufo-input-task.h @@ -0,0 +1,54 @@ +#ifndef __UFO_INPUT_TASK_H +#define __UFO_INPUT_TASK_H + +#include <glib-object.h> +#include "ufo-task-node.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_INPUT_TASK (ufo_input_task_get_type()) +#define UFO_INPUT_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_INPUT_TASK, UfoInputTask)) +#define UFO_IS_INPUT_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_INPUT_TASK)) +#define UFO_INPUT_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_INPUT_TASK, UfoInputTaskClass)) +#define UFO_IS_INPUT_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_INPUT_TASK)) +#define UFO_INPUT_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_INPUT_TASK, UfoInputTaskClass)) + +typedef struct _UfoInputTask UfoInputTask; +typedef struct _UfoInputTaskClass UfoInputTaskClass; +typedef struct _UfoInputTaskPrivate UfoInputTaskPrivate; + +/** + * UfoInputTask: + * + * Main object for organizing filters. The contents of the #UfoInputTask structure + * are private and should only be accessed via the provided API. + */ +struct _UfoInputTask { + /*< private >*/ + UfoTaskNode parent_instance; + + UfoInputTaskPrivate *priv; +}; + +/** + * UfoInputTaskClass: + * + * #UfoInputTask class + */ +struct _UfoInputTaskClass { + /*< private >*/ + UfoTaskNodeClass parent_class; +}; + +UfoNode * ufo_input_task_new (UfoTask *wrapped); +void ufo_input_task_stop (UfoInputTask *task); +void ufo_input_task_release_input_buffer (UfoInputTask *task, + guint input, + UfoBuffer *buffer); +UfoBuffer * ufo_input_task_get_input_buffer (UfoInputTask *task, + gint input); +GType ufo_input_task_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-node.c b/src/ufo-node.c new file mode 100644 index 0000000..f586c89 --- /dev/null +++ b/src/ufo-node.c @@ -0,0 +1,88 @@ +#include "ufo-node.h" + +G_DEFINE_TYPE (UfoNode, ufo_node, G_TYPE_OBJECT) + +#define UFO_NODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_NODE, UfoNodePrivate)) + +struct _UfoNodePrivate { + UfoNode *copied_from; + gpointer label; +}; + +enum { + PROP_0, + N_PROPERTIES +}; + +UfoNode * +ufo_node_new (gpointer label) +{ + UfoNode *node; + + node = UFO_NODE (g_object_new (UFO_TYPE_NODE, NULL)); + node->priv->label = label; + return node; +} + +gpointer +ufo_node_get_label (UfoNode *node) +{ + g_return_val_if_fail (UFO_IS_NODE (node), NULL); + return node->priv->label; +} + +static UfoNode * +ufo_node_copy_real (UfoNode *node, + GError **error) +{ + return ufo_node_new (node->priv->label); +} + +static gboolean +ufo_node_equal_real (UfoNode *n1, + UfoNode *n2) +{ + g_return_val_if_fail (UFO_IS_NODE (n1) && UFO_IS_NODE (n2), FALSE); + + /* FIXME: When done we should just check if the types match */ + return n1 == n2 || + n1->priv->copied_from == n2 || + n2->priv->copied_from == n1; +} + +UfoNode * +ufo_node_copy (UfoNode *node, + GError **error) +{ + UfoNode *offspring; + + offspring = UFO_NODE_GET_CLASS (node)->copy (node, error); + offspring->priv->copied_from = node; + return offspring; +} + +gboolean +ufo_node_equal (UfoNode *n1, + UfoNode *n2) +{ + return UFO_NODE_GET_CLASS (n1)->equal (n1, n2); +} + +static void +ufo_node_class_init (UfoNodeClass *klass) +{ + klass->copy = ufo_node_copy_real; + klass->equal = ufo_node_equal_real; + + g_type_class_add_private(klass, sizeof(UfoNodePrivate)); +} + +static void +ufo_node_init (UfoNode *self) +{ + UfoNodePrivate *priv; + self->priv = priv = UFO_NODE_GET_PRIVATE (self); + + priv->copied_from = NULL; + priv->label = NULL; +} diff --git a/src/ufo-node.h b/src/ufo-node.h new file mode 100644 index 0000000..b9ee3b3 --- /dev/null +++ b/src/ufo-node.h @@ -0,0 +1,57 @@ +#ifndef __UFO_NODE_H +#define __UFO_NODE_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define UFO_TYPE_NODE (ufo_node_get_type()) +#define UFO_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_NODE, UfoNode)) +#define UFO_IS_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_NODE)) +#define UFO_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_NODE, UfoNodeClass)) +#define UFO_IS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_NODE)) +#define UFO_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_NODE, UfoNodeClass)) + +typedef struct _UfoNode UfoNode; +typedef struct _UfoNodeClass UfoNodeClass; +typedef struct _UfoNodePrivate UfoNodePrivate; + +/** + * UfoNode: + * + * Main object for organizing filters. The contents of the #UfoNode structure + * are private and should only be accessed via the provided API. + */ +struct _UfoNode { + /*< private >*/ + GObject parent_instance; + + UfoNodePrivate *priv; +}; + +/** + * UfoNodeClass: + * + * #UfoNode class + */ +struct _UfoNodeClass { + /*< private >*/ + GObjectClass parent_class; + + UfoNode * (*copy) (UfoNode *node, + GError **error); + gboolean (*equal) (UfoNode *n1, + UfoNode *n2); +}; + +UfoNode *ufo_node_new (gpointer label); +gpointer ufo_node_get_label (UfoNode *node); +UfoNode *ufo_node_copy (UfoNode *node, + GError **error); +gboolean ufo_node_equal (UfoNode *n1, + UfoNode *n2); +GType ufo_node_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-output-task.c b/src/ufo-output-task.c new file mode 100644 index 0000000..4cc8c77 --- /dev/null +++ b/src/ufo-output-task.c @@ -0,0 +1,184 @@ +/** + * SECTION:ufo-output-task + * @Short_description: Output task + * @Title: Output task + */ + +#include <gmodule.h> +#include <tiffio.h> +#ifdef __APPLE__ +#include <OpenCL/cl.h> +#else +#include <CL/cl.h> +#endif + +#include <ufo-output-task.h> +#include <ufo-cpu-task-iface.h> + +struct _UfoOutputTaskPrivate { + GAsyncQueue *out_queue; + GAsyncQueue *in_queue; + guint n_dims; + guint n_copies; +}; + +static void ufo_task_interface_init (UfoTaskIface *iface); +static void ufo_cpu_task_interface_init (UfoCpuTaskIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UfoOutputTask, ufo_output_task, UFO_TYPE_TASK_NODE, + G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK, + ufo_task_interface_init) + G_IMPLEMENT_INTERFACE (UFO_TYPE_CPU_TASK, + ufo_cpu_task_interface_init)) + +#define UFO_OUTPUT_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_OUTPUT_TASK, UfoOutputTaskPrivate)) + +enum { + PROP_0, + N_PROPERTIES +}; + +UfoNode * +ufo_output_task_new (guint n_dims) +{ + UfoOutputTask *task = UFO_OUTPUT_TASK (g_object_new (UFO_TYPE_OUTPUT_TASK, NULL)); + + task->priv->n_dims = n_dims; + return UFO_NODE (task); +} + +void +ufo_output_task_get_output_requisition (UfoOutputTask *task, + UfoRequisition *requisition) +{ + UfoBuffer *buffer; + UfoOutputTaskPrivate *priv; + + g_return_if_fail (UFO_IS_OUTPUT_TASK (task)); + priv = task->priv; + buffer = g_async_queue_pop (priv->out_queue); + ufo_buffer_get_requisition (buffer, requisition); + g_async_queue_push (priv->out_queue, buffer); +} + +UfoBuffer * +ufo_output_task_get_output_buffer (UfoOutputTask *task) +{ + g_return_val_if_fail (UFO_IS_OUTPUT_TASK (task), NULL); + return g_async_queue_pop (task->priv->out_queue); +} + +void +ufo_output_task_release_output_buffer (UfoOutputTask *task, + UfoBuffer *buffer) +{ + g_return_if_fail (UFO_IS_OUTPUT_TASK (task)); + g_async_queue_push (task->priv->in_queue, buffer); +} + +static void +ufo_output_task_setup (UfoTask *task, GError **error) +{ +} + +static void +ufo_output_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition) +{ + (*requisition).n_dims = 0; +} + +static void +ufo_output_task_get_structure (UfoTask *task, + guint *n_inputs, + UfoInputParameter **in_params) +{ + UfoOutputTaskPrivate *priv = UFO_OUTPUT_TASK_GET_PRIVATE (task); + + *n_inputs = 1; + *in_params = g_new0 (UfoInputParameter, 1); + (*in_params)[0].n_dims = priv->n_dims; + (*in_params)[0].n_expected_items = -1; +} + +static gboolean +ufo_output_task_process (UfoCpuTask *task, + UfoBuffer **outputs, + UfoBuffer *output, + UfoRequisition *requisition) +{ + UfoOutputTaskPrivate *priv; + UfoRequisition req; + UfoBuffer *copy; + + g_return_val_if_fail (UFO_IS_OUTPUT_TASK (task), FALSE); + ufo_buffer_get_requisition (outputs[0], &req); + + priv = UFO_OUTPUT_TASK_GET_PRIVATE (task); + + if (priv->n_copies == 0) { + copy = ufo_buffer_dup (outputs[0]); + g_async_queue_push (priv->in_queue, copy); + priv->n_copies++; + } + + copy = g_async_queue_pop (priv->in_queue); + ufo_buffer_copy (outputs[0], copy); + g_async_queue_push (priv->out_queue, copy); + return TRUE; +} + +static void +ufo_output_task_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_output_task_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_task_interface_init (UfoTaskIface *iface) +{ + iface->setup = ufo_output_task_setup; + iface->get_structure = ufo_output_task_get_structure; + iface->get_requisition = ufo_output_task_get_requisition; +} + +static void +ufo_cpu_task_interface_init (UfoCpuTaskIface *iface) +{ + iface->process = ufo_output_task_process; +} + +static void +ufo_output_task_class_init (UfoOutputTaskClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = ufo_output_task_set_property; + gobject_class->get_property = ufo_output_task_get_property; + + g_type_class_add_private (gobject_class, sizeof(UfoOutputTaskPrivate)); +} + +static void +ufo_output_task_init(UfoOutputTask *self) +{ + self->priv = UFO_OUTPUT_TASK_GET_PRIVATE(self); + self->priv->out_queue = g_async_queue_new (); + self->priv->in_queue = g_async_queue_new (); + self->priv->n_copies = 0; +} diff --git a/src/ufo-output-task.h b/src/ufo-output-task.h new file mode 100644 index 0000000..68a8e66 --- /dev/null +++ b/src/ufo-output-task.h @@ -0,0 +1,53 @@ +#ifndef __UFO_OUTPUT_TASK_H +#define __UFO_OUTPUT_TASK_H + +#include <glib-object.h> +#include "ufo-task-node.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_OUTPUT_TASK (ufo_output_task_get_type()) +#define UFO_OUTPUT_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_OUTPUT_TASK, UfoOutputTask)) +#define UFO_IS_OUTPUT_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_OUTPUT_TASK)) +#define UFO_OUTPUT_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_OUTPUT_TASK, UfoOutputTaskClass)) +#define UFO_IS_OUTPUT_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_OUTPUT_TASK)) +#define UFO_OUTPUT_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_OUTPUT_TASK, UfoOutputTaskClass)) + +typedef struct _UfoOutputTask UfoOutputTask; +typedef struct _UfoOutputTaskClass UfoOutputTaskClass; +typedef struct _UfoOutputTaskPrivate UfoOutputTaskPrivate; + +/** + * UfoOutputTask: + * + * Main object for organizing filters. The contents of the #UfoOutputTask structure + * are private and should only be accessed via the provided API. + */ +struct _UfoOutputTask { + /*< private >*/ + UfoTaskNode parent_instance; + + UfoOutputTaskPrivate *priv; +}; + +/** + * UfoOutputTaskClass: + * + * #UfoOutputTask class + */ +struct _UfoOutputTaskClass { + /*< private >*/ + UfoTaskNodeClass parent_class; +}; + +UfoNode * ufo_output_task_new (guint n_dims); +void ufo_output_task_get_output_requisition (UfoOutputTask *task, + UfoRequisition *requisition); +UfoBuffer * ufo_output_task_get_output_buffer (UfoOutputTask *task); +void ufo_output_task_release_output_buffer (UfoOutputTask *task, + UfoBuffer *buffer); +GType ufo_output_task_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-plugin-manager.c b/src/ufo-plugin-manager.c index 931710e..201e68d 100644 --- a/src/ufo-plugin-manager.c +++ b/src/ufo-plugin-manager.c @@ -11,21 +11,21 @@ */ #include <gmodule.h> #include <glob.h> +#include <ufo-plugin-manager.h> +#include <ufo-configurable.h> #include "config.h" -#include "ufo-plugin-manager.h" -#include "ufo-configurable.h" G_DEFINE_TYPE_WITH_CODE (UfoPluginManager, ufo_plugin_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (UFO_TYPE_CONFIGURABLE, NULL)) #define UFO_PLUGIN_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_PLUGIN_MANAGER, UfoPluginManagerPrivate)) -typedef UfoFilter* (* GetFilterFunc) (void); +typedef UfoNode* (* NewFunc) (void); struct _UfoPluginManagerPrivate { GSList *search_paths; GSList *modules; - GHashTable *filter_funcs; /**< maps from gchar* to GetFilterFunc* */ + GHashTable *new_funcs; /**< maps from gchar* to NewFunc* */ }; enum { @@ -64,7 +64,7 @@ plugin_manager_get_path (UfoPluginManagerPrivate *priv, const gchar *name) GSList *p = g_slist_nth (priv->search_paths, 0); while (p != NULL) { - gchar *path = g_strdup_printf ("%s%c%s", (gchar *) p->data, G_DIR_SEPARATOR, name); + gchar *path = g_build_filename ((gchar *) p->data, name, NULL); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; @@ -77,11 +77,11 @@ plugin_manager_get_path (UfoPluginManagerPrivate *priv, const gchar *name) } static void -copy_config_paths (UfoPluginManagerPrivate *priv, UfoConfiguration *config) +copy_config_paths (UfoPluginManagerPrivate *priv, UfoConfig *config) { gchar **paths; - paths = ufo_configuration_get_paths (config); + paths = ufo_config_get_paths (config); for (guint i = 0; paths[i] != NULL; i++) priv->search_paths = g_slist_prepend (priv->search_paths, g_strdup (paths[i])); @@ -91,7 +91,7 @@ copy_config_paths (UfoPluginManagerPrivate *priv, UfoConfiguration *config) /** * ufo_plugin_manager_new: - * @config: (allow-none): A #UfoConfiguration object or %NULL. + * @config: (allow-none): A #UfoConfig object or %NULL. * * Create a plugin manager object to instantiate filter objects. When a config * object is passed to the constructor, its search-path property is added to the @@ -100,7 +100,7 @@ copy_config_paths (UfoPluginManagerPrivate *priv, UfoConfiguration *config) * Return value: A new plugin manager object. */ UfoPluginManager * -ufo_plugin_manager_new (UfoConfiguration *config) +ufo_plugin_manager_new (UfoConfig *config) { UfoPluginManager *manager; @@ -124,27 +124,28 @@ ufo_plugin_manager_new (UfoConfiguration *config) * * Since: 0.2, the error parameter is available */ -UfoFilter * -ufo_plugin_manager_get_filter (UfoPluginManager *manager, const gchar *name, GError **error) +UfoNode * +ufo_plugin_manager_get_task (UfoPluginManager *manager, const gchar *name, GError **error) { g_return_val_if_fail (UFO_IS_PLUGIN_MANAGER (manager) && (name != NULL), NULL); UfoPluginManagerPrivate *priv = UFO_PLUGIN_MANAGER_GET_PRIVATE (manager); - UfoFilter *filter; - GetFilterFunc *func = NULL; - GModule *module = NULL; + UfoNode *node; + NewFunc *func; + GModule *module; gchar *module_name = NULL; + const gchar *entry_symbol_name = "ufo_filter_plugin_new"; - func = g_hash_table_lookup (priv->filter_funcs, name); + func = g_hash_table_lookup (priv->new_funcs, name); if (func == NULL) { /* No suitable function found, let's find the module */ - module_name = g_strdup_printf ("libufofilter%s.so", name); + module_name = g_strdup_printf ("libufotask%s.so", name); gchar *path = plugin_manager_get_path (priv, module_name); if (path == NULL) { g_set_error (error, UFO_PLUGIN_MANAGER_ERROR, UFO_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND, - "Module %s not found", module_name); + "Module %s not found", module_name); goto handle_error; } @@ -153,15 +154,15 @@ ufo_plugin_manager_get_filter (UfoPluginManager *manager, const gchar *name, GEr if (!module) { g_set_error (error, UFO_PLUGIN_MANAGER_ERROR, UFO_PLUGIN_MANAGER_ERROR_MODULE_OPEN, - "Module %s could not be opened: %s", module_name, g_module_error ()); + "Module %s could not be opened: %s", module_name, g_module_error ()); goto handle_error; } - func = g_malloc0 (sizeof (GetFilterFunc)); + func = g_malloc0 (sizeof (NewFunc)); if (!g_module_symbol (module, entry_symbol_name, (gpointer *) func)) { g_set_error (error, UFO_PLUGIN_MANAGER_ERROR, UFO_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND, - "%s is not exported by module %s: %s", entry_symbol_name, module_name, g_module_error ()); + "%s is not exported by module %s: %s", entry_symbol_name, module_name, g_module_error ()); g_free (func); if (!g_module_close (module)) @@ -171,15 +172,15 @@ ufo_plugin_manager_get_filter (UfoPluginManager *manager, const gchar *name, GEr } priv->modules = g_slist_append (priv->modules, module); - g_hash_table_insert (priv->filter_funcs, g_strdup (name), func); + g_hash_table_insert (priv->new_funcs, g_strdup (name), func); g_free (module_name); } - filter = (*func) (); - ufo_filter_set_plugin_name (filter, name); - g_message ("UfoPluginManager: Created %s-%p", name, (gpointer) filter); + node = (*func) (); + /* ufo_filter_set_plugin_name (filter, name); */ + g_message ("UfoPluginManager: Created %s-%p", name, (gpointer) node); - return filter; + return node; handle_error: g_free (module_name); @@ -187,7 +188,7 @@ handle_error: } /** - * ufo_plugin_manager_get_all_filter_names: + * ufo_plugin_manager_get_all_task_names: * @manager: A #UfoPluginManager * * Return a list with potential filter names that match shared objects in all @@ -196,21 +197,23 @@ handle_error: * Return value: (element-type utf8) (transfer full): List of strings with filter names */ GList * -ufo_plugin_manager_get_all_filter_names (UfoPluginManager *manager) +ufo_plugin_manager_get_all_task_names (UfoPluginManager *manager) { g_return_val_if_fail (UFO_IS_PLUGIN_MANAGER (manager), NULL); UfoPluginManagerPrivate *priv = UFO_PLUGIN_MANAGER_GET_PRIVATE (manager); GList *result = NULL; GSList *path; - GRegex *regex = g_regex_new ("libufofilter([A-Za-z]+).so", 0, 0, NULL); + GRegex *regex = g_regex_new ("libufotask([A-Za-z]+).so", 0, 0, NULL); GMatchInfo *match_info = NULL; path = g_slist_nth (priv->search_paths, 0); while (path != NULL) { glob_t glob_vector; - gchar *pattern = g_strdup_printf ("%s%clibufofilter*.so", (gchar *) path->data, G_DIR_SEPARATOR); + gchar *pattern; + + pattern = g_build_filename ((gchar *) path->data, "libufotask*.so", NULL); glob (pattern, GLOB_MARK | GLOB_TILDE, NULL, &glob_vector); g_free (pattern); gsize i = 0; @@ -255,9 +258,9 @@ ufo_plugin_manager_set_property (GObject *object, guint property_id, const GValu value_object = g_value_get_object (value); if (value_object != NULL) { - UfoConfiguration *config; + UfoConfig *config; - config = UFO_CONFIGURATION (value_object); + config = UFO_CONFIG (value_object); copy_config_paths (UFO_PLUGIN_MANAGER_GET_PRIVATE (object), config); } } @@ -275,7 +278,7 @@ ufo_plugin_manager_constructed (GObject *object) UfoPluginManagerPrivate *priv = UFO_PLUGIN_MANAGER_GET_PRIVATE (object); if (priv->search_paths == NULL) { - UfoConfiguration *config = ufo_configuration_new (); + UfoConfig *config = ufo_config_new (); copy_config_paths (priv, config); g_object_unref (config); } @@ -305,7 +308,7 @@ ufo_plugin_manager_finalize (GObject *gobject) g_slist_foreach (priv->search_paths, (GFunc) g_free, NULL); g_slist_free (priv->search_paths); - g_hash_table_destroy (priv->filter_funcs); + g_hash_table_destroy (priv->new_funcs); G_OBJECT_CLASS (ufo_plugin_manager_parent_class)->finalize (gobject); g_message ("UfoPluginManager: finalized"); } @@ -320,7 +323,7 @@ ufo_plugin_manager_class_init (UfoPluginManagerClass *klass) gobject_class->dispose = ufo_plugin_manager_dispose; gobject_class->finalize = ufo_plugin_manager_finalize; - g_object_class_override_property (gobject_class, PROP_CONFIG, "configuration"); + g_object_class_override_property (gobject_class, PROP_CONFIG, "config"); g_type_class_add_private (klass, sizeof (UfoPluginManagerPrivate)); } @@ -331,8 +334,8 @@ ufo_plugin_manager_init (UfoPluginManager *manager) UfoPluginManagerPrivate *priv; manager->priv = priv = UFO_PLUGIN_MANAGER_GET_PRIVATE (manager); - priv->modules = NULL; - priv->search_paths = NULL; - priv->filter_funcs = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_free); + priv->modules = NULL; + priv->search_paths = NULL; + priv->new_funcs = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); } diff --git a/src/ufo-plugin-manager.h b/src/ufo-plugin-manager.h index 6bd47fb..48c0ccb 100644 --- a/src/ufo-plugin-manager.h +++ b/src/ufo-plugin-manager.h @@ -2,8 +2,8 @@ #define __UFO_PLUGIN_MANAGER_H #include <glib-object.h> -#include "ufo-configuration.h" -#include "ufo-filter.h" +#include <ufo-config.h> +#include <ufo-node.h> G_BEGIN_DECLS @@ -51,11 +51,11 @@ struct _UfoPluginManagerClass { GObjectClass parent_class; }; -UfoPluginManager *ufo_plugin_manager_new (UfoConfiguration *config); -UfoFilter *ufo_plugin_manager_get_filter (UfoPluginManager *manager, - const gchar *name, +UfoPluginManager * ufo_plugin_manager_new (UfoConfig *config); +UfoNode * ufo_plugin_manager_get_task (UfoPluginManager *manager, + const gchar *name, GError **error); -GList *ufo_plugin_manager_get_all_filter_names (UfoPluginManager *manager); +GList * ufo_plugin_manager_get_all_task_names (UfoPluginManager *manager); GType ufo_plugin_manager_get_type (void); G_END_DECLS diff --git a/src/ufo-profiler.c b/src/ufo-profiler.c index d5e353b..41bef23 100644 --- a/src/ufo-profiler.c +++ b/src/ufo-profiler.c @@ -24,9 +24,9 @@ #endif #include <gmodule.h> #include <glob.h> -#include "config.h" -#include "ufo-profiler.h" -#include "ufo-aux.h" + +#include <ufo-profiler.h> +#include <ufo-resources.h> G_DEFINE_TYPE(UfoProfiler, ufo_profiler, G_TYPE_OBJECT) @@ -147,7 +147,7 @@ ufo_profiler_call (UfoProfiler *profiler, global_work_size, local_work_size, 0, NULL, event_loc); - CHECK_OPENCL_ERROR (cl_err); + UFO_RESOURCES_CHECK_CLERR (cl_err); if (priv->level & UFO_PROFILER_LEVEL_OPENCL) { row.event = event; diff --git a/src/ufo-profiler.h b/src/ufo-profiler.h index b12eaaf..292fb5e 100644 --- a/src/ufo-profiler.h +++ b/src/ufo-profiler.h @@ -2,7 +2,6 @@ #define __UFO_PROFILER_H #include <glib-object.h> -#include "ufo-resource-manager.h" G_BEGIN_DECLS diff --git a/src/ufo-relation.c b/src/ufo-relation.c deleted file mode 100644 index 01a64e7..0000000 --- a/src/ufo-relation.c +++ /dev/null @@ -1,454 +0,0 @@ -/** - * SECTION:ufo-relation - * @Short_description: Data transport between two UfoFilters - * @Title: UfoRelation - */ - -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-relation.h" -#include "ufo-enums.h" - -G_DEFINE_TYPE(UfoRelation, ufo_relation, G_TYPE_OBJECT) - -#define UFO_RELATION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_RELATION, UfoRelationPrivate)) - -struct _UfoRelationPrivate { - UfoRelationMode mode; - - UfoFilter *producer; - guint output_port; - GAsyncQueue *producer_pop_queue; - GAsyncQueue *producer_push_queue; - GList *consumers; /* contains UfoFilter * */ - GHashTable *consumer_ports; /* maps from UfoFilter* to input port */ - GHashTable *consumer_pop_queues; /* maps from UfoFilter* to GAsyncQueue */ - GHashTable *consumer_push_queues; /* maps from UfoFilter* to GAsyncQueue */ -}; - -enum { - PROP_0, - PROP_PRODUCER, - PROP_OUTPUT_PORT, - PROP_MODE, - N_PROPERTIES -}; - -static GParamSpec *relation_properties[N_PROPERTIES] = { NULL, }; - -/** - * ufo_relation_new: - * @producer: A #UfoFilter - * @output_port: The outgoing port number of the producer - * @mode: The relation mode that determines how data is forwarded - * - * Creates a new #UfoRelation that represents a 1:m relationship between a - * @producer and an arbitrary number of consumers.. - * - * Return value: A new #UfoRelation - * Since: 0.2 - */ -UfoRelation * -ufo_relation_new (UfoFilter *producer, guint output_port, UfoRelationMode mode) -{ - UfoRelation *relation; - - relation = UFO_RELATION (g_object_new (UFO_TYPE_RELATION, - "producer", producer, - "output-port", output_port, - "mode", mode, - NULL)); - - g_object_ref (producer); - return relation; -} - -/** - * ufo_relation_get_producer: (skip) - * @relation: A #UfoRelation object - * - * Get the producer associated with the relation. - * - * Returns: A #UfoFilter - * Since: 0.2 - */ -UfoFilter * -ufo_relation_get_producer (UfoRelation *relation) -{ - g_return_val_if_fail (UFO_IS_RELATION (relation), NULL); - return relation->priv->producer; -} - -/** - * ufo_relation_add_consumer: - * @relation: A #UfoRelation object - * @consumer: The consumer that takes input from the #relation - * @input_port: The input port number of the consumer - * @error: Location for #GError - * - * Add a consumer to this relation. - * - * Since: 0.2 - */ -void -ufo_relation_add_consumer (UfoRelation *relation, UfoFilter *consumer, guint input_port, GError **error) -{ - UfoRelationPrivate *priv; - UfoInputParameter *input_params; - UfoOutputParameter *output_params; - guint num_input_ports; - guint input_num_dims; - guint output_num_dims; - - g_return_if_fail (UFO_IS_RELATION (relation)); - - priv = UFO_RELATION_GET_PRIVATE (relation); - - num_input_ports = ufo_filter_get_num_inputs (consumer); - input_params = ufo_filter_get_input_parameters (consumer); - output_params = ufo_filter_get_output_parameters (priv->producer); - - if (input_port >= num_input_ports) { - g_set_error (error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_INSUFFICIENTINPUTS, - "%s has only %i input ports, but port %i was specified\n", - ufo_filter_get_plugin_name (consumer), num_input_ports, input_port); - return; - } - - input_num_dims = input_params[input_port].n_dims; - output_num_dims = output_params[priv->output_port].n_dims; - - if (input_num_dims != output_num_dims) { - g_set_error (error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_NUMDIMSMISMATCH, - "%i dimensions at output port %i != %i dimensions at input port %i\n", - output_num_dims, priv->output_port, input_num_dims, input_port); - return; - } - - g_hash_table_insert (priv->consumer_ports, consumer, GINT_TO_POINTER (input_port)); - - if (priv->producer_pop_queue == NULL) - priv->producer_pop_queue = g_async_queue_new (); - - if (priv->producer_push_queue == NULL) - priv->producer_push_queue = g_async_queue_new (); - - if (priv->mode == UFO_RELATION_MODE_DISTRIBUTE) { - /* - * In distribute mode, each consumer consumes from the same input queue and - * has to push it back to the same used output queue. - */ - g_hash_table_insert (priv->consumer_push_queues, consumer, priv->producer_pop_queue); - g_hash_table_insert (priv->consumer_pop_queues, consumer, priv->producer_push_queue); - } - else { - /* - * In copy mode, we daisy chain pop-push-queues and transfer the - * produced buffer from one consumer to the next until it is placed back - * again in the producers pop queue. - */ - GList *last_element = g_list_last (priv->consumers); - - if (last_element == NULL) { - g_hash_table_insert (priv->consumer_push_queues, consumer, priv->producer_pop_queue); - g_hash_table_insert (priv->consumer_pop_queues, consumer, priv->producer_push_queue); - } - else { - UfoFilter *last_consumer = UFO_FILTER (last_element->data); - GAsyncQueue *queue = g_async_queue_new (); - g_hash_table_insert (priv->consumer_push_queues, last_consumer, queue); - g_hash_table_insert (priv->consumer_pop_queues, consumer, queue); - g_hash_table_insert (priv->consumer_push_queues, consumer, priv->producer_pop_queue); - } - } - - g_object_ref (consumer); - priv->consumers = g_list_append (priv->consumers, consumer); -} - -/** - * ufo_relation_get_consumers: (skip) - * @relation: A #UfoRelation object - * - * Get the consumers associated with this relation - * - * Returns: (transfer none) (element-type UfoFilter): A list with #UfoFilter consumers - * Since: 0.2 - */ -GList * -ufo_relation_get_consumers (UfoRelation *relation) -{ - g_return_val_if_fail (UFO_IS_RELATION (relation), NULL); - return relation->priv->consumers; -} - -/** - * ufo_relation_get_producer_port: - * @relation: A #UfoRelation object - * - * Get the producer's output port number - * - * Returns: The producer's output port number - * Since: 0.2 - */ -guint -ufo_relation_get_producer_port (UfoRelation *relation) -{ - g_return_val_if_fail (UFO_IS_RELATION (relation), 0); - return relation->priv->output_port; -} - -/** - * ufo_relation_get_consumer_port: - * @relation: A #UfoRelation object - * @consumer: A consumer that is - * - * Get the #consumer's input port number - * - * Returns: The consumer's output port number - * Since: 0.2 - */ -guint -ufo_relation_get_consumer_port (UfoRelation *relation, UfoFilter *consumer) -{ - if (!ufo_relation_has_consumer (relation, consumer)) - g_warning ("Consumer is not part of this relation. Expect wrong port 0."); - - return (guint) GPOINTER_TO_INT (g_hash_table_lookup (relation->priv->consumer_ports, consumer)); -} - -/** - * ufo_relation_get_producer_queues: - * @relation: A #UfoRelation object - * @push_queue: A location for the queue into which to push fresh output data - * @pop_queue: A location for the queue from which to pop used output buffers - * - * Get queues for the producer. - * - * Since: 0.2 - */ -void -ufo_relation_get_producer_queues (UfoRelation *relation, GAsyncQueue **push_queue, GAsyncQueue **pop_queue) -{ - g_return_if_fail (UFO_IS_RELATION (relation)); - g_return_if_fail (push_queue != NULL && pop_queue != NULL); - - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (relation); - *push_queue = priv->producer_push_queue; - *pop_queue = priv->producer_pop_queue; -} - -/** - * ufo_relation_get_consumer_queues: - * @relation: A #UfoRelation object - * @consumer: The #UfoFilter for which to get the queues - * @push_queue: A location for the queue into which to push used input data - * @pop_queue: A location for the queue from which to pop fresh input buffers - * - * Get queues for #consumer. - * - * Since: 0.2 - */ -void -ufo_relation_get_consumer_queues (UfoRelation *relation, UfoFilter *consumer, GAsyncQueue **push_queue, GAsyncQueue **pop_queue) -{ - g_return_if_fail (UFO_IS_RELATION (relation) && UFO_IS_FILTER (consumer)); - g_return_if_fail (push_queue != NULL && pop_queue != NULL); - - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (relation); - *push_queue = g_hash_table_lookup (priv->consumer_push_queues, consumer); - *pop_queue = g_hash_table_lookup (priv->consumer_pop_queues, consumer); -} - -/** - * ufo_relation_has_consumer: - * @relation: A #UfoRelation object - * @consumer: A #UfoFilter consumer - * - * Check if #consumer is part of #relation. - * - * Returns: %TRUE if #consumer is part of #relation, otherwise %FALSE. - * Since: 0.2 - */ -gboolean -ufo_relation_has_consumer (UfoRelation *relation, UfoFilter *consumer) -{ - g_return_val_if_fail (UFO_IS_RELATION (relation), FALSE); - return g_hash_table_lookup_extended (relation->priv->consumer_ports, consumer, NULL, NULL); -} - -/** - * ufo_relation_push_poison_pill: - * @relation: A #UfoRelation object - * - * Tell all consumers that the producer does not provide any more data. - * - * Since: 0.2 - */ -void -ufo_relation_push_poison_pill (UfoRelation *relation) -{ - g_return_if_fail (UFO_IS_RELATION (relation)); - - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (relation); - - /* - * The mode doesn't matter here. If it is distributed, pop_queue will be the - * same for each consumer thus pushing the pill n times. If copy mode is - * enable, the pill will be inserted into each consumer's pop queue. - */ - for (GList *it = g_list_first (priv->consumers); it != NULL; it = g_list_next (it)) { - UfoFilter *consumer = UFO_FILTER (it->data); - GAsyncQueue *pop_queue = g_hash_table_lookup (priv->consumer_pop_queues, consumer); - g_async_queue_push (pop_queue, GINT_TO_POINTER (1)); - } -} - -static void -ufo_relation_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (object); - - switch (property_id) { - case PROP_PRODUCER: - priv->producer = g_value_get_object (value); - break; - case PROP_OUTPUT_PORT: - priv->output_port = g_value_get_uint (value); - break; - case PROP_MODE: - priv->mode = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -ufo_relation_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (object); - - switch (property_id) { - case PROP_PRODUCER: - g_value_set_object (value, priv->producer); - break; - case PROP_OUTPUT_PORT: - g_value_set_uint (value, priv->output_port); - break; - case PROP_MODE: - g_value_set_enum (value, priv->mode); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -g_async_queue_safe_unref (GAsyncQueue *queue) -{ - if (queue) - g_async_queue_unref (queue); -} - -static void -ufo_relation_dispose (GObject *object) -{ - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (object); - - g_list_foreach (priv->consumers, (GFunc) g_object_unref, NULL); - - /* - * FIXME: if we enable the following unref, the unref will segfault with a - * certain number of filters. Why, this is, I don't know :( - */ - /* g_object_unref (priv->producer); */ - - G_OBJECT_CLASS (ufo_relation_parent_class)->dispose (object); -} - -static void -ufo_relation_finalize (GObject *object) -{ - UfoRelationPrivate *priv = UFO_RELATION_GET_PRIVATE (object); - - if (priv->mode == UFO_RELATION_MODE_DISTRIBUTE) { - g_async_queue_safe_unref (priv->producer_pop_queue); - g_async_queue_safe_unref (priv->producer_push_queue); - } - else { - for (GList *it = g_list_first (priv->consumers); it != NULL; it = g_list_next (it)) { - UfoFilter *consumer = UFO_FILTER (it->data); - GAsyncQueue *pop_queue = g_hash_table_lookup (priv->consumer_pop_queues, consumer); - g_async_queue_safe_unref (pop_queue); - } - - g_async_queue_safe_unref (priv->producer_pop_queue); - } - - g_list_free (priv->consumers); - g_hash_table_destroy (priv->consumer_push_queues); - g_hash_table_destroy (priv->consumer_pop_queues); - g_hash_table_destroy (priv->consumer_ports); - - G_OBJECT_CLASS (ufo_relation_parent_class)->finalize (object); -} - -static void -ufo_relation_class_init (UfoRelationClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->get_property = ufo_relation_get_property; - gobject_class->set_property = ufo_relation_set_property; - gobject_class->dispose = ufo_relation_dispose; - gobject_class->finalize = ufo_relation_finalize; - - relation_properties[PROP_PRODUCER] = - g_param_spec_object ("producer", - "An UfoFilter", - "An UfoFilter", - UFO_TYPE_FILTER, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - relation_properties[PROP_OUTPUT_PORT] = - g_param_spec_uint ("output-port", - "Number of the producer output port", - "Number of the producer output port", - 0, 256, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - relation_properties[PROP_MODE] = - g_param_spec_enum ("mode", - "Work item mode", - "Work item mode", - UFO_TYPE_RELATION_MODE, UFO_RELATION_MODE_DISTRIBUTE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++) - g_object_class_install_property (gobject_class, i, relation_properties[i]); - - g_type_class_add_private (klass, sizeof (UfoRelationPrivate)); -} - -static void -ufo_relation_init (UfoRelation *relation) -{ - UfoRelationPrivate *priv; - relation->priv = priv = UFO_RELATION_GET_PRIVATE (relation); - priv->producer = NULL; - priv->output_port = 0; - priv->consumers = NULL; - priv->consumer_ports = g_hash_table_new (g_direct_hash, g_direct_equal); - - priv->producer_push_queue= NULL; - priv->producer_pop_queue = NULL; - priv->consumer_pop_queues = g_hash_table_new (g_direct_hash, g_direct_equal); - priv->consumer_push_queues = g_hash_table_new (g_direct_hash, g_direct_equal); -} diff --git a/src/ufo-relation.h b/src/ufo-relation.h deleted file mode 100644 index 54a9f12..0000000 --- a/src/ufo-relation.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __UFO_RELATION_H -#define __UFO_RELATION_H - -#include <glib-object.h> -#include "ufo-filter.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_RELATION (ufo_relation_get_type()) -#define UFO_RELATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_RELATION, UfoRelation)) -#define UFO_IS_RELATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_RELATION)) -#define UFO_RELATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_RELATION, UfoRelationClass)) -#define UFO_IS_RELATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_RELATION)) -#define UFO_RELATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_RELATION, UfoRelationClass)) - -typedef struct _UfoRelation UfoRelation; -typedef struct _UfoRelationClass UfoRelationClass; -typedef struct _UfoRelationPrivate UfoRelationPrivate; - -/** - * UfoRelationMode: - * @UFO_RELATION_MODE_DISTRIBUTE: Data from the producer is distributed in a - * non-predictable way to one consumer. - * @UFO_RELATION_MODE_COPY: The data from the producer is copied and send to all - * producers. - */ -typedef enum { - UFO_RELATION_MODE_DISTRIBUTE, - UFO_RELATION_MODE_COPY -} UfoRelationMode; - -/** - * UfoRelation: - * - * Data transport channel between two #UfoFilter objects. The contents of the - * #UfoRelation structure are private and should only be accessed via the - * provided API. - */ -struct _UfoRelation { - /*< private >*/ - GObject parent_instance; - - UfoRelationPrivate *priv; -}; - -/** - * UfoRelationClass: - * - * #UfoRelation class - */ -struct _UfoRelationClass { - /*< private >*/ - GObjectClass parent_class; -}; - -UfoRelation *ufo_relation_new (UfoFilter *producer, - guint output_port, - UfoRelationMode mode); -UfoFilter *ufo_relation_get_producer (UfoRelation *relation); -GList *ufo_relation_get_consumers (UfoRelation *relation); -void ufo_relation_add_consumer (UfoRelation *relation, - UfoFilter *consumer, - guint input_port, - GError **error); -gboolean ufo_relation_has_consumer (UfoRelation *relation, - UfoFilter *consumer); -guint ufo_relation_get_producer_port (UfoRelation *relation); -guint ufo_relation_get_consumer_port (UfoRelation *relation, - UfoFilter *consumer); -void ufo_relation_get_producer_queues (UfoRelation *relation, - GAsyncQueue **push_queue, - GAsyncQueue **pop_queue); -void ufo_relation_get_consumer_queues (UfoRelation *relation, - UfoFilter *consumer, - GAsyncQueue **push_queue, - GAsyncQueue **pop_queue); -void ufo_relation_push_poison_pill (UfoRelation *relation); -GType ufo_relation_get_type (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-remote-node.c b/src/ufo-remote-node.c new file mode 100644 index 0000000..fd72ad7 --- /dev/null +++ b/src/ufo-remote-node.c @@ -0,0 +1,231 @@ +#include <zmq.h> +#include <string.h> +#include "ufo-remote-node.h" + +G_DEFINE_TYPE (UfoRemoteNode, ufo_remote_node, UFO_TYPE_NODE) + +#define UFO_REMOTE_NODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_REMOTE_NODE, UfoRemoteNodePrivate)) + +static void ufo_msg_send (UfoMessage *msg, gpointer socket, gint flags); + +struct _UfoRemoteNodePrivate { + gpointer context; + gpointer socket; + guint n_inputs; +}; + +UfoNode * +ufo_remote_node_new (gpointer zmq_context, + const gchar *address) +{ + UfoRemoteNode *node; + UfoRemoteNodePrivate *priv; + + g_return_val_if_fail (zmq_context != NULL && address != NULL, NULL); + node = UFO_REMOTE_NODE (g_object_new (UFO_TYPE_REMOTE_NODE, NULL)); + priv = node->priv; + priv->context = zmq_context; + priv->socket = zmq_socket (zmq_context, ZMQ_REQ); + zmq_connect (priv->socket, address); + + return UFO_NODE (node); +} + +void +ufo_remote_node_request_setup (UfoRemoteNode *node) +{ + UfoRemoteNodePrivate *priv; + UfoMessage request; + zmq_msg_t reply_msg; + + g_return_if_fail (UFO_IS_REMOTE_NODE (node)); + + priv = node->priv; + request.type = UFO_MESSAGE_SETUP; + ufo_msg_send (&request, priv->socket, 0); + + /* Receive reply */ + zmq_msg_init (&reply_msg); + zmq_msg_recv (&reply_msg, priv->socket, 0); + zmq_msg_close (&reply_msg); +} + +void +ufo_remote_node_get_structure (UfoRemoteNode *node, + guint *n_inputs, + UfoInputParameter **in_params) +{ + UfoRemoteNodePrivate *priv; + UfoMessage request; + UfoMessage *header; + UfoInputParameter *payload; + zmq_msg_t header_msg; + zmq_msg_t payload_msg; + gsize payload_size; + + g_return_if_fail (UFO_IS_REMOTE_NODE (node)); + + priv = node->priv; + request.type = UFO_MESSAGE_GET_STRUCTURE; + ufo_msg_send (&request, priv->socket, 0); + + /* Receive header */ + zmq_msg_init (&header_msg); + zmq_msg_recv (&header_msg, priv->socket, 0); + header = (UfoMessage *) zmq_msg_data (&header_msg); + + /* Receive payload */ + zmq_msg_init (&payload_msg); + zmq_msg_recv (&payload_msg, priv->socket, 0); + payload_size = header->n_inputs * sizeof (UfoInputParameter); + g_assert (zmq_msg_size (&payload_msg) >= payload_size); + payload = zmq_msg_data (&payload_msg); + + priv->n_inputs = header->n_inputs; + *n_inputs = header->n_inputs; + *in_params = g_new0 (UfoInputParameter, header->n_inputs); + memcpy (*in_params, payload, payload_size); + + zmq_msg_close (&header_msg); + zmq_msg_close (&payload_msg); +} + +void +ufo_remote_node_send_inputs (UfoRemoteNode *node, + UfoBuffer **inputs) +{ + UfoRemoteNodePrivate *priv; + UfoMessage request; + zmq_msg_t reply_msg; + + g_return_if_fail (UFO_IS_REMOTE_NODE (node)); + + priv = node->priv; + request.type = UFO_MESSAGE_SEND_INPUTS; + ufo_msg_send (&request, priv->socket, ZMQ_SNDMORE); + + /* + * For each of the input data items send two frames: the first one contains + * the size as an UfoRequisition struct and the second one the raw byte + * data. + */ + for (guint i = 0; i < priv->n_inputs; i++) { + UfoRequisition requisition; + zmq_msg_t requisition_msg; + zmq_msg_t data_msg; + gsize size; + gint flags; + + ufo_buffer_get_requisition (inputs[i], &requisition); + size = ufo_buffer_get_size (inputs[i]); + + zmq_msg_init_size (&requisition_msg, sizeof (UfoRequisition)); + zmq_msg_init_size (&data_msg, size); + + memcpy (zmq_msg_data (&requisition_msg), &requisition, sizeof (UfoRequisition)); + memcpy (zmq_msg_data (&data_msg), ufo_buffer_get_host_array (inputs[i], NULL), size); + + flags = i == priv->n_inputs - 1 ? 0 : ZMQ_SNDMORE; + zmq_msg_send (&requisition_msg, priv->socket, ZMQ_SNDMORE); + zmq_msg_send (&data_msg, priv->socket, flags); + + zmq_msg_close (&requisition_msg); + zmq_msg_close (&data_msg); + } + + /* Receive final ACK */ + zmq_msg_init (&reply_msg); + zmq_msg_recv (&reply_msg, priv->socket, 0); + zmq_msg_close (&reply_msg); +} + +void +ufo_remote_node_get_result (UfoRemoteNode *node, + UfoBuffer *buffer) +{ + UfoRemoteNodePrivate *priv; + UfoMessage request; + zmq_msg_t reply_msg; + gpointer host_array; + + g_return_if_fail (UFO_IS_REMOTE_NODE (node)); + + priv = node->priv; + request.type = UFO_MESSAGE_GET_RESULT; + ufo_msg_send (&request, priv->socket, 0); + + /* Get the remote data and put it into our buffer */ + zmq_msg_init (&reply_msg); + zmq_msg_recv (&reply_msg, priv->socket, 0); + + ufo_buffer_discard_location (buffer, UFO_LOCATION_DEVICE); + host_array = ufo_buffer_get_host_array (buffer, NULL); + g_assert (ufo_buffer_get_size (buffer) == zmq_msg_size (&reply_msg)); + memcpy (host_array, zmq_msg_data (&reply_msg), ufo_buffer_get_size (buffer)); + + zmq_msg_close (&reply_msg); +} + +void +ufo_remote_node_get_requisition (UfoRemoteNode *node, + UfoRequisition *requisition) +{ + UfoRemoteNodePrivate *priv; + UfoMessage request; + zmq_msg_t reply_msg; + + g_return_if_fail (UFO_IS_REMOTE_NODE (node)); + + priv = node->priv; + request.type = UFO_MESSAGE_GET_REQUISITION; + ufo_msg_send (&request, priv->socket, 0); + + zmq_msg_init (&reply_msg); + zmq_msg_recv (&reply_msg, priv->socket, 0); + g_assert (zmq_msg_size (&reply_msg) >= sizeof (UfoRequisition)); + memcpy (requisition, zmq_msg_data (&reply_msg), sizeof (UfoRequisition)); + zmq_msg_close (&reply_msg); +} + +static void ufo_msg_send (UfoMessage *msg, + gpointer socket, + gint flags) +{ + zmq_msg_t request; + + zmq_msg_init_size (&request, sizeof (UfoMessage)); + memcpy (zmq_msg_data (&request), msg, sizeof (UfoMessage)); + zmq_msg_send (&request, socket, flags); + zmq_msg_close (&request); +} + +static void +ufo_remote_node_finalize (GObject *object) +{ + UfoRemoteNodePrivate *priv; + + priv = UFO_REMOTE_NODE_GET_PRIVATE (object); + zmq_close (priv->socket); + G_OBJECT_CLASS (ufo_remote_node_parent_class)->finalize (object); +} + +static void +ufo_remote_node_class_init (UfoRemoteNodeClass *klass) +{ + GObjectClass *oclass; + + oclass = G_OBJECT_CLASS (klass); + oclass->finalize = ufo_remote_node_finalize; + + g_type_class_add_private (klass, sizeof(UfoRemoteNodePrivate)); +} + +static void +ufo_remote_node_init (UfoRemoteNode *self) +{ + UfoRemoteNodePrivate *priv; + self->priv = priv = UFO_REMOTE_NODE_GET_PRIVATE (self); + priv->context = NULL; + priv->socket = NULL; + priv->n_inputs = 0; +} diff --git a/src/ufo-remote-node.h b/src/ufo-remote-node.h new file mode 100644 index 0000000..7f131c4 --- /dev/null +++ b/src/ufo-remote-node.h @@ -0,0 +1,80 @@ +#ifndef __UFO_REMOTE_NODE_H +#define __UFO_REMOTE_NODE_H + +#include <glib-object.h> +#include "ufo-node.h" +#include "ufo-buffer.h" +#include "ufo-task-iface.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_REMOTE_NODE (ufo_remote_node_get_type()) +#define UFO_REMOTE_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_REMOTE_NODE, UfoRemoteNode)) +#define UFO_IS_REMOTE_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_REMOTE_NODE)) +#define UFO_REMOTE_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_REMOTE_NODE, UfoRemoteNodeClass)) +#define UFO_IS_REMOTE_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_REMOTE_NODE)) +#define UFO_REMOTE_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_REMOTE_NODE, UfoRemoteNodeClass)) + +typedef struct _UfoRemoteNode UfoRemoteNode; +typedef struct _UfoRemoteNodeClass UfoRemoteNodeClass; +typedef struct _UfoRemoteNodePrivate UfoRemoteNodePrivate; +typedef struct _UfoMessage UfoMessage; + +/** + * UfoRemoteNode: + * + * Main object for organizing filters. The contents of the #UfoRemoteNode structure + * are private and should only be accessed via the provided API. + */ +struct _UfoRemoteNode { + /*< private >*/ + UfoNode parent_instance; + + UfoRemoteNodePrivate *priv; +}; + +/** + * UfoRemoteNodeClass: + * + * #UfoRemoteNode class + */ +struct _UfoRemoteNodeClass { + /*< private >*/ + UfoNodeClass parent_class; +}; + +typedef enum { + UFO_MESSAGE_SETUP = 0, + UFO_MESSAGE_GET_STRUCTURE, + UFO_MESSAGE_STRUCTURE, + UFO_MESSAGE_GET_REQUISITION, + UFO_MESSAGE_REQUISITION, + UFO_MESSAGE_SEND_INPUTS, + UFO_MESSAGE_GET_RESULT, + UFO_MESSAGE_RESULT, + UFO_MESSAGE_ACK +} UfoMessageType; + +struct _UfoMessage { + UfoMessageType type; + + guint n_inputs; +}; + +UfoNode *ufo_remote_node_new (gpointer zmq_context, + const gchar *address); +void ufo_remote_node_request_setup (UfoRemoteNode *node); +void ufo_remote_node_get_structure (UfoRemoteNode *node, + guint *n_inputs, + UfoInputParameter **in_params); +void ufo_remote_node_send_inputs (UfoRemoteNode *node, + UfoBuffer **inputs); +void ufo_remote_node_get_result (UfoRemoteNode *node, + UfoBuffer *result); +void ufo_remote_node_get_requisition (UfoRemoteNode *node, + UfoRequisition *requisition); +GType ufo_remote_node_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-remote-task.c b/src/ufo-remote-task.c new file mode 100644 index 0000000..603f6ee --- /dev/null +++ b/src/ufo-remote-task.c @@ -0,0 +1,160 @@ +/** + * SECTION:ufo-remote-task + * @Short_description: Encapsulate remote task + * @Title: Remote task + */ + +#include <gmodule.h> +#include <tiffio.h> +#ifdef __APPLE__ +#include <OpenCL/cl.h> +#else +#include <CL/cl.h> +#endif + +#include <ufo-remote-task.h> +#include <ufo-remote-node.h> +#include <ufo-cpu-task-iface.h> + +struct _UfoRemoteTaskPrivate { + UfoRemoteNode *remote; +}; + +static void ufo_task_interface_init (UfoTaskIface *iface); +static void ufo_cpu_task_interface_init (UfoCpuTaskIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UfoRemoteTask, ufo_remote_task, UFO_TYPE_TASK_NODE, + G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK, + ufo_task_interface_init) + G_IMPLEMENT_INTERFACE (UFO_TYPE_CPU_TASK, + ufo_cpu_task_interface_init)) + +#define UFO_REMOTE_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_REMOTE_TASK, UfoRemoteTaskPrivate)) + +enum { + PROP_0, + N_PROPERTIES +}; + +UfoNode * +ufo_remote_task_new (void) +{ + return UFO_NODE (g_object_new (UFO_TYPE_REMOTE_TASK, NULL)); +} + +static void +ufo_remote_task_setup (UfoTask *task, GError **error) +{ + UfoRemoteTaskPrivate *priv; + + priv = UFO_REMOTE_TASK_GET_PRIVATE (UFO_REMOTE_TASK (task)); + priv->remote = UFO_REMOTE_NODE (ufo_task_node_get_proc_node (UFO_TASK_NODE (task))); + g_assert (priv->remote != NULL); + g_object_ref (priv->remote); + ufo_remote_node_request_setup (priv->remote); +} + +static void +ufo_remote_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition) +{ + UfoRemoteTaskPrivate *priv; + + priv = UFO_REMOTE_TASK_GET_PRIVATE (UFO_REMOTE_TASK (task)); + + /* + * We send our input to the remote node which will execute immediately. + * After remote execution, we will know the requisition of the _last_ remote + * task node and can get it back. + */ + ufo_remote_node_send_inputs (priv->remote, inputs); + ufo_remote_node_get_requisition (priv->remote, requisition); +} + +static void +ufo_remote_task_get_structure (UfoTask *task, + guint *n_inputs, + UfoInputParameter **in_params) +{ + UfoRemoteTaskPrivate *priv; + + priv = UFO_REMOTE_TASK_GET_PRIVATE (UFO_REMOTE_TASK (task)); + ufo_remote_node_get_structure (priv->remote, n_inputs, in_params); +} + +static gboolean +ufo_remote_task_process (UfoCpuTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition) +{ + UfoRemoteTaskPrivate *priv; + priv = UFO_REMOTE_TASK_GET_PRIVATE (UFO_REMOTE_TASK (task)); + + ufo_remote_node_get_result (priv->remote, output); + return TRUE; +} + +static void +ufo_remote_task_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_remote_task_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_remote_task_dispose (GObject *object) +{ + UfoRemoteTaskPrivate *priv; + + priv = UFO_REMOTE_TASK_GET_PRIVATE (object); + g_object_unref (priv->remote); + priv->remote = NULL; + G_OBJECT_CLASS (ufo_remote_task_parent_class)->dispose (object); +} + +static void +ufo_task_interface_init (UfoTaskIface *iface) +{ + iface->setup = ufo_remote_task_setup; + iface->get_structure = ufo_remote_task_get_structure; + iface->get_requisition = ufo_remote_task_get_requisition; +} + +static void +ufo_cpu_task_interface_init (UfoCpuTaskIface *iface) +{ + iface->process = ufo_remote_task_process; +} + +static void +ufo_remote_task_class_init (UfoRemoteTaskClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + + oclass->set_property = ufo_remote_task_set_property; + oclass->get_property = ufo_remote_task_get_property; + oclass->dispose = ufo_remote_task_dispose; + + g_type_class_add_private (oclass, sizeof(UfoRemoteTaskPrivate)); +} + +static void +ufo_remote_task_init(UfoRemoteTask *self) +{ + self->priv = UFO_REMOTE_TASK_GET_PRIVATE(self); +} diff --git a/src/ufo-remote-task.h b/src/ufo-remote-task.h new file mode 100644 index 0000000..12e8d64 --- /dev/null +++ b/src/ufo-remote-task.h @@ -0,0 +1,48 @@ +#ifndef __UFO_REMOTE_TASK_H +#define __UFO_REMOTE_TASK_H + +#include <glib-object.h> +#include <ufo-task-node.h> + +G_BEGIN_DECLS + +#define UFO_TYPE_REMOTE_TASK (ufo_remote_task_get_type()) +#define UFO_REMOTE_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_REMOTE_TASK, UfoRemoteTask)) +#define UFO_IS_REMOTE_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_REMOTE_TASK)) +#define UFO_REMOTE_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_REMOTE_TASK, UfoRemoteTaskClass)) +#define UFO_IS_REMOTE_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_REMOTE_TASK)) +#define UFO_REMOTE_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_REMOTE_TASK, UfoRemoteTaskClass)) + +typedef struct _UfoRemoteTask UfoRemoteTask; +typedef struct _UfoRemoteTaskClass UfoRemoteTaskClass; +typedef struct _UfoRemoteTaskPrivate UfoRemoteTaskPrivate; + +/** + * UfoRemoteTask: + * + * Main object for organizing filters. The contents of the #UfoRemoteTask structure + * are private and should only be accessed via the provided API. + */ +struct _UfoRemoteTask { + /*< private >*/ + UfoTaskNode parent_instance; + + UfoRemoteTaskPrivate *priv; +}; + +/** + * UfoRemoteTaskClass: + * + * #UfoRemoteTask class + */ +struct _UfoRemoteTaskClass { + /*< private >*/ + UfoTaskNodeClass parent_class; +}; + +UfoNode *ufo_remote_task_new (void); +GType ufo_remote_task_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-resource-manager.c b/src/ufo-resource-manager.c deleted file mode 100644 index cc916ec..0000000 --- a/src/ufo-resource-manager.c +++ /dev/null @@ -1,846 +0,0 @@ -/** - * SECTION:ufo-resource-manager - * @Short_description: Manage OpenCL resources - * @Title: UfoResourceManager - * - * The #UfoResourceManager creates the OpenCL environment and loads OpenCL - * kernels from text files. - */ - -#include <glib.h> -#include <stdio.h> -#ifdef __APPLE__ -#include <OpenCL/cl.h> -#else -#include <CL/cl.h> -#endif - -#include "config.h" -#include "ufo-resource-manager.h" -#include "ufo-configurable.h" -#include "ufo-aux.h" - -G_DEFINE_TYPE_WITH_CODE (UfoResourceManager, ufo_resource_manager, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (UFO_TYPE_CONFIGURABLE, NULL)) - -#define UFO_RESOURCE_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_RESOURCE_MANAGER, UfoResourceManagerPrivate)) - -/** - * UfoResourceManagerError: - * @UFO_RESOURCE_MANAGER_ERROR_LOAD_PROGRAM: Could not load the OpenCL file - * @UFO_RESOURCE_MANAGER_ERROR_CREATE_PROGRAM: Could not create a program from - * the sources - * @UFO_RESOURCE_MANAGER_ERROR_BUILD_PROGRAM: Could not build program from - * sources - * @UFO_RESOURCE_MANAGER_ERROR_CREATE_KERNEL: Could not create kernel - * - * OpenCL related errors. - */ -GQuark ufo_resource_manager_error_quark (void) -{ - return g_quark_from_static_string ("ufo-resource-manager-error-quark"); -} - -struct _UfoResourceManagerPrivate { - UfoConfiguration *config; - - cl_uint num_platforms; - cl_platform_id *opencl_platforms; - cl_context opencl_context; - cl_uint *num_devices; /**< Number of OpenCL devices per platform id */ - cl_device_id **opencl_devices; /**< Array of OpenCL devices per platform id */ - cl_command_queue *command_queues; /**< Array of command queues per device */ - - GList *kernel_paths; /**< Colon-separated string with paths to kernel files */ - GHashTable *opencl_programs; /**< Map from filename to cl_program */ - GList *opencl_kernels; - GString *opencl_build_options; - GString *include_paths; /**< List of include paths "-I/foo/bar" built from added paths */ - - guint current_id; /**< current non-assigned buffer id */ -}; - -enum { - PROP_0, - PROP_CONFIG, - N_PROPERTIES -}; - -const gchar *opencl_error_msgs[] = { - "CL_SUCCESS", - "CL_DEVICE_NOT_FOUND", - "CL_DEVICE_NOT_AVAILABLE", - "CL_COMPILER_NOT_AVAILABLE", - "CL_MEM_OBJECT_ALLOCATION_FAILURE", - "CL_OUT_OF_RESOURCES", - "CL_OUT_OF_HOST_MEMORY", - "CL_PROFILING_INFO_NOT_AVAILABLE", - "CL_MEM_COPY_OVERLAP", - "CL_IMAGE_FORMAT_MISMATCH", - "CL_IMAGE_FORMAT_NOT_SUPPORTED", - "CL_BUILD_PROGRAM_FAILURE", - "CL_MAP_FAILURE", - "CL_MISALIGNED_SUB_BUFFER_OFFSET", - "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST", - - /* next IDs start at 30! */ - "CL_INVALID_VALUE", - "CL_INVALID_DEVICE_TYPE", - "CL_INVALID_PLATFORM", - "CL_INVALID_DEVICE", - "CL_INVALID_CONTEXT", - "CL_INVALID_QUEUE_PROPERTIES", - "CL_INVALID_COMMAND_QUEUE", - "CL_INVALID_HOST_PTR", - "CL_INVALID_MEM_OBJECT", - "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR", - "CL_INVALID_IMAGE_SIZE", - "CL_INVALID_SAMPLER", - "CL_INVALID_BINARY", - "CL_INVALID_BUILD_OPTIONS", - "CL_INVALID_PROGRAM", - "CL_INVALID_PROGRAM_EXECUTABLE", - "CL_INVALID_KERNEL_NAME", - "CL_INVALID_KERNEL_DEFINITION", - "CL_INVALID_KERNEL", - "CL_INVALID_ARG_INDEX", - "CL_INVALID_ARG_VALUE", - "CL_INVALID_ARG_SIZE", - "CL_INVALID_KERNEL_ARGS", - "CL_INVALID_WORK_DIMENSION", - "CL_INVALID_WORK_GROUP_SIZE", - "CL_INVALID_WORK_ITEM_SIZE", - "CL_INVALID_GLOBAL_OFFSET", - "CL_INVALID_EVENT_WAIT_LIST", - "CL_INVALID_EVENT", - "CL_INVALID_OPERATION", - "CL_INVALID_GL_OBJECT", - "CL_INVALID_BUFFER_SIZE", - "CL_INVALID_MIP_LEVEL", - "CL_INVALID_GLOBAL_WORK_SIZE" -}; - -const gchar * -opencl_map_error (int error) -{ - static const gchar *invalid = "Invalid error code"; - const gint array_size = sizeof opencl_error_msgs/sizeof(gchar*); - gint index; - - index = error >= -14 ? -error : -error-15; - - if (index >= 0 && index < array_size) - return opencl_error_msgs[index]; - - return invalid; -} - -static gchar * -resource_manager_load_opencl_program (const gchar *filename) -{ - FILE *fp = fopen (filename, "r"); - - if (fp == NULL) - return NULL; - - fseek (fp, 0, SEEK_END); - const gsize length = (gsize) ftell (fp); - rewind (fp); - gchar *buffer = (gchar *) g_malloc0(length + 1); - - if (buffer == NULL) { - fclose (fp); - return NULL; - } - - size_t buffer_length = fread (buffer, 1, length, fp); - fclose (fp); - - if (buffer_length != length) { - g_free (buffer); - return NULL; - } - - return buffer; -} - -static void -resource_manager_release_kernel (gpointer data, gpointer user_data) -{ - cl_kernel kernel = (cl_kernel) data; - CHECK_OPENCL_ERROR (clReleaseKernel (kernel)); - ufo_debug_cl ("Released kernel %p", (gpointer) kernel); -} - -static void -resource_manager_release_program (gpointer data) -{ - cl_program program = (cl_program) data; - CHECK_OPENCL_ERROR (clReleaseProgram (program)); - ufo_debug_cl ("Released program %p", (gpointer) program); -} - -static gchar * -resource_manager_find_path (UfoResourceManagerPrivate *priv, const gchar *filename) -{ - /* Check first if filename is already a path */ - if (g_path_is_absolute (filename)) { - if (g_file_test (filename, G_FILE_TEST_EXISTS)) - return g_strdup (filename); - else - return NULL; - } - - /* If it is not a path, search in all paths that were added */ - GList *elem = g_list_first (priv->kernel_paths); - - while (elem != NULL) { - gchar *path = g_strdup_printf ("%s%c%s", (gchar *) elem->data, G_DIR_SEPARATOR, filename); - - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - - g_free (path); - elem = g_list_next (elem); - } - - return NULL; -} - -/** - * ufo_resource_manager_new: - * @config: A #UfoConfiguration object or %NULL - * - * Create a new #UfoResourceManager instance. - * - * Returns: (transfer none): A new #UfoResourceManager - */ -UfoResourceManager * -ufo_resource_manager_new (UfoConfiguration *config) -{ - return UFO_RESOURCE_MANAGER (g_object_new (UFO_TYPE_RESOURCE_MANAGER, - "configuration", config, - NULL)); -} - -static void -add_paths (UfoResourceManagerPrivate *priv, gchar *paths[]) -{ - if (paths == NULL) - return; - - for (guint i = 0; paths[i] != NULL; i++) { - priv->kernel_paths = g_list_append (priv->kernel_paths, g_strdup (paths[i])); - g_string_append_printf (priv->include_paths, "-I%s ", paths[i]); - } -} - -static cl_program -add_program_from_source (UfoResourceManagerPrivate *priv, - const gchar *source, - const gchar *options, - GError **error) -{ - cl_program program; - gchar *build_options = NULL; - cl_int errcode = CL_SUCCESS; - - program = clCreateProgramWithSource (priv->opencl_context, - 1, &source, NULL, &errcode); - ufo_debug_cl ("Created program %p with error code %i", (gpointer) program, errcode); - - if (errcode != CL_SUCCESS) { - g_set_error (error, - UFO_RESOURCE_MANAGER_ERROR, - UFO_RESOURCE_MANAGER_ERROR_CREATE_PROGRAM, - "Failed to create OpenCL program: %s", opencl_map_error (errcode)); - return NULL; - } - - if (options != NULL) - build_options = g_strdup_printf ("%s %s %s", priv->opencl_build_options->str, priv->include_paths->str, options); - else - build_options = g_strdup_printf ("%s %s", priv->opencl_build_options->str, priv->include_paths->str); - - errcode = clBuildProgram (program, - priv->num_devices[0], - priv->opencl_devices[0], - build_options, - NULL, NULL); - - ufo_debug_cl ("Build program %p with error code %i", (gpointer) program, errcode); - g_free (build_options); - - if (errcode != CL_SUCCESS) { - g_set_error (error, - UFO_RESOURCE_MANAGER_ERROR, - UFO_RESOURCE_MANAGER_ERROR_BUILD_PROGRAM, - "Failed to build OpenCL program: %s", opencl_map_error (errcode)); - - const gsize LOG_SIZE = 4096; - gchar *log = (gchar *) g_malloc0(LOG_SIZE * sizeof (char)); - CHECK_OPENCL_ERROR (clGetProgramBuildInfo (program, - priv->opencl_devices[0][0], - CL_PROGRAM_BUILD_LOG, - LOG_SIZE, (void *) log, NULL)); - g_print ("\n=== Build log for s===%s\n\n", log); - g_free (log); - return NULL; - } - - return program; -} - -static cl_program -resource_manager_add_program (UfoResourceManager *manager, const gchar *filename, const gchar *options, GError **error) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager) || (filename != NULL), FALSE); - UfoResourceManagerPrivate *priv = manager->priv; - - /* Programs might be added multiple times if this is not locked */ - static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - g_static_mutex_lock (&mutex); - - /* Don't process the kernel file again, if already load */ - cl_program program = g_hash_table_lookup (priv->opencl_programs, filename); - - if (program != NULL) { - g_static_mutex_unlock (&mutex); - return program; - } - - gchar *path = resource_manager_find_path (priv, filename); - - if (path == NULL) { - g_set_error (error, - UFO_RESOURCE_MANAGER_ERROR, - UFO_RESOURCE_MANAGER_ERROR_LOAD_PROGRAM, - "Could not find `%s'. Maybe you forgot to pass a configuration?", filename); - g_static_mutex_unlock (&mutex); - return NULL; - } - - gchar *buffer = resource_manager_load_opencl_program (path); - g_free (path); - - if (buffer == NULL) { - g_set_error (error, - UFO_RESOURCE_MANAGER_ERROR, - UFO_RESOURCE_MANAGER_ERROR_LOAD_PROGRAM, - "Could not open `%s'", filename); - g_static_mutex_unlock (&mutex); - return NULL; - } - - program = add_program_from_source (priv, buffer, options, error); - g_message ("Added program %p from `%s`", (gpointer) program, filename); - - if (program != NULL) - g_hash_table_insert (priv->opencl_programs, g_strdup (filename), program); - - g_static_mutex_unlock (&mutex); - g_free (buffer); - return program; -} - -static cl_kernel -resource_manager_get_kernel (UfoResourceManagerPrivate *priv, cl_program program, const gchar *kernel_name, GError **error) -{ - cl_int errcode = CL_SUCCESS; - cl_kernel kernel = clCreateKernel (program, kernel_name, &errcode); - - ufo_debug_cl ("Created kernel `%s` from program %p", kernel_name, (gpointer) program); - - if (kernel == NULL || errcode != CL_SUCCESS) { - g_set_error (error, - UFO_RESOURCE_MANAGER_ERROR, - UFO_RESOURCE_MANAGER_ERROR_CREATE_KERNEL, - "Failed to create kernel `%s`: %s", kernel_name, opencl_map_error (errcode)); - return NULL; - } - - priv->opencl_kernels = g_list_append (priv->opencl_kernels, kernel); - CHECK_OPENCL_ERROR (clRetainKernel (kernel)); - return kernel; -} - -/** - * ufo_resource_manager_get_kernel: (skip) - * @manager: A #UfoResourceManager - * @filename: Name of the .cl kernel file - * @kernel_name: Name of a kernel - * @error: Return location for a GError from #UfoResourceManagerError, or NULL - * - * Loads a and builds a kernel from a file. The file is searched in the current - * working directory and all paths added through - * ufo_resource_manager_add_paths (). - * - * Returns: a cl_kernel object that is load from @filename or %NULL on error - */ -gpointer -ufo_resource_manager_get_kernel (UfoResourceManager *manager, const gchar *filename, const gchar *kernel_name, GError **error) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager) && - (filename != NULL) && (kernel_name != NULL), NULL); - - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (manager); - GError *tmp_error = NULL; - - cl_program program = resource_manager_add_program (manager, filename, "", &tmp_error); - - if (program == NULL) { - g_propagate_error (error, tmp_error); - return NULL; - } - - return resource_manager_get_kernel (priv, program, kernel_name, error); -} - -/** - * ufo_resource_manager_get_kernel_from_source: (skip) - * @manager: A #UfoResourceManager - * @source: OpenCL source string - * @kernel_name: Name of a kernel - * @error: Return location for a GError from #UfoResourceManagerError, or NULL - * - * Loads and builds a kernel from a string. - * - * Returns: a cl_kernel object that is load from @filename - */ -gpointer -ufo_resource_manager_get_kernel_from_source (UfoResourceManager *manager, const gchar *source, const gchar *kernel_name, GError **error) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager) && (source != NULL) && (kernel_name != NULL), NULL); - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (manager); - cl_program program = add_program_from_source (priv, source, NULL, error); - - /* - * We add the program under a fake file name. This looks very brittle to me - * (kernel name could be the same as a source filename) but it should work - * in most cases. - */ - if (program != NULL) - g_hash_table_insert (priv->opencl_programs, g_strdup (kernel_name), program); - else - return NULL; - - return resource_manager_get_kernel (priv, program, kernel_name, error); -} - -/* void ufo_resource_manager_call(UfoResourceManager *manager, */ -/* const gchar *kernel_name, */ -/* void *command_queue, */ -/* uint32_t work_dim, */ -/* size_t *global_work_size, */ -/* size_t *local_work_size, */ -/* ...) */ -/* { */ -/* cl_kernel kernel = (cl_kernel) g_hash_table_lookup(manager->priv->opencl_kernels, kernel_name); */ - -/* if (kernel == NULL) */ -/* return; */ - -/* cl_uint num_args = 0; */ -/* clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(cl_uint), &num_args, NULL); */ -/* void *ptr = NULL; */ -/* size_t size = 0; */ -/* va_list ap; */ -/* va_start(ap, local_work_size); */ -/* g_message("parsing arguments"); */ - -/* for (guint i = 0; i < num_args; i++) { */ -/* size = va_arg(ap, size_t); */ -/* ptr = va_arg(ap, void *); */ -/* clSetKernelArg(kernel, i, size, ptr); */ -/* } */ - -/* va_end(ap); */ -/* clEnqueueNDRangeKernel(command_queue, kernel, */ -/* work_dim, NULL, global_work_size, local_work_size, */ -/* 0, NULL, NULL); */ -/* } */ - -/** - * ufo_resource_manager_get_context: (skip) - * @manager: A #UfoResourceManager - * - * Returns the OpenCL context object that is used by the resource manager. This - * context can be used to initialize othe third-party libraries. - * - * Return value: A cl_context object. - */ -gpointer -ufo_resource_manager_get_context (UfoResourceManager *manager) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager), NULL); - return manager->priv->opencl_context; -} - -/** - * ufo_resource_manager_request_buffer: (skip) - * @manager: A #UfoResourceManager - * @num_dims: (in): Number of dimensions - * @dim_size: (in) (array): Size of each dimension - * @data: (in) (allow-none): Data used to initialize the buffer with, or NULL - * @cmd_queue: (in) (allow-none): If data should be copied onto the device, - * a cl_command_queue must be provide, or %NULL - * - * Creates a new #UfoBuffer and initializes it with data on demand. If - * non-floating point data have to be uploaded, use ufo_buffer_set_host_array() - * and ufo_buffer_reinterpret() on the #UfoBuffer. - * - * Return value: A new #UfoBuffer with the given dimensions - */ -UfoBuffer * -ufo_resource_manager_request_buffer (UfoResourceManager *manager, - guint num_dims, - const guint *dim_size, - gfloat *data, - gpointer cmd_queue) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager), NULL); - g_return_val_if_fail ((num_dims > UFO_BUFFER_MAX_NDIMS) || (dim_size != NULL), NULL); - - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (manager); - UfoBuffer *buffer = ufo_buffer_new (num_dims, dim_size); - const gsize num_bytes = ufo_buffer_get_size (buffer); - cl_mem_flags mem_flags = CL_MEM_READ_WRITE; - - if ((data != NULL) && (cmd_queue != NULL)) - mem_flags |= CL_MEM_COPY_HOST_PTR; - - cl_int errcode; - cl_mem buffer_mem = clCreateBuffer (priv->opencl_context, - mem_flags, - num_bytes, - data, &errcode); - CHECK_OPENCL_ERROR (errcode); - ufo_buffer_set_cl_mem (buffer, buffer_mem); - - if ((data) && (cmd_queue == NULL)) - ufo_buffer_set_host_array (buffer, data, num_bytes, NULL); - - return buffer; -} - -/** - * ufo_resource_manager_memalloc: (skip) - * @manager: A #UfoResourceManager - * @size: Size of cl_mem in bytes - * - * Allocates a new cl_mem object with the given size. - * - * Return value: A cl_mem object - */ -gpointer -ufo_resource_manager_memalloc (UfoResourceManager *manager, gsize size) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager) || (size == 0), NULL); - cl_int errcode = CL_SUCCESS; - cl_mem mem = clCreateBuffer (manager->priv->opencl_context, CL_MEM_READ_WRITE, size, NULL, &errcode); - CHECK_OPENCL_ERROR (errcode); - return mem; -} - -/** - * ufo_resource_manager_memdup: (skip) - * @manager: A #UfoResourceManager - * @memobj: A cl_mem object - * - * Creates a new cl_mem object with the same size and content as a given cl_mem - * object. - * - * Return value: A new cl_mem object - */ -gpointer -ufo_resource_manager_memdup (UfoResourceManager *manager, gpointer memobj) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager) || (memobj == NULL), NULL); - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (manager); - cl_int errcode; - cl_event event; - cl_mem mem, dup; - size_t size; - - mem = (cl_mem) memobj; - CHECK_OPENCL_ERROR (clGetMemObjectInfo (mem, CL_MEM_SIZE, sizeof (size_t), &size, NULL)); - dup = clCreateBuffer (priv->opencl_context, CL_MEM_READ_WRITE, size, NULL, &errcode); - CHECK_OPENCL_ERROR (errcode); - - CHECK_OPENCL_ERROR (clEnqueueCopyBuffer (priv->command_queues[0], - mem, dup, 0, 0, size, 0, NULL, &event)); - - CHECK_OPENCL_ERROR (clWaitForEvents (1, &event)); - CHECK_OPENCL_ERROR (clReleaseEvent (event)); - - return dup; -} - -/** - * ufo_resource_manager_get_command_queues: - * @manager: A #UfoResourceManager - * @cmd_queues: (out): Sets pointer to command_queues array - * @num_queues: (out): Number of queues - * - * Return the number and actual command queues. - */ -void ufo_resource_manager_get_command_queues (UfoResourceManager *manager, gpointer *cmd_queues, guint *num_queues) -{ - g_return_if_fail (UFO_IS_RESOURCE_MANAGER (manager) || (cmd_queues != NULL) || (num_queues != NULL)); - /* FIXME: Use only first platform */ - *num_queues = manager->priv->num_devices[0]; - *cmd_queues= manager->priv->command_queues; -} - -/** - * ufo_resource_manager_get_command_queue: (skip) - * @manager: A #UfoResourceManager - * @queue: The number of the queue which must be less than the number returned - * by ufo_resource_manager_get_number_of_devices (). - * - * Return a specific command queue. - * - * Return value: The ith cl_command_queue - * Since: 0.2 - */ -gpointer -ufo_resource_manager_get_command_queue (UfoResourceManager *manager, guint queue) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager), NULL); - g_return_val_if_fail (queue >= manager->priv->num_devices[0], NULL); - return manager->priv->command_queues[queue]; -} - -/** - * ufo_resource_manager_get_queue_number: - * @manager: A #UfoResourceManager - * @cmd_queue: A %cl_command_queue - * - * Translate a %cl_command_queue pointer into a numerical representation. - * - * Returns: The numeral position of %cmd_queue or -1 if it is not found. - * Since: 0.2 - */ -gint -ufo_resource_manager_get_queue_number (UfoResourceManager *manager, - gpointer cmd_queue) -{ - UfoResourceManagerPrivate *priv; - - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager), -1); - priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (manager); - - for (guint i = 0; i < priv->num_devices[0]; i++) - if (priv->command_queues[i] == cmd_queue) - return (gint) i; - - return -1; -} - -/** - * ufo_resource_manager_get_number_of_devices: - * @manager: A #UfoResourceManager - * - * Get number of acceleration devices such as GPUs. - * - * Return value: Number of acceleration devices. - */ -guint ufo_resource_manager_get_number_of_devices (UfoResourceManager *manager) -{ - g_return_val_if_fail (UFO_IS_RESOURCE_MANAGER (manager), 0); - return manager->priv->num_devices[0]; -} - -static void -ufo_resource_manager_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE(object); - - switch (property_id) { - case PROP_CONFIG: - { - UfoConfiguration *config; - gchar **paths; - GObject *value_object = g_value_get_object (value); - - ufo_set_property_object ((GObject **) &priv->config, value_object); - - if (value_object != NULL) { - config = UFO_CONFIGURATION (value_object); - paths = ufo_configuration_get_paths (config); - add_paths (priv, paths); - g_strfreev (paths); - } - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -ufo_resource_manager_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE(object); - - switch (property_id) { - case PROP_CONFIG: - g_value_set_object (value, priv->config); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -ufo_resource_manager_dispose (GObject *object) -{ - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (object); - - ufo_unref_stored_object ((GObject **) &priv->config); - - G_OBJECT_CLASS (ufo_resource_manager_parent_class)->finalize (object); - g_message ("UfoResourceManager: disposed"); -} - -static void -ufo_resource_manager_finalize (GObject *object) -{ - UfoResourceManagerPrivate *priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (object); - - g_hash_table_destroy (priv->opencl_programs); - g_list_foreach (priv->kernel_paths, (GFunc) g_free, NULL); - g_list_free (priv->kernel_paths); - g_list_foreach (priv->opencl_kernels, resource_manager_release_kernel, NULL); - g_list_free (priv->opencl_kernels); - - for (guint i = 0; i < priv->num_devices[0]; i++) - CHECK_OPENCL_ERROR (clReleaseCommandQueue (priv->command_queues[i])); - - CHECK_OPENCL_ERROR (clReleaseContext (priv->opencl_context)); - g_string_free (priv->opencl_build_options, TRUE); - g_string_free (priv->include_paths, TRUE); - - for (guint i = 0; i < priv->num_platforms; i ++) - g_free (priv->opencl_devices[i]); - - g_free (priv->num_devices); - g_free (priv->opencl_devices); - g_free (priv->opencl_platforms); - g_free (priv->command_queues); - priv->num_devices = NULL; - priv->opencl_kernels = NULL; - priv->opencl_devices = NULL; - priv->opencl_platforms = NULL; - - G_OBJECT_CLASS (ufo_resource_manager_parent_class)->finalize (object); - g_message ("UfoResourceManager: finalized"); -} - -static void -ufo_resource_manager_class_init (UfoResourceManagerClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->set_property = ufo_resource_manager_set_property; - gobject_class->get_property = ufo_resource_manager_get_property; - gobject_class->dispose = ufo_resource_manager_dispose; - gobject_class->finalize = ufo_resource_manager_finalize; - - g_object_class_override_property (gobject_class, PROP_CONFIG, "configuration"); - - g_type_class_add_private (klass, sizeof (UfoResourceManagerPrivate)); -} - -static void -ufo_resource_manager_init (UfoResourceManager *self) -{ - UfoResourceManagerPrivate *priv; - self->priv = priv = UFO_RESOURCE_MANAGER_GET_PRIVATE (self); - priv->current_id = 0; - - priv->config = NULL; - priv->opencl_programs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, resource_manager_release_program); - priv->kernel_paths = g_list_append (NULL, g_strdup (".")); - priv->opencl_kernels = NULL; - priv->opencl_platforms = NULL; - priv->opencl_build_options = g_string_new ("-cl-mad-enable "); - priv->include_paths = g_string_new ("-I. "); - - /* initialize OpenCL subsystem */ - int errcode = CL_SUCCESS; - CHECK_OPENCL_ERROR (clGetPlatformIDs (0, NULL, &priv->num_platforms)); - priv->opencl_platforms = g_malloc0(priv->num_platforms * sizeof (cl_platform_id)); - - CHECK_OPENCL_ERROR (clGetPlatformIDs (priv->num_platforms, priv->opencl_platforms, NULL)); - priv->num_devices = g_malloc0(priv->num_platforms * sizeof (cl_uint)); - priv->opencl_devices = g_malloc0(priv->num_platforms * sizeof (cl_device_id *)); - - ufo_debug_cl ("Number of OpenCL platforms: %i", priv->num_platforms); - - /* Get devices for each available platform */ - gchar *info_buffer = g_malloc0(256); - - for (guint i = 0; i < priv->num_platforms; i++) { - cl_uint num_devices; - cl_platform_id platform = priv->opencl_platforms[i]; - - CHECK_OPENCL_ERROR (clGetPlatformInfo (platform, CL_PLATFORM_NAME, 256, info_buffer, NULL)); - ufo_debug_cl ("--- %s ---", info_buffer); - CHECK_OPENCL_ERROR (clGetPlatformInfo (platform, CL_PLATFORM_VENDOR, 256, info_buffer, NULL)); - ufo_debug_cl (" Vendor : %s", info_buffer); - - if (g_str_has_prefix (info_buffer, "NVIDIA")) - g_string_append (priv->opencl_build_options, "-cl-nv-verbose -DVENDOR=NVIDIA"); - else if (g_str_has_prefix (info_buffer, "Advanced Micro Devices")) - g_string_append (priv->opencl_build_options, "-DVENDOR=AMD"); - - CHECK_OPENCL_ERROR (clGetPlatformInfo (platform, CL_PLATFORM_VERSION, 256, info_buffer, NULL)); - ufo_debug_cl (" Version : %s", info_buffer); - - CHECK_OPENCL_ERROR (clGetDeviceIDs (platform, - CL_DEVICE_TYPE_ALL, - 0, NULL, - &num_devices)); - priv->opencl_devices[i] = g_malloc0(num_devices * sizeof (cl_device_id)); - - CHECK_OPENCL_ERROR (clGetDeviceIDs (platform, - CL_DEVICE_TYPE_ALL, - num_devices, priv->opencl_devices[i], - NULL)); - priv->num_devices[i] = num_devices; - - ufo_debug_cl (" Device count : %i", num_devices); - ufo_debug_cl (" Build options : %s", priv->opencl_build_options->str); - } - - g_free (info_buffer); - cl_command_queue_properties queue_properties = CL_QUEUE_PROFILING_ENABLE; - - /* XXX: create context for each platform?! */ - if (priv->num_platforms > 0) { - priv->opencl_context = clCreateContext (NULL, - priv->num_devices[0], - priv->opencl_devices[0], - NULL, NULL, &errcode); - CHECK_OPENCL_ERROR (errcode); - priv->command_queues = g_malloc0(priv->num_devices[0] * sizeof (cl_command_queue)); - - for (guint i = 0; i < priv->num_devices[0]; i++) { - priv->command_queues[i] = clCreateCommandQueue (priv->opencl_context, - priv->opencl_devices[0][i], - queue_properties, &errcode); - CHECK_OPENCL_ERROR (errcode); - } - } -} diff --git a/src/ufo-resource-manager.h b/src/ufo-resource-manager.h deleted file mode 100644 index 0fed200..0000000 --- a/src/ufo-resource-manager.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __UFO_RESOURCE_MANAGER_H -#define __UFO_RESOURCE_MANAGER_H - -#include <glib-object.h> -#include "ufo-configuration.h" -#include "ufo-buffer.h" - -G_BEGIN_DECLS - -#define UFO_TYPE_RESOURCE_MANAGER (ufo_resource_manager_get_type()) -#define UFO_RESOURCE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_RESOURCE_MANAGER, UfoResourceManager)) -#define UFO_IS_RESOURCE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_RESOURCE_MANAGER)) -#define UFO_RESOURCE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_RESOURCE_MANAGER, UfoResourceManagerClass)) -#define UFO_IS_RESOURCE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_RESOURCE_MANAGER)) -#define UFO_RESOURCE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_RESOURCE_MANAGER, UfoResourceManagerClass)) - -typedef struct _UfoResourceManager UfoResourceManager; -typedef struct _UfoResourceManagerClass UfoResourceManagerClass; -typedef struct _UfoResourceManagerPrivate UfoResourceManagerPrivate; - -#define UFO_RESOURCE_MANAGER_ERROR ufo_resource_manager_error_quark() -typedef enum { - UFO_RESOURCE_MANAGER_ERROR_LOAD_PROGRAM, - UFO_RESOURCE_MANAGER_ERROR_CREATE_PROGRAM, - UFO_RESOURCE_MANAGER_ERROR_BUILD_PROGRAM, - UFO_RESOURCE_MANAGER_ERROR_CREATE_KERNEL -} UfoResourceManagerError; - - -/** - * opencl_map_error: (skip) - */ -const gchar *opencl_map_error(int error); - -/** - * CHECK_OPENCL_ERROR: - * @error: OpenCL error code - * - * Check the return value of OpenCL functions and issue a warning with file and - * line number if an error occured. - */ -#define CHECK_OPENCL_ERROR(error) { \ - if ((error) != CL_SUCCESS) g_log("ocl", G_LOG_LEVEL_CRITICAL, "Error <%s:%i>: %s", __FILE__, __LINE__, opencl_map_error((error))); } - -/** - * UfoResourceManager: - * - * Manages OpenCL resources. The contents of the #UfoResourceManager structure - * are private and should only be accessed via the provided API. - */ -struct _UfoResourceManager { - /*< private >*/ - GObject parent_instance; - - UfoResourceManagerPrivate *priv; -}; - -/** - * UfoResourceManagerClass: - * - * #UfoResourceManager class - */ -struct _UfoResourceManagerClass { - /*< private >*/ - GObjectClass parent_class; -}; - -UfoResourceManager *ufo_resource_manager_new (UfoConfiguration *config); -gpointer ufo_resource_manager_get_kernel (UfoResourceManager *manager, - const gchar *filename, - const gchar *kernel_name, - GError **error); -gpointer ufo_resource_manager_get_kernel_from_source (UfoResourceManager *manager, - const gchar *source, - const gchar *kernel_name, - GError **error); -gpointer ufo_resource_manager_get_context (UfoResourceManager *manager); -void ufo_resource_manager_get_command_queues (UfoResourceManager *manager, - gpointer *cmd_queues, - guint *num_queues); -gint ufo_resource_manager_get_queue_number (UfoResourceManager *manager, - gpointer cmd_queue); -gpointer ufo_resource_manager_get_command_queue (UfoResourceManager *manager, - guint queue); -guint ufo_resource_manager_get_number_of_devices (UfoResourceManager *manager); -gpointer ufo_resource_manager_memdup (UfoResourceManager *manager, - gpointer memobj); -gpointer ufo_resource_manager_memalloc (UfoResourceManager *manager, - gsize size); -UfoBuffer *ufo_resource_manager_request_buffer (UfoResourceManager *manager, - guint num_dims, - const guint *dim_size, - gfloat *data, - gpointer cmd_queue); -GType ufo_resource_manager_get_type (void); -GQuark ufo_resource_manager_error_quark (void); - -G_END_DECLS - -#endif diff --git a/src/ufo-resources.c b/src/ufo-resources.c new file mode 100644 index 0000000..ea3ac0a --- /dev/null +++ b/src/ufo-resources.c @@ -0,0 +1,665 @@ +/** + * SECTION:ufo-resources + * @Short_description: Manage OpenCL resources + * @Title: UfoResources + * + * The #UfoResources creates the OpenCL environment and loads OpenCL + * kernels from text files. + */ + +#include <glib.h> +#include <stdio.h> +#ifdef __APPLE__ +#include <OpenCL/cl.h> +#else +#include <CL/cl.h> +#endif + +#include "ufo-resources.h" +#include "ufo-configurable.h" + +G_DEFINE_TYPE_WITH_CODE (UfoResources, ufo_resources, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (UFO_TYPE_CONFIGURABLE, NULL)) + +#define UFO_RESOURCES_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_RESOURCES, UfoResourcesPrivate)) + +/** + * UfoResourcesError: + * @UFO_RESOURCES_ERROR_LOAD_PROGRAM: Could not load the OpenCL file + * @UFO_RESOURCES_ERROR_CREATE_PROGRAM: Could not create a program from + * the sources + * @UFO_RESOURCES_ERROR_BUILD_PROGRAM: Could not build program from + * sources + * @UFO_RESOURCES_ERROR_CREATE_KERNEL: Could not create kernel + * + * OpenCL related errors. + */ +GQuark +ufo_resources_error_quark (void) +{ + return g_quark_from_static_string ("ufo-resource-resources-error-quark"); +} + +struct _UfoResourcesPrivate { + UfoConfig *config; + + cl_uint num_platforms; + cl_platform_id *opencl_platforms; + cl_context opencl_context; + cl_uint *num_devices; /**< Number of OpenCL devices per platform id */ + cl_device_id **opencl_devices; /**< Array of OpenCL devices per platform id */ + cl_command_queue *command_queues; /**< Array of command queues per device */ + + GList *kernel_paths; /**< Colon-separated string with paths to kernel files */ + GHashTable *opencl_programs; /**< Map from filename to cl_program */ + GList *opencl_kernels; + GString *opencl_build_options; + GString *include_paths; /**< List of include paths "-I/foo/bar" built from added paths */ +}; + +enum { + PROP_0, + PROP_CONFIG, + N_PROPERTIES +}; + +const gchar *opencl_error_msgs[] = { + "CL_SUCCESS", + "CL_DEVICE_NOT_FOUND", + "CL_DEVICE_NOT_AVAILABLE", + "CL_COMPILER_NOT_AVAILABLE", + "CL_MEM_OBJECT_ALLOCATION_FAILURE", + "CL_OUT_OF_RESOURCES", + "CL_OUT_OF_HOST_MEMORY", + "CL_PROFILING_INFO_NOT_AVAILABLE", + "CL_MEM_COPY_OVERLAP", + "CL_IMAGE_FORMAT_MISMATCH", + "CL_IMAGE_FORMAT_NOT_SUPPORTED", + "CL_BUILD_PROGRAM_FAILURE", + "CL_MAP_FAILURE", + "CL_MISALIGNED_SUB_BUFFER_OFFSET", + "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST", + + /* next IDs start at 30! */ + "CL_INVALID_VALUE", + "CL_INVALID_DEVICE_TYPE", + "CL_INVALID_PLATFORM", + "CL_INVALID_DEVICE", + "CL_INVALID_CONTEXT", + "CL_INVALID_QUEUE_PROPERTIES", + "CL_INVALID_COMMAND_QUEUE", + "CL_INVALID_HOST_PTR", + "CL_INVALID_MEM_OBJECT", + "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR", + "CL_INVALID_IMAGE_SIZE", + "CL_INVALID_SAMPLER", + "CL_INVALID_BINARY", + "CL_INVALID_BUILD_OPTIONS", + "CL_INVALID_PROGRAM", + "CL_INVALID_PROGRAM_EXECUTABLE", + "CL_INVALID_KERNEL_NAME", + "CL_INVALID_KERNEL_DEFINITION", + "CL_INVALID_KERNEL", + "CL_INVALID_ARG_INDEX", + "CL_INVALID_ARG_VALUE", + "CL_INVALID_ARG_SIZE", + "CL_INVALID_KERNEL_ARGS", + "CL_INVALID_WORK_DIMENSION", + "CL_INVALID_WORK_GROUP_SIZE", + "CL_INVALID_WORK_ITEM_SIZE", + "CL_INVALID_GLOBAL_OFFSET", + "CL_INVALID_EVENT_WAIT_LIST", + "CL_INVALID_EVENT", + "CL_INVALID_OPERATION", + "CL_INVALID_GL_OBJECT", + "CL_INVALID_BUFFER_SIZE", + "CL_INVALID_MIP_LEVEL", + "CL_INVALID_GLOBAL_WORK_SIZE" +}; + +const gchar * +ufo_resources_clerr (int error) +{ + static const gchar *invalid = "Invalid error code"; + const gint array_size = sizeof opencl_error_msgs/sizeof(gchar*); + gint index; + + index = error >= -14 ? -error : -error-15; + + if (index >= 0 && index < array_size) + return opencl_error_msgs[index]; + + return invalid; +} + +static gchar * +resources_load_opencl_program (const gchar *filename) +{ + FILE *fp = fopen (filename, "r"); + + if (fp == NULL) + return NULL; + + fseek (fp, 0, SEEK_END); + const gsize length = (gsize) ftell (fp); + rewind (fp); + gchar *buffer = (gchar *) g_malloc0(length + 1); + + if (buffer == NULL) { + fclose (fp); + return NULL; + } + + size_t buffer_length = fread (buffer, 1, length, fp); + fclose (fp); + + if (buffer_length != length) { + g_free (buffer); + return NULL; + } + + return buffer; +} + +static void +resources_release_kernel (gpointer data, gpointer user_data) +{ + cl_kernel kernel = (cl_kernel) data; + UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (kernel)); +} + +static void +resources_release_program (gpointer data) +{ + cl_program program = (cl_program) data; + UFO_RESOURCES_CHECK_CLERR (clReleaseProgram (program)); +} + +static gchar * +resources_find_path (UfoResourcesPrivate *priv, const gchar *filename) +{ + /* Check first if filename is already a path */ + if (g_path_is_absolute (filename)) { + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + return g_strdup (filename); + else + return NULL; + } + + /* If it is not a path, search in all paths that were added */ + GList *elem = g_list_first (priv->kernel_paths); + + while (elem != NULL) { + gchar *path = g_strdup_printf ("%s%c%s", (gchar *) elem->data, G_DIR_SEPARATOR, filename); + + if (g_file_test (path, G_FILE_TEST_EXISTS)) + return path; + + g_free (path); + elem = g_list_next (elem); + } + + return NULL; +} + +/** + * ufo_resources_new: + * @config: A #UfoConfiguration object or %NULL + * + * Create a new #UfoResources instance. + * + * Returns: (transfer none): A new #UfoResources + */ +UfoResources * +ufo_resources_new (UfoConfig *config) +{ + return UFO_RESOURCES (g_object_new (UFO_TYPE_RESOURCES, + "configuration", config, + NULL)); +} + +static void +add_paths (UfoResourcesPrivate *priv, gchar *paths[]) +{ + if (paths == NULL) + return; + + for (guint i = 0; paths[i] != NULL; i++) { + priv->kernel_paths = g_list_append (priv->kernel_paths, g_strdup (paths[i])); + g_string_append_printf (priv->include_paths, "-I%s ", paths[i]); + } +} + +static cl_program +add_program_from_source (UfoResourcesPrivate *priv, + const gchar *source, + const gchar *options, + GError **error) +{ + cl_program program; + gchar *build_options = NULL; + cl_int errcode = CL_SUCCESS; + + program = clCreateProgramWithSource (priv->opencl_context, + 1, &source, NULL, &errcode); + + if (errcode != CL_SUCCESS) { + g_set_error (error, + UFO_RESOURCES_ERROR, + UFO_RESOURCES_ERROR_CREATE_PROGRAM, + "Failed to create OpenCL program: %s", ufo_resources_clerr (errcode)); + return NULL; + } + + if (options != NULL) + build_options = g_strdup_printf ("%s %s %s", priv->opencl_build_options->str, priv->include_paths->str, options); + else + build_options = g_strdup_printf ("%s %s", priv->opencl_build_options->str, priv->include_paths->str); + + errcode = clBuildProgram (program, + priv->num_devices[0], + priv->opencl_devices[0], + build_options, + NULL, NULL); + + g_free (build_options); + + if (errcode != CL_SUCCESS) { + g_set_error (error, + UFO_RESOURCES_ERROR, + UFO_RESOURCES_ERROR_BUILD_PROGRAM, + "Failed to build OpenCL program: %s", ufo_resources_clerr (errcode)); + + const gsize LOG_SIZE = 4096; + gchar *log = (gchar *) g_malloc0(LOG_SIZE * sizeof (char)); + UFO_RESOURCES_CHECK_CLERR (clGetProgramBuildInfo (program, + priv->opencl_devices[0][0], + CL_PROGRAM_BUILD_LOG, + LOG_SIZE, (void *) log, NULL)); + g_print ("\n=== Build log for s===%s\n\n", log); + g_free (log); + return NULL; + } + + return program; +} + +static cl_program +resources_add_program (UfoResources *resources, const gchar *filename, const gchar *options, GError **error) +{ + g_return_val_if_fail (UFO_IS_RESOURCES (resources) || (filename != NULL), FALSE); + UfoResourcesPrivate *priv = resources->priv; + + /* Programs might be added multiple times if this is not locked */ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + g_static_mutex_lock (&mutex); + + /* Don't process the kernel file again, if already load */ + cl_program program = g_hash_table_lookup (priv->opencl_programs, filename); + + if (program != NULL) { + g_static_mutex_unlock (&mutex); + return program; + } + + gchar *path = resources_find_path (priv, filename); + + if (path == NULL) { + g_set_error (error, + UFO_RESOURCES_ERROR, + UFO_RESOURCES_ERROR_LOAD_PROGRAM, + "Could not find `%s'. Maybe you forgot to pass a configuration?", filename); + g_static_mutex_unlock (&mutex); + return NULL; + } + + gchar *buffer = resources_load_opencl_program (path); + g_free (path); + + if (buffer == NULL) { + g_set_error (error, + UFO_RESOURCES_ERROR, + UFO_RESOURCES_ERROR_LOAD_PROGRAM, + "Could not open `%s'", filename); + g_static_mutex_unlock (&mutex); + return NULL; + } + + program = add_program_from_source (priv, buffer, options, error); + g_message ("Added program %p from `%s`", (gpointer) program, filename); + + if (program != NULL) + g_hash_table_insert (priv->opencl_programs, g_strdup (filename), program); + + g_static_mutex_unlock (&mutex); + g_free (buffer); + return program; +} + +static cl_kernel +resources_get_kernel (UfoResourcesPrivate *priv, + cl_program program, + const gchar *kernel_name, + GError **error) +{ + cl_int errcode = CL_SUCCESS; + cl_kernel kernel = clCreateKernel (program, kernel_name, &errcode); + + if (kernel == NULL || errcode != CL_SUCCESS) { + g_set_error (error, + UFO_RESOURCES_ERROR, + UFO_RESOURCES_ERROR_CREATE_KERNEL, + "Failed to create kernel `%s`: %s", kernel_name, ufo_resources_clerr (errcode)); + return NULL; + } + + priv->opencl_kernels = g_list_append (priv->opencl_kernels, kernel); + UFO_RESOURCES_CHECK_CLERR (clRetainKernel (kernel)); + return kernel; +} + +/** + * ufo_resources_get_kernel: + * @resources: A #UfoResources object + * @filename: Name of the .cl kernel file + * @kernel: Name of a kernel + * @error: Return location for a GError from #UfoResourcesError, or NULL + * + * Loads a and builds a kernel from a file. The file is searched in the current + * working directory and all paths added through + * ufo_resources_add_paths (). + * + * Returns: a cl_kernel object that is load from @filename or %NULL on error + */ +gpointer +ufo_resources_get_kernel (UfoResources *resources, + const gchar *filename, + const gchar *kernel, + GError **error) +{ + UfoResourcesPrivate *priv; + cl_program program; + GError *tmp_error = NULL; + + g_return_val_if_fail (UFO_IS_RESOURCES (resources) && + (filename != NULL) && + (kernel != NULL), NULL); + + priv = resources->priv; + program = resources_add_program (resources, filename, "", &tmp_error); + + if (program == NULL) { + g_propagate_error (error, tmp_error); + return NULL; + } + + return resources_get_kernel (priv, program, kernel, error); +} + +/** + * ufo_resources_get_kernel_from_source: (skip) + * @resources: A #UfoResources + * @source: OpenCL source string + * @kernel_name: Name of a kernel + * @error: Return location for a GError from #UfoResourcesError, or NULL + * + * Loads and builds a kernel from a string. + * + * Returns: a cl_kernel object that is load from @filename + */ +gpointer +ufo_resources_get_kernel_from_source (UfoResources *resources, + const gchar *source, + const gchar *kernel, + GError **error) +{ + UfoResourcesPrivate *priv; + cl_program program; + + g_return_val_if_fail (UFO_IS_RESOURCES (resources) && + (source != NULL) && + (kernel != NULL), NULL); + + priv = UFO_RESOURCES_GET_PRIVATE (resources); + program = add_program_from_source (priv, source, NULL, error); + + /* + * We add the program under a fake file name. This looks very brittle to me + * (kernel name could be the same as a source filename) but it should work + * in most cases. + */ + if (program != NULL) + g_hash_table_insert (priv->opencl_programs, g_strdup (kernel), program); + else + return NULL; + + return resources_get_kernel (priv, program, kernel, error); +} + +/** + * ufo_resources_get_context: (skip) + * @resources: A #UfoResources + * + * Returns the OpenCL context object that is used by the resource resources. This + * context can be used to initialize othe third-party libraries. + * + * Return value: A cl_context object. + */ +gpointer +ufo_resources_get_context (UfoResources *resources) +{ + g_return_val_if_fail (UFO_IS_RESOURCES (resources), NULL); + return resources->priv->opencl_context; +} + +/** + * ufo_resources_get_cmd_queues: + * @resources: A #UfoResources + * + * Returns: (element-type gpointer) (transfer container): List with + * cl_command_queue objects. + */ +GList * +ufo_resources_get_cmd_queues (UfoResources *resources) +{ + UfoResourcesPrivate *priv; + GList *result = NULL; + + g_return_val_if_fail (UFO_IS_RESOURCES (resources), NULL); + priv = resources->priv; + + for (guint i = 0; i < priv->num_devices[0]; i++) + result = g_list_append (result, priv->command_queues[i]); + + return result; +} + +static void +ufo_resources_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + UfoResourcesPrivate *priv = UFO_RESOURCES_GET_PRIVATE (object); + + switch (property_id) { + case PROP_CONFIG: + { + UfoConfig *config; + gchar **paths; + GObject *value_object = g_value_get_object (value); + + if (priv->config) + g_object_unref (priv->config); + + + if (value_object != NULL) { + config = UFO_CONFIG (value_object); + paths = ufo_config_get_paths (config); + add_paths (priv, paths); + g_strfreev (paths); + g_object_ref (config); + priv->config = config; + } + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_resources_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + UfoResourcesPrivate *priv = UFO_RESOURCES_GET_PRIVATE (object); + + switch (property_id) { + case PROP_CONFIG: + g_value_set_object (value, priv->config); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +ufo_resources_dispose (GObject *object) +{ + UfoResourcesPrivate *priv = UFO_RESOURCES_GET_PRIVATE (object); + + if (priv->config) { + g_object_unref (priv->config); + priv->config = NULL; + } + + G_OBJECT_CLASS (ufo_resources_parent_class)->finalize (object); +} + +static void +ufo_resources_finalize (GObject *object) +{ + UfoResourcesPrivate *priv = UFO_RESOURCES_GET_PRIVATE (object); + + g_hash_table_destroy (priv->opencl_programs); + g_list_foreach (priv->kernel_paths, (GFunc) g_free, NULL); + g_list_free (priv->kernel_paths); + g_list_foreach (priv->opencl_kernels, resources_release_kernel, NULL); + g_list_free (priv->opencl_kernels); + + for (guint i = 0; i < priv->num_devices[0]; i++) + UFO_RESOURCES_CHECK_CLERR (clReleaseCommandQueue (priv->command_queues[i])); + + UFO_RESOURCES_CHECK_CLERR (clReleaseContext (priv->opencl_context)); + + g_string_free (priv->opencl_build_options, TRUE); + g_string_free (priv->include_paths, TRUE); + + for (guint i = 0; i < priv->num_platforms; i ++) + g_free (priv->opencl_devices[i]); + + g_free (priv->num_devices); + g_free (priv->opencl_devices); + g_free (priv->opencl_platforms); + g_free (priv->command_queues); + + priv->num_devices = NULL; + priv->opencl_kernels = NULL; + priv->opencl_devices = NULL; + priv->opencl_platforms = NULL; + + G_OBJECT_CLASS (ufo_resources_parent_class)->finalize (object); + g_message ("UfoResources: finalized"); +} + +static void +ufo_resources_class_init (UfoResourcesClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = ufo_resources_set_property; + gobject_class->get_property = ufo_resources_get_property; + gobject_class->dispose = ufo_resources_dispose; + gobject_class->finalize = ufo_resources_finalize; + + g_object_class_override_property (gobject_class, PROP_CONFIG, "config"); + + g_type_class_add_private (klass, sizeof (UfoResourcesPrivate)); +} + +static void +ufo_resources_init (UfoResources *self) +{ + UfoResourcesPrivate *priv; + self->priv = priv = UFO_RESOURCES_GET_PRIVATE (self); + + priv->config = NULL; + priv->opencl_programs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, resources_release_program); + priv->kernel_paths = g_list_append (NULL, g_strdup (".")); + priv->opencl_kernels = NULL; + priv->opencl_platforms = NULL; + priv->opencl_build_options = g_string_new ("-cl-mad-enable "); + priv->include_paths = g_string_new ("-I. "); + + /* initialize OpenCL subsystem */ + int errcode = CL_SUCCESS; + UFO_RESOURCES_CHECK_CLERR (clGetPlatformIDs (0, NULL, &priv->num_platforms)); + priv->opencl_platforms = g_malloc0(priv->num_platforms * sizeof (cl_platform_id)); + + UFO_RESOURCES_CHECK_CLERR (clGetPlatformIDs (priv->num_platforms, priv->opencl_platforms, NULL)); + priv->num_devices = g_malloc0(priv->num_platforms * sizeof (cl_uint)); + priv->opencl_devices = g_malloc0(priv->num_platforms * sizeof (cl_device_id *)); + + /* Get devices for each available platform */ + gchar *info_buffer = g_malloc0 (256); + + for (guint i = 0; i < priv->num_platforms; i++) { + cl_uint num_devices; + cl_platform_id platform = priv->opencl_platforms[i]; + + UFO_RESOURCES_CHECK_CLERR (clGetPlatformInfo (platform, CL_PLATFORM_VENDOR, 256, info_buffer, NULL)); + + if (g_str_has_prefix (info_buffer, "NVIDIA")) + g_string_append (priv->opencl_build_options, "-cl-nv-verbose -DVENDOR=NVIDIA"); + else if (g_str_has_prefix (info_buffer, "Advanced Micro Devices")) + g_string_append (priv->opencl_build_options, "-DVENDOR=AMD"); + + UFO_RESOURCES_CHECK_CLERR (clGetDeviceIDs (platform, + CL_DEVICE_TYPE_ALL, + 0, NULL, + &num_devices)); + priv->opencl_devices[i] = g_malloc0 (num_devices * sizeof (cl_device_id)); + + UFO_RESOURCES_CHECK_CLERR (clGetDeviceIDs (platform, + CL_DEVICE_TYPE_ALL, + num_devices, priv->opencl_devices[i], + NULL)); + priv->num_devices[i] = num_devices; + } + + g_free (info_buffer); + cl_command_queue_properties queue_properties = CL_QUEUE_PROFILING_ENABLE; + + /* XXX: create context for each platform?! */ + if (priv->num_platforms > 0) { + priv->opencl_context = clCreateContext (NULL, + priv->num_devices[0], + priv->opencl_devices[0], + NULL, NULL, &errcode); + UFO_RESOURCES_CHECK_CLERR (errcode); + priv->command_queues = g_malloc0 (priv->num_devices[0] * sizeof (cl_command_queue)); + + for (guint i = 0; i < priv->num_devices[0]; i++) { + priv->command_queues[i] = clCreateCommandQueue (priv->opencl_context, + priv->opencl_devices[0][i], + queue_properties, &errcode); + UFO_RESOURCES_CHECK_CLERR (errcode); + } + } +} diff --git a/src/ufo-resources.h b/src/ufo-resources.h new file mode 100644 index 0000000..0744434 --- /dev/null +++ b/src/ufo-resources.h @@ -0,0 +1,84 @@ +#ifndef __UFO_RESOURCES_H +#define __UFO_RESOURCES_H + +#include <glib-object.h> +#include "ufo-config.h" +#include "ufo-buffer.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_RESOURCES (ufo_resources_get_type()) +#define UFO_RESOURCES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_RESOURCES, UfoResources)) +#define UFO_IS_RESOURCES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_RESOURCES)) +#define UFO_RESOURCES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_RESOURCES, UfoResourcesClass)) +#define UFO_IS_RESOURCES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_RESOURCES)) +#define UFO_RESOURCES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_RESOURCES, UfoResourcesClass)) + +typedef struct _UfoResources UfoResources; +typedef struct _UfoResourcesClass UfoResourcesClass; +typedef struct _UfoResourcesPrivate UfoResourcesPrivate; + +#define UFO_RESOURCES_ERROR ufo_resources_error_quark() +typedef enum { + UFO_RESOURCES_ERROR_LOAD_PROGRAM, + UFO_RESOURCES_ERROR_CREATE_PROGRAM, + UFO_RESOURCES_ERROR_BUILD_PROGRAM, + UFO_RESOURCES_ERROR_CREATE_KERNEL +} UfoResourcesError; + + +/** + * opencl_map_error: (skip) + */ + +/** + * UFO_RESOURCES_CHECK_CLERR: + * @error: OpenCL error code + * + * Check the return value of OpenCL functions and issue a warning with file and + * line number if an error occured. + */ +#define UFO_RESOURCES_CHECK_CLERR(error) { \ + if ((error) != CL_SUCCESS) g_log("ocl", G_LOG_LEVEL_CRITICAL, "Error <%s:%i>: %s", __FILE__, __LINE__, ufo_resources_clerr((error))); } + +/** + * UfoResources: + * + * Manages OpenCL resources. The contents of the #UfoResources structure + * are private and should only be accessed via the provided API. + */ +struct _UfoResources { + /*< private >*/ + GObject parent_instance; + + UfoResourcesPrivate *priv; +}; + +/** + * UfoResourcesClass: + * + * #UfoResources class + */ +struct _UfoResourcesClass { + /*< private >*/ + GObjectClass parent_class; +}; + +UfoResources * ufo_resources_new (UfoConfig *config); +gpointer ufo_resources_get_kernel (UfoResources *resources, + const gchar *filename, + const gchar *kernel, + GError **error); +gpointer ufo_resources_get_kernel_from_source (UfoResources *resources, + const gchar *source, + const gchar *kernel, + GError **error); +gpointer ufo_resources_get_context (UfoResources *resources); +GList * ufo_resources_get_cmd_queues (UfoResources *resources); +const gchar * ufo_resources_clerr (int error); +GType ufo_resources_get_type (void); +GQuark ufo_resources_error_quark (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-scheduler.c b/src/ufo-scheduler.c index eeb98b5..2edfd0b 100644 --- a/src/ufo-scheduler.c +++ b/src/ufo-scheduler.c @@ -15,803 +15,244 @@ #include <stdio.h> #include <string.h> -#include "config.h" -#include "ufo-aux.h" #include "ufo-scheduler.h" -#include "ufo-configurable.h" -#include "ufo-filter.h" -#include "ufo-filter-source.h" -#include "ufo-filter-sink.h" -#include "ufo-filter-reduce.h" -#include "ufo-filter-repeater.h" -#include "ufo-filter-splitter.h" +#include "ufo-buffer.h" +#include "ufo-task-node.h" +#include "ufo-task-iface.h" +#include "ufo-cpu-task-iface.h" +#include "ufo-gpu-task-iface.h" -G_DEFINE_TYPE_WITH_CODE (UfoScheduler, ufo_scheduler, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (UFO_TYPE_CONFIGURABLE, NULL)) +G_DEFINE_TYPE (UfoScheduler, ufo_scheduler, G_TYPE_OBJECT) #define UFO_SCHEDULER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_SCHEDULER, UfoSchedulerPrivate)) typedef struct { - UfoFilter *filter; - UfoProfiler *profiler; - guint num_inputs; - guint num_outputs; - UfoInputParameter *input_params; - UfoOutputParameter *output_params; - guint **output_dims; - UfoBuffer **work; - UfoBuffer **result; - guint num_children; - GError *error; - GAsyncQueue *return_queue; -} ThreadInfo; + UfoTask *task; + guint n_inputs; + UfoInputParameter + *in_params; +} ThreadLocalData; struct _UfoSchedulerPrivate { - UfoConfiguration *config; - UfoResourceManager *manager; - GAsyncQueue *return_queue; + guint foo; }; enum { PROP_0, - PROP_CONFIG, - PROP_RESOURCE_MANAGER, N_PROPERTIES }; -static GParamSpec *scheduler_properties[N_PROPERTIES] = { NULL, }; - -static gpointer NO_ERROR = GINT_TO_POINTER (1); - /** * ufo_scheduler_new: - * @config: (allow-none): A #UfoConfiguration or %NULL - * @manager: (allow-none): A #UfoResourceManager or %NULL * * Creates a new #UfoScheduler. * * Return value: A new #UfoScheduler */ UfoScheduler * -ufo_scheduler_new (UfoConfiguration *config, - UfoResourceManager *manager) +ufo_scheduler_new (void) { - UfoScheduler *scheduler; - - scheduler = UFO_SCHEDULER (g_object_new (UFO_TYPE_SCHEDULER, - "configuration", config, - "resource-manager", manager, - NULL)); - - return scheduler; + return UFO_SCHEDULER (g_object_new (UFO_TYPE_SCHEDULER, NULL)); } -static void -alloc_output_buffers (ThreadInfo *info, - gboolean use_default_value, - gfloat default_value) +static gpointer +run_task (ThreadLocalData *tld) { - UfoFilter *filter; - UfoOutputParameter *output_params; - UfoResourceManager *manager; - guint num_outputs; - guint num_buffers; - - filter = info->filter; - output_params = ufo_filter_get_output_parameters (filter); - manager = ufo_filter_get_resource_manager (filter); - num_outputs = ufo_filter_get_num_outputs (filter); - num_buffers = 2 * info->num_children * num_outputs; - - for (guint port = 0; port < num_outputs; port++) { - UfoChannel *channel; - guint num_dims; - - num_dims = output_params[port].n_dims; - channel = ufo_filter_get_output_channel (filter, port); - - for (guint i = 0; i < num_buffers; i++) { - UfoBuffer *buffer; - - buffer = ufo_resource_manager_request_buffer (manager, num_dims, info->output_dims[port], NULL, NULL); - - /* - * For some reason, if we don't reference the buffer again, - * it is returned by ufo_buffer_new() for other filters as - * well, thus sharing the buffer which is not what we want. - * - * TODO: remove the reference in a meaningful way, or find - * out what the problem is. - */ - g_object_ref (buffer); - - if (use_default_value) - ufo_buffer_fill_with_value (buffer, default_value); - - ufo_channel_insert (channel, buffer); + UfoBuffer *inputs[tld->n_inputs]; + UfoBuffer *output; + UfoTaskNode *node; + UfoRequisition requisition; + gboolean active; + + node = UFO_TASK_NODE (tld->task); + active = TRUE; + output = NULL; + + while (active) { + /* Get input buffers */ + for (guint i = 0; i < tld->n_inputs; i++) { + UfoGroup *group = ufo_task_node_get_current_in_group (node, i); + + inputs[i] = ufo_group_pop_input_buffer (group, tld->task); + + if (inputs[i] == UFO_END_OF_STREAM) { + active = FALSE; + break; + } } - } -} -static gboolean -expected_number_of_items_fetched (UfoInputParameter *param) -{ - return param->n_expected_items != UFO_FILTER_INFINITE_INPUT && - param->n_fetched_items >= param->n_expected_items; -} - -static void -cleanup_fetched (ThreadInfo *info) -{ - for (guint port = 0; port < info->num_inputs; port++) { - if (expected_number_of_items_fetched (&info->input_params[port])) { - UfoChannel *channel = ufo_filter_get_input_channel (info->filter, port); - ufo_channel_release_input (channel, info->work[port]); + if (!active) { + ufo_group_finish (ufo_task_node_get_out_group (node)); + break; } - } -} - -static gboolean -fetch_work (ThreadInfo *info) -{ - const gpointer POISON_PILL = GINT_TO_POINTER (1); - gboolean success = TRUE; - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_FETCH); + /* Get output buffers */ + ufo_task_get_requisition (tld->task, inputs, &requisition); - for (guint port = 0; port < info->num_inputs; port++) { - UfoChannel *channel = ufo_filter_get_input_channel (info->filter, port); + if (requisition.n_dims > 0) { + UfoGroup *group; - if (!expected_number_of_items_fetched (&info->input_params[port])) { - info->work[port] = ufo_channel_fetch_input (channel); - info->input_params[port].n_fetched_items++; + group = ufo_task_node_get_out_group (node); + output = ufo_group_pop_output_buffer (group, &requisition); + g_assert (output != NULL); } - if (info->work[port] == POISON_PILL) { - ufo_channel_finish_next (channel); - success = FALSE; - } - } - - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_FETCH); - return success; -} - -static void -push_work (ThreadInfo *info) -{ - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_RELEASE); + /* Process */ + if (UFO_IS_CPU_TASK (tld->task)) { + if (output != NULL) + ufo_buffer_discard_location (output, UFO_LOCATION_DEVICE); - for (guint port = 0; port < info->num_inputs; port++) { - if (!expected_number_of_items_fetched (&info->input_params[port])) { - UfoChannel *channel = ufo_filter_get_input_channel (info->filter, port); - ufo_channel_release_input (channel, info->work[port]); + active = ufo_cpu_task_process (UFO_CPU_TASK (tld->task), inputs, output, &requisition); } - } - - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_RELEASE); -} - -static void -fetch_result (ThreadInfo *info) -{ - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_FETCH); - - for (guint port = 0; port < info->num_outputs; port++) { - UfoChannel *channel = ufo_filter_get_output_channel (info->filter, port); - info->result[port] = ufo_channel_fetch_output (channel); - } - - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_FETCH); -} - -static void -push_result (ThreadInfo *info) -{ - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_RELEASE); - - for (guint port = 0; port < info->num_outputs; port++) { - UfoChannel *channel = ufo_filter_get_output_channel (info->filter, port); - ufo_channel_release_output (channel, info->result[port]); - } - - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_RELEASE); -} - -static GError * -process_source_filter (ThreadInfo *info) -{ - UfoFilter *filter = UFO_FILTER (info->filter); - GError *error = NULL; - gboolean cont = TRUE; - - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - ufo_filter_source_initialize (UFO_FILTER_SOURCE (filter), info->output_dims, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - alloc_output_buffers (info, FALSE, 0.0); - - while (cont) { - fetch_result (info); - - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - cont = ufo_filter_source_generate (UFO_FILTER_SOURCE (filter), info->result, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - if (cont) - push_result (info); - } - - return NULL; -} - -static GError * -process_synchronous_filter (ThreadInfo *info) -{ - UfoFilter *filter = UFO_FILTER (info->filter); - UfoFilterClass *filter_class = UFO_FILTER_GET_CLASS (filter); - GError *error = NULL; - gboolean cont = TRUE; - guint iteration = 0; - - /* - * Initialize - */ - if (fetch_work (info)) { - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - ufo_filter_initialize (filter, info->work, info->output_dims, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) { - g_error ("%s", error->message); - return error; + else if (UFO_IS_GPU_TASK (tld->task)) { + if (output != NULL) + ufo_buffer_discard_location (output, UFO_LOCATION_HOST); + + active = ufo_gpu_task_process (UFO_GPU_TASK (tld->task), + inputs, output, + &requisition, + UFO_GPU_NODE (ufo_task_node_get_proc_node (node))); } - alloc_output_buffers (info, FALSE, 0.0); - } - else { - return NULL; - } - - fetch_result (info); - - while (cont) { - g_message ("%-25s processing % 5i", - ufo_filter_get_unique_name (filter), - iteration++); - - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (filter_class->process_gpu != NULL) - ufo_filter_process_gpu (filter, info->work, info->result, &error); - else - ufo_filter_process_cpu (filter, info->work, info->result, &error); - - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - push_work (info); - push_result (info); - - fetch_result (info); - cont = fetch_work (info); - } - - /* - * In case this buffer keeps some of its inputs (if n_expected_items < - * UFO_FILTER_INPUT_INFINITE), then we need to return those buffers to the - * preceding filter. Otherwise we get stuck. - */ - cleanup_fetched (info); - - return NULL; -} - -static GError * -process_sink_filter (ThreadInfo *info) -{ - UfoFilter *filter = UFO_FILTER (info->filter); - UfoFilterSink *sink_filter = UFO_FILTER_SINK (filter); - GError *error = NULL; - gboolean cont = TRUE; - - if (fetch_work (info)) { - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - ufo_filter_sink_initialize (sink_filter, info->work, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - } - else - return NULL; - - while (cont) { - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - ufo_filter_sink_consume (sink_filter, info->work, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - push_work (info); - cont = fetch_work (info); - } - - return NULL; -} - -static GError * -process_reduce_filter (ThreadInfo *info) -{ - UfoFilter *filter = UFO_FILTER (info->filter); - GError *error = NULL; - gboolean cont; - gfloat default_value = 0.0f; - - if (fetch_work (info)) { - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - ufo_filter_reduce_initialize (UFO_FILTER_REDUCE (filter), info->work, info->output_dims, &default_value, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - alloc_output_buffers (info, TRUE, default_value); - } - else { - return NULL; - } - - /* - * Fetch the first result buffers and initialize them with the requested - * default value. These buffer will be used throughout the collection phase. - */ - fetch_result (info); - - for (guint i = 0; i < info->num_outputs; i++) - ufo_buffer_fill_with_value (info->result[i], default_value); - - /* - * Collect until no more data is available for consumption. The filter is - * given the same result buffers, so that results can be accumulated. - */ - cont = TRUE; - - while (cont) { - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - ufo_filter_reduce_collect (UFO_FILTER_REDUCE (filter), info->work, info->result, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - push_work (info); - cont = fetch_work (info); - } - - /* - * Calculate reduction results until the filter finishes. - */ - cont = TRUE; - - while (cont) { - ufo_profiler_start (info->profiler, UFO_PROFILER_TIMER_CPU); - cont = ufo_filter_reduce_reduce (UFO_FILTER_REDUCE (filter), info->result, &error); - ufo_profiler_stop (info->profiler, UFO_PROFILER_TIMER_CPU); - - if (error != NULL) - return error; - - if (cont) { - push_result (info); - fetch_result (info); + /* Release buffers for further consumption */ + for (guint i = 0; i < tld->n_inputs; i++) { + UfoGroup *group = ufo_task_node_get_current_in_group (node, i); + ufo_group_push_input_buffer (group, tld->task, inputs[i]); + ufo_task_node_switch_in_group (node, i); } - } - - return error; -} - -static GError * -process_splitter_filter (ThreadInfo *info) -{ - GValueArray *counts; - UfoChannel *channel; - gint max_count; - gint count; - guint output; - gboolean cont; - - g_object_get (info->filter, "counts", &counts, NULL); - - if (counts == NULL) { - GError *error; - g_set_error (&error, UFO_FILTER_ERROR, UFO_FILTER_ERROR_INSUFFICIENTINPUTS, - "`splitter's \"counts\" property must be set"); - return error; - } - - cont = fetch_work (info); - count = 0; - output = 0; - max_count = g_value_get_int (g_value_array_get_nth (counts, output)); + if (requisition.n_dims > 0) { + UfoGroup *group = ufo_task_node_get_out_group (node); - while (cont) { - if ((max_count >= 0) && (count == max_count) && (output < counts->n_values - 1)) { - output++; - count = 0; - max_count = g_value_get_int (g_value_array_get_nth (counts, output)); + if (active) + ufo_group_push_output_buffer (group, output); + else + ufo_group_finish (group); } - - channel = ufo_filter_get_output_channel (info->filter, output); - ufo_channel_release_output (channel, info->work[0]); - ufo_channel_fetch_output (channel); - push_work (info); - - count++; - cont = fetch_work (info); } return NULL; } -static GError * -process_repeater_filter (ThreadInfo *info) -{ - UfoChannel *channel; - gboolean cont; - guint count; - - g_object_get (G_OBJECT (info->filter), "count", &count, NULL); - - channel = ufo_filter_get_output_channel (info->filter, 0); - cont = fetch_work (info); - - if (!cont) { - g_warning ("`%s': didn't receive work\n", ufo_filter_get_unique_name (info->filter)); - return NULL; - } - - for (guint i = 0; i < count; i++) { - ufo_channel_release_output (channel, info->work[0]); - ufo_channel_fetch_output (channel); - } - - push_work (info); - - return NULL; -} - -static gpointer -process_thread (gpointer data) -{ - ThreadInfo *info = (ThreadInfo *) data; - UfoFilter *filter = info->filter; - GError *error = NULL; - - g_assert (ufo_filter_get_command_queue (filter) != NULL); - - UfoOutputParameter *output_params = ufo_filter_get_output_parameters (filter); - - info->num_inputs = ufo_filter_get_num_inputs (filter); - info->num_outputs = ufo_filter_get_num_outputs (filter); - info->input_params = ufo_filter_get_input_parameters (filter); - info->output_params = ufo_filter_get_output_parameters (filter); - info->work = g_malloc (info->num_inputs * sizeof (UfoBuffer *)); - info->result = g_malloc (info->num_outputs * sizeof (UfoBuffer *)); - info->output_dims = g_malloc0(info->num_outputs * sizeof (guint *)); - - for (guint i = 0; i < info->num_inputs; i++) - info->input_params[i].n_fetched_items = 0; - - for (guint i = 0; i < info->num_outputs; i++) - info->output_dims[i] = g_malloc0 (output_params[i].n_dims * sizeof(guint)); - - if (UFO_IS_FILTER_SOURCE (filter)) - error = process_source_filter (info); - else if (UFO_IS_FILTER_SINK (filter)) - error = process_sink_filter (info); - else if (UFO_IS_FILTER_REDUCE (filter)) - error = process_reduce_filter (info); - else if (UFO_IS_FILTER_SPLITTER (filter)) - error = process_splitter_filter (info); - else if (UFO_IS_FILTER_REPEATER (filter)) - error = process_repeater_filter (info); - else - error = process_synchronous_filter (info); - - g_async_queue_ref (info->return_queue); - - if (error != NULL) { - GError *prefixed; - - g_propagate_prefixed_error (&prefixed, error, "%s: ", ufo_filter_get_plugin_name (info->filter)); - g_async_queue_push (info->return_queue, prefixed); - } - else - g_async_queue_push (info->return_queue, NO_ERROR); - - g_async_queue_unref (info->return_queue); - - for (guint port = 0; port < info->num_outputs; port++) { - UfoChannel *channel = ufo_filter_get_output_channel (info->filter, port); - - if (channel != NULL) - ufo_channel_finish (channel); - } - - g_message ("UfoScheduler: %s finished", ufo_filter_get_unique_name (filter)); - - g_free (info->output_dims); - g_free (info->work); - g_free (info->result); - g_free (info); - - return NULL; -} - -static void -print_row (const gchar *row, FILE *fp) -{ - fprintf (fp, "%s\n", row); -} - -static void -pass_queue (UfoGraph *graph, UfoFilter *filter, guint queue, guint n_queues, cl_command_queue *queues) -{ - GList *children; - guint i = queue; - - children = ufo_graph_get_children (graph, filter); - - for (GList *it = g_list_first (children); it != NULL; it = g_list_next (it), i++) { - UfoFilter *successor; - guint new_queue; - - successor = UFO_FILTER (it->data); - new_queue = i % n_queues; - ufo_filter_set_command_queue (successor, queues[new_queue]); - pass_queue (graph, successor, new_queue, n_queues, queues); - } -} - -static void -init_filter_queues (UfoSchedulerPrivate *priv, - UfoGraph *graph) -{ - cl_command_queue *queues; - GList *roots; - guint n_queues; - guint i = 0; - - ufo_resource_manager_get_command_queues (priv->manager, (gpointer *) &queues, &n_queues); - - roots = ufo_graph_get_roots (graph); - - for (GList *it = g_list_first (roots); it != NULL; it = g_list_next (it), i++) { - UfoFilter *root; - guint queue; - - root = UFO_FILTER (it->data); - queue = i % n_queues; - ufo_filter_set_command_queue (root, queues[queue]); - pass_queue (graph, root, queue, n_queues, queues); - } - - g_list_free (roots); -} - -static GThread * -start_filter_thread (UfoSchedulerPrivate *priv, - UfoFilter *filter, - UfoGraph *graph, - GError **error) -{ - UfoProfilerLevel profile_level; - GList *children; - ThreadInfo *info; - - g_object_get (G_OBJECT (priv->config), - "profile-level", &profile_level, - NULL); - - info = g_new0 (ThreadInfo, 1); - info->filter = filter; - - info->return_queue = priv->return_queue; - info->profiler = ufo_profiler_new (profile_level); - ufo_filter_set_profiler (filter, info->profiler); - ufo_filter_set_resource_manager (filter, priv->manager); - - children = ufo_graph_get_children (graph, filter); - info->num_children = g_list_length (children); - g_list_free (children); - - return g_thread_create (process_thread, info, TRUE, error); -} - -static FILE * -open_prefixed_file (const gchar *prefix, const gchar *suffix) -{ - gchar *filename; - FILE *fp; - - filename = g_strdup_printf ("%s.%s", prefix, suffix); - fp = fopen (filename, "w"); - g_free (filename); - return fp; -} - -static void -print_profile_information (UfoSchedulerPrivate *priv, UfoGraph *graph) +void +ufo_scheduler_run (UfoScheduler *scheduler, + UfoArchGraph *arch_graph, + UfoTaskGraph *task_graph, + GError **error) { - GList *filters; - UfoProfilerLevel profile_level; - gchar *profile_prefix; - FILE *opencl_fp = stdout; - FILE *io_fp = stdout; - FILE *sync_fp = stdout; - FILE *cpu_fp = stdout; - - g_object_get (G_OBJECT (priv->config), - "profile-level", &profile_level, - "profile-output-prefix", &profile_prefix, - NULL); - - if (profile_prefix != NULL) { - if (profile_level & UFO_PROFILER_LEVEL_OPENCL) - opencl_fp = open_prefixed_file (profile_prefix, "cl.stat"); - - if (profile_level & UFO_PROFILER_LEVEL_IO) - io_fp = open_prefixed_file (profile_prefix, "io.stat"); - - if (profile_level & UFO_PROFILER_LEVEL_SYNC) - sync_fp = open_prefixed_file (profile_prefix, "sync.stat"); - - if (profile_level & UFO_PROFILER_LEVEL_CPU) - cpu_fp = open_prefixed_file (profile_prefix, "cpu.stat"); - } - - filters = ufo_graph_get_filters (graph); + GList *nodes; + guint n_nodes; + GThread **threads; + ThreadLocalData **tlds; + GTimer *timer; + gpointer context; - for (GList *it = filters; it != NULL; it = g_list_next (it)) { - UfoProfiler *profiler; - UfoFilter *filter; - - filter = (UfoFilter *) it->data; - profiler = ufo_filter_get_profiler (filter); + g_return_if_fail (UFO_IS_SCHEDULER (scheduler)); - if (profile_level & UFO_PROFILER_LEVEL_OPENCL) - ufo_profiler_foreach (profiler, (UfoProfilerFunc) print_row, opencl_fp); + ufo_task_graph_split (task_graph, arch_graph); + ufo_task_graph_map (task_graph, arch_graph); - if (profile_level & UFO_PROFILER_LEVEL_IO) - fprintf (io_fp, "%-16s %f\n", - ufo_filter_get_plugin_name (filter), - ufo_profiler_elapsed (profiler, UFO_PROFILER_TIMER_IO)); + timer = g_timer_new (); + context = ufo_arch_graph_get_context (arch_graph); + n_nodes = ufo_graph_get_num_nodes (UFO_GRAPH (task_graph)); + nodes = ufo_graph_get_nodes (UFO_GRAPH (task_graph)); + threads = g_new0 (GThread *, n_nodes); + tlds = g_new0 (ThreadLocalData *, n_nodes); - if (profile_level & UFO_PROFILER_LEVEL_SYNC) - fprintf (sync_fp, "%-16s %f %f\n", - ufo_filter_get_plugin_name (filter), - ufo_profiler_elapsed (profiler, UFO_PROFILER_TIMER_FETCH), - ufo_profiler_elapsed (profiler, UFO_PROFILER_TIMER_RELEASE)); + if (error && (*error != NULL)) + return; - if (profile_level & UFO_PROFILER_LEVEL_CPU) - fprintf (cpu_fp, "%-16s %f\n", - ufo_filter_get_plugin_name (filter), - ufo_profiler_elapsed (profiler, UFO_PROFILER_TIMER_CPU)); + for (guint i = 0; i < n_nodes; i++) { + UfoNode *node; + UfoGroup *group; + ThreadLocalData *tld; - g_object_unref (profiler); - } -} + node = g_list_nth_data (nodes, i); -static GError * -spawn_threads (UfoSchedulerPrivate *priv, UfoGraph *graph) -{ - GList *filters; - GList *threads = NULL; - GError *error = NULL; + /* Setup thread data */ + tld = g_new0 (ThreadLocalData, 1); + tld->task = UFO_TASK (node); + tlds[i] = tld; - filters = ufo_graph_get_filters (graph); + ufo_task_setup (UFO_TASK (node), error); + ufo_task_get_structure (UFO_TASK (node), + &tld->n_inputs, + &tld->in_params); - /* Start each filter in its own thread */ - for (GList *it = filters; it != NULL; it = g_list_next (it)) { - UfoFilter *filter; - GThread *thread; + group = ufo_group_new (ufo_graph_get_successors (UFO_GRAPH (task_graph), node), + context); - filter = (UfoFilter *) it->data; - thread = start_filter_thread (priv, filter, graph, &error); + ufo_task_node_set_out_group (UFO_TASK_NODE (node), group); - if (error != NULL) - return error; + /* TODO: cleanup */ + if (error && *error != NULL) + return; - threads = g_list_append (threads, thread); + g_object_set_data (G_OBJECT (node), "thread-local-data", tld); } - g_list_free (filters); - g_list_free (threads); - - return NULL; -} + /* Connect group references */ + for (guint i = 0; i < n_nodes; i++) { + UfoNode *node; + UfoGroup *group; + GList *successors; -static GError * -join_threads (UfoSchedulerPrivate *priv, UfoGraph *graph) -{ - guint n_threads; - guint n_finished; + node = g_list_nth_data (nodes, i); + group = ufo_task_node_get_out_group (UFO_TASK_NODE (node)); + successors = ufo_graph_get_successors (UFO_GRAPH (task_graph), node); - n_threads = ufo_graph_get_num_filters (graph); + for (GList *it = g_list_first (successors); it != NULL; it = g_list_next (it)) { + UfoNode *target; + UfoTaskGraphConnection *conn; - for (n_finished = 0; n_finished < n_threads; n_finished++) { - gpointer val = g_async_queue_pop (priv->return_queue); + target = UFO_NODE (it->data); + conn = ufo_graph_get_edge_label (UFO_GRAPH (task_graph), node, target); + ufo_task_node_add_in_group (UFO_TASK_NODE (target), + conn->target_input, + group); + } - if (val != NO_ERROR) - return val; + g_list_free (successors); } - return NULL; -} - -/** - * ufo_scheduler_run: - * @scheduler: A #UfoScheduler object - * @graph: A #UfoGraph object whose filters are scheduled - * @error: return location for a GError with error codes from - * #UfoPluginManagerError or %NULL - * - * Start executing all filters from the @filters list in their own threads. - */ -void -ufo_scheduler_run (UfoScheduler *scheduler, - UfoGraph *graph, - GError **error) -{ - UfoSchedulerPrivate *priv; - - GTimer *timer; - GError *tmp_error = NULL; - - g_return_if_fail (UFO_IS_SCHEDULER (scheduler)); - - priv = scheduler->priv; + g_timer_stop (timer); + g_print ("Preparation took %fs\n", g_timer_elapsed (timer, NULL)); - if (priv->config == NULL) - priv->config = ufo_configuration_new (); + g_timer_start (timer); - if (priv->manager == NULL) { - priv->manager = ufo_resource_manager_new (priv->config); + /* Spawn threads */ + for (guint i = 0; i < n_nodes; i++) { + threads[i] = g_thread_create ((GThreadFunc) run_task, + tlds[i], + TRUE, error); + if (error && (*error != NULL)) + return; } - init_filter_queues (priv, graph); + /* Wait for threads to finish */ + for (guint i = 0; i < n_nodes; i++) + g_thread_join (threads[i]); - timer = g_timer_new (); - tmp_error = spawn_threads (priv, graph); + g_timer_stop (timer); + g_print ("Processing finished after %3.5fs\n", + g_timer_elapsed (timer, NULL)); + g_timer_destroy (timer); - if (tmp_error != NULL) { - g_propagate_error (error, tmp_error); - return; - } + /* Cleanup */ + for (guint i = 0; i < n_nodes; i++) { + UfoNode *node; + UfoGroup *group; + ThreadLocalData *tld; - tmp_error = join_threads (priv, graph); + node = g_list_nth_data (nodes, i); + group = ufo_task_node_get_out_group (UFO_TASK_NODE (node)); + g_object_unref (group); - if (tmp_error != NULL) { - g_propagate_error (error, tmp_error); - return; + tld = tlds[i]; + g_free (tld); } - g_timer_stop (timer); - g_message ("Processing finished after %3.5f seconds", g_timer_elapsed (timer, NULL)); - g_timer_destroy (timer); - - print_profile_information (priv, graph); + g_free (tlds); } static void @@ -820,17 +261,7 @@ ufo_scheduler_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - UfoSchedulerPrivate *priv = UFO_SCHEDULER_GET_PRIVATE(object); - switch (property_id) { - case PROP_CONFIG: - ufo_set_property_object ((GObject **) &priv->config, g_value_get_object (value)); - break; - - case PROP_RESOURCE_MANAGER: - ufo_set_property_object ((GObject **) &priv->manager, g_value_get_object (value)); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -843,17 +274,7 @@ ufo_scheduler_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - UfoSchedulerPrivate *priv = UFO_SCHEDULER_GET_PRIVATE(object); - switch (property_id) { - case PROP_CONFIG: - g_value_set_object (value, priv->config); - break; - - case PROP_RESOURCE_MANAGER: - g_value_set_object (value, priv->manager); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -863,22 +284,13 @@ ufo_scheduler_get_property (GObject *object, static void ufo_scheduler_dispose (GObject *object) { - UfoSchedulerPrivate *priv = UFO_SCHEDULER_GET_PRIVATE (object); - - ufo_unref_stored_object ((GObject **) &priv->config); - ufo_unref_stored_object ((GObject **) &priv->manager); - - g_async_queue_unref (priv->return_queue); - G_OBJECT_CLASS (ufo_scheduler_parent_class)->dispose (object); - g_message ("UfoScheduler: disposed"); } static void ufo_scheduler_finalize (GObject *object) { G_OBJECT_CLASS (ufo_scheduler_parent_class)->finalize (object); - g_message ("UfoScheduler: finalized"); } static void @@ -890,16 +302,6 @@ ufo_scheduler_class_init (UfoSchedulerClass *klass) gobject_class->dispose = ufo_scheduler_dispose; gobject_class->finalize = ufo_scheduler_finalize; - scheduler_properties[PROP_RESOURCE_MANAGER] = - g_param_spec_object ("resource-manager", - "A UfoResourceManager", - "A UfoResourceManager", - UFO_TYPE_RESOURCE_MANAGER, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - g_object_class_install_property (gobject_class, PROP_RESOURCE_MANAGER, scheduler_properties[PROP_RESOURCE_MANAGER]); - g_object_class_override_property (gobject_class, PROP_CONFIG, "configuration"); - g_type_class_add_private (klass, sizeof (UfoSchedulerPrivate)); } @@ -907,6 +309,6 @@ static void ufo_scheduler_init (UfoScheduler *scheduler) { UfoSchedulerPrivate *priv; + scheduler->priv = priv = UFO_SCHEDULER_GET_PRIVATE (scheduler); - priv->return_queue = g_async_queue_new (); } diff --git a/src/ufo-scheduler.h b/src/ufo-scheduler.h index 1a7122a..6102474 100644 --- a/src/ufo-scheduler.h +++ b/src/ufo-scheduler.h @@ -2,10 +2,8 @@ #define __UFO_SCHEDULER_H #include <glib-object.h> -#include "ufo-configuration.h" -#include "ufo-graph.h" -#include "ufo-resource-manager.h" -#include "ufo-filter.h" +#include "ufo-arch-graph.h" +#include "ufo-task-graph.h" G_BEGIN_DECLS @@ -44,10 +42,10 @@ struct _UfoSchedulerClass { GObjectClass parent_class; }; -UfoScheduler* ufo_scheduler_new (UfoConfiguration *config, - UfoResourceManager *manager); +UfoScheduler* ufo_scheduler_new (void); void ufo_scheduler_run (UfoScheduler *scheduler, - UfoGraph *graph, + UfoArchGraph *arch_graph, + UfoTaskGraph *task_graph, GError** error); GType ufo_scheduler_get_type (void); diff --git a/src/ufo-task-graph.c b/src/ufo-task-graph.c new file mode 100644 index 0000000..5dcf59a --- /dev/null +++ b/src/ufo-task-graph.c @@ -0,0 +1,135 @@ +#include "ufo-task-graph.h" +#include "ufo-task-node.h" +#include "ufo-cpu-task-iface.h" +#include "ufo-gpu-task-iface.h" +#include "ufo-remote-task.h" +#include "ufo-input-task.h" + +G_DEFINE_TYPE (UfoTaskGraph, ufo_task_graph, UFO_TYPE_GRAPH) + +#define UFO_TASK_GRAPH_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_TASK_GRAPH, UfoTaskGraphPrivate)) + +struct _UfoTaskGraphPrivate { + gint foo; +}; + +UfoGraph * +ufo_task_graph_new (void) +{ + UfoTaskGraph *graph; + graph = UFO_TASK_GRAPH (g_object_new (UFO_TYPE_TASK_GRAPH, NULL)); + return UFO_GRAPH (graph); +} + +static gboolean +is_gpu_task (UfoNode *node) +{ + return UFO_IS_GPU_TASK (node); +} + +void +ufo_task_graph_split (UfoTaskGraph *task_graph, + UfoArchGraph *arch_graph) +{ + GList *paths; + guint n_gpus; + + paths = ufo_graph_get_paths (UFO_GRAPH (task_graph), is_gpu_task); + n_gpus = ufo_arch_graph_get_num_gpus (arch_graph); + + for (GList *it = g_list_first (paths); it != NULL; it = g_list_next (it)) { + GList *path = (GList *) it->data; + + for (guint i = 1; i < n_gpus; i++) + ufo_graph_split (UFO_GRAPH (task_graph), path); + + g_list_free (path); + } + + g_list_free (paths); +} + +void +ufo_task_graph_fuse (UfoTaskGraph *task_graph) +{ +} + +static void +map_proc_node (UfoGraph *graph, + UfoNode *node, + guint proc_index, + GList *gpu_nodes, + GList *remote_nodes) +{ + GList *successors; + guint index; + guint n_gpus; + + n_gpus = g_list_length (gpu_nodes); + successors = ufo_graph_get_successors (graph, node); + index = 0; + + if (UFO_IS_GPU_TASK (node)) { + ufo_task_node_set_proc_node (UFO_TASK_NODE (node), + g_list_nth_data (gpu_nodes, proc_index)); + } + + if (UFO_IS_INPUT_TASK (node)) { + ufo_task_node_set_proc_node (UFO_TASK_NODE (node), + g_list_nth_data (gpu_nodes, proc_index)); + } + + if (UFO_IS_REMOTE_TASK (node)) { + ufo_task_node_set_proc_node (UFO_TASK_NODE (node), + g_list_nth_data (remote_nodes, 0)); + } + + for (GList *it = g_list_first (successors); it != NULL; it = g_list_next (it)) { + map_proc_node (graph, UFO_NODE (it->data), proc_index + index, gpu_nodes, remote_nodes); + index = (index + 1) % n_gpus; + } + + g_list_free (successors); +} + + +/** + * ufo_task_graph_map: + * + * Map task nodes of a task graph to the processing nodes of an architecture + * graph. + */ +void +ufo_task_graph_map (UfoTaskGraph *task_graph, + UfoArchGraph *arch_graph) +{ + GList *gpu_nodes; + GList *remote_nodes; + GList *roots; + + gpu_nodes = ufo_arch_graph_get_gpu_nodes (arch_graph); + remote_nodes = ufo_arch_graph_get_remote_nodes (arch_graph); + roots = ufo_graph_get_roots (UFO_GRAPH (task_graph)); + + for (GList *it = g_list_first (roots); it != NULL; it = g_list_next (it)) + map_proc_node (UFO_GRAPH (task_graph), UFO_NODE (it->data), 0, gpu_nodes, remote_nodes); + + g_list_free (roots); +} + +static void +ufo_task_graph_class_init (UfoTaskGraphClass *klass) +{ + g_type_class_add_private(klass, sizeof(UfoTaskGraphPrivate)); +} + +static void +ufo_task_graph_init (UfoTaskGraph *self) +{ + UfoTaskGraphPrivate *priv; + self->priv = priv = UFO_TASK_GRAPH_GET_PRIVATE (self); + + /* Maybe we should define a specific task node type from which all tasks + * must inherit */ + ufo_graph_register_node_type (UFO_GRAPH (self), UFO_TYPE_NODE); +} diff --git a/src/ufo-task-graph.h b/src/ufo-task-graph.h new file mode 100644 index 0000000..4c79aa2 --- /dev/null +++ b/src/ufo-task-graph.h @@ -0,0 +1,60 @@ +#ifndef __UFO_TASK_GRAPH_H +#define __UFO_TASK_GRAPH_H + +#include <glib-object.h> +#include "ufo-graph.h" +#include "ufo-arch-graph.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_TASK_GRAPH (ufo_task_graph_get_type()) +#define UFO_TASK_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_TASK_GRAPH, UfoTaskGraph)) +#define UFO_IS_TASK_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_TASK_GRAPH)) +#define UFO_TASK_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_TASK_GRAPH, UfoTaskGraphClass)) +#define UFO_IS_TASK_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_TASK_GRAPH)) +#define UFO_TASK_GRAPH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_TASK_GRAPH, UfoTaskGraphClass)) + +typedef struct _UfoTaskGraph UfoTaskGraph; +typedef struct _UfoTaskGraphClass UfoTaskGraphClass; +typedef struct _UfoTaskGraphPrivate UfoTaskGraphPrivate; +typedef struct _UfoTaskGraphConnection UfoTaskGraphConnection; + +struct _UfoTaskGraphConnection { + guint source_output; + guint target_input; +}; + +/** + * UfoTaskGraph: + * + * Main object for organizing filters. The contents of the #UfoTaskGraph structure + * are private and should only be accessed via the provided API. + */ +struct _UfoTaskGraph { + /*< private >*/ + UfoGraph parent_instance; + + UfoTaskGraphPrivate *priv; +}; + +/** + * UfoTaskGraphClass: + * + * #UfoTaskGraph class + */ +struct _UfoTaskGraphClass { + /*< private >*/ + UfoGraphClass parent_class; +}; + +UfoGraph *ufo_task_graph_new (void); +void ufo_task_graph_map (UfoTaskGraph *task_graph, + UfoArchGraph *arch_graph); +void ufo_task_graph_split (UfoTaskGraph *task_graph, + UfoArchGraph *arch_graph); +void ufo_task_graph_fuse (UfoTaskGraph *task_graph); +GType ufo_task_graph_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-task-iface.c b/src/ufo-task-iface.c new file mode 100644 index 0000000..7d2b61a --- /dev/null +++ b/src/ufo-task-iface.c @@ -0,0 +1,59 @@ +#include "ufo-task-iface.h" + +typedef UfoTaskIface UfoTaskInterface; + +G_DEFINE_INTERFACE (UfoTask, ufo_task, G_TYPE_OBJECT) + +void +ufo_task_setup (UfoTask *task, + GError **error) +{ + UFO_TASK_GET_IFACE (task)->setup (task, error); +} + +void +ufo_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition) +{ + UFO_TASK_GET_IFACE (task)->get_requisition (task, inputs, requisition); +} + +void +ufo_task_get_structure (UfoTask *task, + guint *n_inputs, + UfoInputParameter **in_params) +{ + UFO_TASK_GET_IFACE (task)->get_structure (task, n_inputs, in_params); +} + +static void +ufo_task_setup_real (UfoTask *task, + GError **error) +{ + g_warning ("`setup' not implemented"); +} + +static void +ufo_task_get_requisition_real (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition) +{ + g_warning ("`get_allocation' not implemented"); +} + +static void +ufo_task_get_structure_real (UfoTask *task, + guint *n_inputs, + UfoInputParameter **in_params) +{ + g_warning ("`get_structure' not implemented"); +} + +static void +ufo_task_default_init (UfoTaskInterface *iface) +{ + iface->setup = ufo_task_setup_real; + iface->get_requisition = ufo_task_get_requisition_real; + iface->get_structure = ufo_task_get_structure_real; +} diff --git a/src/ufo-task-iface.h b/src/ufo-task-iface.h new file mode 100644 index 0000000..c9e7671 --- /dev/null +++ b/src/ufo-task-iface.h @@ -0,0 +1,62 @@ +#ifndef UFO_TASK_IFACE_H +#define UFO_TASK_IFACE_H + +#include <glib-object.h> +#include "ufo-buffer.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_TASK (ufo_task_get_type()) +#define UFO_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_TASK, UfoTask)) +#define UFO_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_TASK, UfoTaskIface)) +#define UFO_IS_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_TASK)) +#define UFO_IS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_TASK)) +#define UFO_TASK_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), UFO_TYPE_TASK, UfoTaskIface)) + +typedef struct _UfoTask UfoTask; +typedef struct _UfoTaskIface UfoTaskIface; +typedef struct _UfoInputParameter UfoInputParameter; +typedef struct _UfoOutputParameter UfoOutputParameter; + +/** + * UfoInputParameter: + * @n_dims: Number of dimension the input accept + * @n_expected_items: Number of expected items. Use UFO_FILTER_INFINITE_INPUT to + * accept a data stream. + * + * Data structure for describing the parameters of an input as used by + * ufo_filter_register_inputs(). + */ +struct _UfoInputParameter { + guint n_dims; + gint n_expected_items; +}; + +struct _UfoTaskIface { + GTypeInterface parent_iface; + + void (*setup) (UfoTask *task, + GError **error); + void (*get_structure) (UfoTask *task, + guint *n_inputs, + UfoInputParameter **in_params); + void (*get_requisition) (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition); +}; + +void ufo_task_setup (UfoTask *task, + GError **error); +void ufo_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition); +void ufo_task_get_structure (UfoTask *task, + guint *n_inputs, + UfoInputParameter + **in_params); + +GType ufo_task_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/ufo-task-node.c b/src/ufo-task-node.c new file mode 100644 index 0000000..648c0d0 --- /dev/null +++ b/src/ufo-task-node.c @@ -0,0 +1,114 @@ +#define _GNU_SOURCE +#include <sched.h> +#include "ufo-task-node.h" + +G_DEFINE_TYPE (UfoTaskNode, ufo_task_node, UFO_TYPE_NODE) + +#define UFO_TASK_NODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_TASK_NODE, UfoTaskNodePrivate)) + + +struct _UfoTaskNodePrivate { + UfoSendPattern pattern; + UfoNode *proc_node; + UfoGroup *out_group; + GList *in_groups[16]; + GList *current[16]; +}; + +void +ufo_task_node_set_send_pattern (UfoTaskNode *node, + UfoSendPattern pattern) +{ + g_return_if_fail (UFO_IS_TASK_NODE (node)); + node->priv->pattern = pattern; +} + +UfoSendPattern +ufo_task_node_get_send_pattern (UfoTaskNode *node) +{ + g_return_val_if_fail (UFO_IS_TASK_NODE (node), 0); + return node->priv->pattern; +} + +void +ufo_task_node_set_out_group (UfoTaskNode *node, + UfoGroup *group) +{ + g_return_if_fail (UFO_IS_TASK_NODE (node)); + node->priv->out_group = group; +} + +UfoGroup * +ufo_task_node_get_out_group (UfoTaskNode *node) +{ + g_return_val_if_fail (UFO_IS_TASK_NODE (node), NULL); + return node->priv->out_group; +} + +void +ufo_task_node_add_in_group (UfoTaskNode *node, + guint pos, + UfoGroup *group) +{ + g_return_if_fail (UFO_IS_TASK_NODE (node)); + /* TODO: check out-of-bounds condition */ + node->priv->in_groups[pos] = g_list_prepend (node->priv->in_groups[pos], group); + node->priv->current[pos] = node->priv->in_groups[pos]; +} + +UfoGroup * +ufo_task_node_get_current_in_group (UfoTaskNode *node, + guint pos) +{ + g_return_val_if_fail (UFO_IS_TASK_NODE (node), NULL); + return UFO_GROUP (node->priv->current[pos]->data); +} + +void +ufo_task_node_switch_in_group (UfoTaskNode *node, + guint pos) +{ + UfoTaskNodePrivate *priv; + + g_return_if_fail (UFO_IS_TASK_NODE (node)); + priv = node->priv; + priv->current[pos] = g_list_next (priv->current[pos]); + + if (priv->current[pos] == NULL) + priv->current[pos] = g_list_first (priv->in_groups[pos]); +} + +void +ufo_task_node_set_proc_node (UfoTaskNode *task_node, + UfoNode *proc_node) +{ + g_return_if_fail (UFO_IS_TASK_NODE (task_node) && UFO_IS_NODE (proc_node)); + task_node->priv->proc_node = proc_node; +} + +UfoNode * +ufo_task_node_get_proc_node (UfoTaskNode *node) +{ + g_return_val_if_fail (UFO_IS_TASK_NODE (node), NULL); + return node->priv->proc_node; +} + +static void +ufo_task_node_class_init (UfoTaskNodeClass *klass) +{ + g_type_class_add_private (klass, sizeof(UfoTaskNodePrivate)); +} + +static void +ufo_task_node_init (UfoTaskNode *self) +{ + self->priv = UFO_TASK_NODE_GET_PRIVATE (self); + self->priv->pattern = UFO_SEND_BROADCAST; + self->priv->proc_node = NULL; + self->priv->out_group = NULL; + + for (guint i = 0; i < 16; i++) { + self->priv->in_groups[i] = NULL; + self->priv->current[i] = NULL; + } +} diff --git a/src/ufo-task-node.h b/src/ufo-task-node.h new file mode 100644 index 0000000..a08fa7f --- /dev/null +++ b/src/ufo-task-node.h @@ -0,0 +1,70 @@ +#ifndef __UFO_TASK_NODE_H +#define __UFO_TASK_NODE_H + +#include <glib-object.h> +#include <sched.h> +#include "ufo-node.h" +#include "ufo-group.h" + +G_BEGIN_DECLS + +#define UFO_TYPE_TASK_NODE (ufo_task_node_get_type()) +#define UFO_TASK_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_TASK_NODE, UfoTaskNode)) +#define UFO_IS_TASK_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_TASK_NODE)) +#define UFO_TASK_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_TASK_NODE, UfoTaskNodeClass)) +#define UFO_IS_TASK_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_TASK_NODE)) +#define UFO_TASK_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_TASK_NODE, UfoTaskNodeClass)) + +typedef struct _UfoTaskNode UfoTaskNode; +typedef struct _UfoTaskNodeClass UfoTaskNodeClass; +typedef struct _UfoTaskNodePrivate UfoTaskNodePrivate; + +typedef enum { + UFO_SEND_BROADCAST, + UFO_SEND_SCATTER +} UfoSendPattern; + +/** + * UfoTaskNode: + * + * Main object for organizing filters. The contents of the #UfoTaskNode structure + * are private and should only be accessed via the provided API. + */ +struct _UfoTaskNode { + /*< private >*/ + UfoNode parent_instance; + + UfoTaskNodePrivate *priv; +}; + +/** + * UfoTaskNodeClass: + * + * #UfoTaskNode class + */ +struct _UfoTaskNodeClass { + /*< private >*/ + UfoNodeClass parent_class; +}; + +void ufo_task_node_set_send_pattern (UfoTaskNode *task_node, + UfoSendPattern pattern); +UfoSendPattern ufo_task_node_get_send_pattern (UfoTaskNode *task_node); +void ufo_task_node_set_out_group (UfoTaskNode *task_node, + UfoGroup *group); +UfoGroup *ufo_task_node_get_out_group (UfoTaskNode *task_node); +void ufo_task_node_add_in_group (UfoTaskNode *task_node, + guint pos, + UfoGroup *group); +UfoGroup *ufo_task_node_get_current_in_group (UfoTaskNode *task_node, + guint pos); +void ufo_task_node_switch_in_group (UfoTaskNode *task_node, + guint pos); +void ufo_task_node_set_proc_node (UfoTaskNode *task_node, + UfoNode *proc_node); +UfoNode *ufo_task_node_get_proc_node (UfoTaskNode *task_node); +GType ufo_task_node_get_type (void); + +G_END_DECLS + +#endif |