Reactor: add type-safe FunctionT and RoutineT

Bug: b/143479561
Change-Id: Ie1b8dad6611d5fb1e2a6e4cc679c01ac98cf8e4d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/37668
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Reactor/Routine.hpp b/src/Reactor/Routine.hpp
index 67560e8..f5dad2c 100644
--- a/src/Reactor/Routine.hpp
+++ b/src/Reactor/Routine.hpp
@@ -15,6 +15,8 @@
 #ifndef rr_Routine_hpp
 #define rr_Routine_hpp
 
+#include <memory>
+
 namespace rr
 {
 	class Routine
@@ -25,6 +27,47 @@
 
 		virtual const void *getEntry(int index = 0) = 0;
 	};
+
+	// RoutineT is a type-safe wrapper around a Routine and its callable entry, returned by FunctionT
+	template<typename FunctionType>
+	class RoutineT;
+
+	template<typename Return, typename... Arguments>
+	class RoutineT<Return(Arguments...)>
+	{
+	public:
+		RoutineT() = default;
+
+		explicit RoutineT(const std::shared_ptr<Routine>& routine)
+			: routine(routine)
+		{
+			if (routine)
+			{
+				callable = reinterpret_cast<CallableType>(const_cast<void*>(routine->getEntry(0)));
+			}
+		}
+
+		operator bool() const
+		{
+			return callable != nullptr;
+		}
+
+		template <typename... Args>
+		Return operator()(Args&&... args) const
+		{
+			return callable(std::forward<Args>(args)...);
+		}
+
+		const void* getEntry() const
+		{
+			return reinterpret_cast<void*>(callable);
+		}
+
+	private:
+		std::shared_ptr<Routine> routine;
+		using CallableType = Return(*)(Arguments...);
+		CallableType callable = nullptr;
+	};
 }
 
 #endif   // rr_Routine_hpp