[Bf-blender-cvs] [010a4a76b58] functions: data flow graph

Jacques Lucke noreply at git.blender.org
Sun Feb 10 20:25:52 CET 2019


Commit: 010a4a76b58d11fff0603eb58a2d8bd5ebd31b6f
Author: Jacques Lucke
Date:   Sat Feb 2 15:03:39 2019 +0100
Branches: functions
https://developer.blender.org/rB010a4a76b58d11fff0603eb58a2d8bd5ebd31b6f

data flow graph

===================================================================

M	source/blender/blenlib/BLI_small_map.hpp
A	source/blender/blenlib/BLI_small_set.hpp
M	source/blender/blenlib/CMakeLists.txt
M	source/blender/functions/CMakeLists.txt
M	source/blender/functions/FN_functions.hpp
A	source/blender/functions/core/data_flow_graph.cpp
A	source/blender/functions/core/data_flow_graph.hpp

===================================================================

diff --git a/source/blender/blenlib/BLI_small_map.hpp b/source/blender/blenlib/BLI_small_map.hpp
index 62a52b9aede..573d1eb4619 100644
--- a/source/blender/blenlib/BLI_small_map.hpp
+++ b/source/blender/blenlib/BLI_small_map.hpp
@@ -1,4 +1,4 @@
-#pragma
+#pragma once
 
 #include "BLI_small_vector.hpp"
 
@@ -19,18 +19,22 @@ namespace BLI {
 		SmallVector<Entry> m_entries;
 
 	public:
-		SmallMap() {}
+		SmallMap() = default;
 
 		void add(K key, V value)
 		{
-			if (!this->contains(key)) {
-				this->m_entries.append(Entry(key, value));
+			for (Entry &entry : this->m_entries) {
+				if (entry.key == key) {
+					entry.value = value;
+					return;
+				}
 			}
+			this->m_entries.append(Entry(key, value));
 		}
 
 		bool contains(K key) const
 		{
-			for (const Entry &entry : this->m_entries) {
+			for (Entry entry : this->m_entries) {
 				if (entry.key == key) {
 					return true;
 				}
@@ -38,15 +42,26 @@ namespace BLI {
 			return false;
 		}
 
-		V lookup(K key) const
+		V lookup(const K &key) const
+		{
+			return this->lookup_ref(key);
+		}
+
+		V &lookup_ref(const K &key) const
+		{
+			V *ptr = this->lookup_ptr(key);
+			BLI_assert(ptr);
+			return *ptr;
+		}
+
+		V *lookup_ptr(const K &key) const
 		{
-			for (const Entry &entry : this->m_entries) {
+			for (Entry &entry : this->m_entries) {
 				if (entry.key == key) {
-					return entry.value;
+					return &entry.value;
 				}
 			}
-			BLI_assert(false);
-			return (V){};
+			return nullptr;
 		}
 
 		uint size() const
diff --git a/source/blender/blenlib/BLI_small_set.hpp b/source/blender/blenlib/BLI_small_set.hpp
new file mode 100644
index 00000000000..0eac0b2174c
--- /dev/null
+++ b/source/blender/blenlib/BLI_small_set.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "BLI_small_vector.hpp"
+
+namespace BLI {
+
+	template<typename T, uint N = 4>
+	class SmallSet {
+	private:
+		SmallVector<T> m_entries;
+
+	public:
+		SmallSet() = default;
+
+		void add(T value)
+		{
+			if (!this->contains(value)) {
+				this->m_entries.append(value);
+			}
+		}
+
+		bool contains(T value) const
+		{
+			for (T entry : this->m_entries) {
+				if (entry == value) {
+					return true;
+				}
+			}
+			return false;
+		}
+
+		uint size() const
+		{
+			return this->m_entries.size();
+		}
+
+
+		/* Iterators */
+
+		T *begin() const
+		{
+			return this->m_entries.begin();
+		}
+
+		T *end() const
+		{
+			return this->m_entries.end();
+		}
+
+		const T *cbegin() const
+		{
+			return this->m_entries.cbegin();
+		}
+
+		const T *cend() const
+		{
+			return this->m_entries.cend();
+		}
+	};
+
+} /* namespace BLI */
\ No newline at end of file
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 0e84b210863..c9530e4736c 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -227,6 +227,7 @@ set(SRC
 
 	BLI_small_vector.hpp
 	BLI_small_map.hpp
+	BLI_small_set.hpp
 )
 
 if(WITH_MEM_VALGRIND)
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
index fe5140ce88a..4d4ae0ebc48 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -11,7 +11,9 @@ set(SRC
 	c_wrapper.cpp
 
 	core/core.hpp
+	core/data_flow_graph.hpp
 	core/cpu.hpp
+	core/data_flow_graph.cpp
 
 	FN_functions.hpp
 
diff --git a/source/blender/functions/FN_functions.hpp b/source/blender/functions/FN_functions.hpp
index ea4e9ff7e42..3eb9fa1db57 100644
--- a/source/blender/functions/FN_functions.hpp
+++ b/source/blender/functions/FN_functions.hpp
@@ -1,4 +1,5 @@
 #pragma once
 
 #include "core/core.hpp"
+#include "core/data_flow_graph.hpp"
 #include "core/cpu.hpp"
\ No newline at end of file
diff --git a/source/blender/functions/core/data_flow_graph.cpp b/source/blender/functions/core/data_flow_graph.cpp
new file mode 100644
index 00000000000..ea7a7778dfa
--- /dev/null
+++ b/source/blender/functions/core/data_flow_graph.cpp
@@ -0,0 +1,13 @@
+#include "data_flow_graph.hpp"
+
+namespace FN {
+	const Type *Socket::type() const
+	{
+		if (this->m_is_output) {
+			return this->node()->signature().outputs()[this->m_index];
+		}
+		else {
+			return this->node()->signature().inputs()[this->m_index];
+		}
+	}
+};
\ No newline at end of file
diff --git a/source/blender/functions/core/data_flow_graph.hpp b/source/blender/functions/core/data_flow_graph.hpp
new file mode 100644
index 00000000000..727be5a4220
--- /dev/null
+++ b/source/blender/functions/core/data_flow_graph.hpp
@@ -0,0 +1,170 @@
+#pragma once
+
+#include "core.hpp"
+
+#include "BLI_small_set.hpp"
+
+namespace FN {
+
+	class Socket;
+	class Node;
+	class GraphLinks;
+	class DataFlowGraph;
+
+	class Socket {
+	public:
+		static Socket Input(const Node *node, uint index)
+		{
+			return Socket(node, false, index);
+		}
+
+		static Socket Output(const Node *node, uint index)
+		{
+			return Socket(node, true, index);
+		}
+
+		const Node *node() const
+		{
+			return this->m_node;
+		}
+
+		bool is_input() const
+		{
+			return !this->m_is_output;
+		}
+
+		bool is_output() const
+		{
+			return this->m_is_output;
+		}
+
+		uint index() const
+		{
+			return this->m_index;
+		}
+
+		const Type *type() const;
+
+		friend bool operator==(const Socket &a, const Socket &b)
+		{
+			return (
+				a.m_node == b.m_node &&
+				a.m_is_output == b.m_is_output &&
+				a.m_index == b.m_index);
+		}
+
+	private:
+		Socket(const Node *node, bool is_output, uint index)
+			: m_node(node), m_is_output(is_output), m_index(index) {}
+
+		const Node *m_node;
+		const bool m_is_output;
+		const uint m_index;
+	};
+
+	class Node {
+	public:
+		Node(const Function &function)
+			: m_function(function) {}
+
+		Socket input(uint index) const
+		{
+			return Socket::Input(this, index);
+		}
+
+		Socket output(uint index) const
+		{
+			return Socket::Output(this, index);
+		}
+
+		const Function &function() const
+		{
+			return this->m_function;
+		}
+
+		const Signature &signature() const
+		{
+			return this->function().signature();
+		}
+
+	private:
+		const Function &m_function;
+	};
+
+	class GraphLinks {
+	public:
+		void insert(Socket a, Socket b)
+		{
+			if (!this->m_links.contains(a)) {
+				this->m_links.add(a, SmallSet<Socket>());
+			}
+			if (!this->m_links.contains(b)) {
+				this->m_links.add(b, SmallSet<Socket>());
+			}
+
+			this->m_links.lookup_ref(a).add(b);
+			this->m_links.lookup_ref(b).add(a);
+		}
+
+		SmallSet<Socket> get_linked(Socket socket) const
+		{
+			return this->m_links.lookup(socket);
+		}
+
+	private:
+		SmallMap<Socket, SmallSet<Socket>> m_links;
+	};
+
+	class DataFlowGraph {
+	public:
+		DataFlowGraph() = default;
+
+		~DataFlowGraph()
+		{
+			for (const Node *node : this->m_nodes) {
+				delete node;
+			}
+		}
+
+		const Node *insert(const Function &function)
+		{
+			BLI_assert(this->can_modify());
+			const Node *node = new Node(function);
+			this->m_nodes.add(node);
+			return node;
+		}
+
+		void link(Socket a, Socket b)
+		{
+			BLI_assert(this->can_modify());
+			BLI_assert(a.node() != b.node());
+			BLI_assert(a.is_input() != b.is_input());
+			BLI_assert(m_nodes.contains(a.node()));
+			BLI_assert(m_nodes.contains(b.node()));
+
+			m_links.insert(a, b);
+			m_links.insert(b, a);
+		}
+
+		inline bool can_modify() const
+		{
+			return !this->frozen();
+		}
+
+		inline bool frozen() const
+		{
+			return this->m_frozen;
+		}
+
+		void freeze()
+		{
+			this->m_frozen = true;
+		}
+
+	private:
+		bool m_frozen = false;
+		SmallSet<const Node *> m_nodes;
+		GraphLinks m_links;
+	};
+
+} /* namespace FN */
\ No newline at end of file



More information about the Bf-blender-cvs mailing list