summaryrefslogtreecommitdiff
path: root/indra/llcommon/llmake.h
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2015-12-18 18:06:32 -0500
committerNat Goodspeed <nat@lindenlab.com>2015-12-18 18:06:32 -0500
commit2ee22ed26483381bb13bc840090bad1897b4fd27 (patch)
tree06e7f052fd44cfa5f848a613b9b3179d2ec27a6e /indra/llcommon/llmake.h
parent4e8edebe13de9d638f1236bfd6aeddadf508de38 (diff)
MAINT-5976: Fix bug in LLCoros::set_consuming() mechanism.
The original implementation of set_consuming() involved a bool* pointing to a local bool in VoidListener::operator()()'s stack frame. postAndSuspend() would set that bool (through the pointer) as soon as it returned from suspension. The trouble with that is that LLEventMailDrop potentially calls its new listener (fulfilling the future) immediately in the listen_impl() override -- in other words, way up at the top of postAndSuspend(), well before the code that sets the relevant bool. Instead, make the adapter formerly known as VoidListener bind the coroutine's get_consuming() value at adapter construction time (before listening on the LLEventPump), so that its operator()() has the coroutine's correct get_consuming() value to return. Eliminating the bool* makes the code both simpler AND more correct! This change makes that adapter very specific to coroutine usage. Rename it FutureListener and migrate it from lleventcoros.h into the .cpp file. Nobody else was using it anyway. Make corresponding changes to postAndSuspend2() and its WaitForEventOnHelper class -- whose name no longer corresponds to the function as it used to. Rename that one FutureListener2. The new FutureListener functionality, common to both these adapters, makes it useful to derive FutureListener2 from FutureListener. Introduce llmake(), a generic function to deduce template type arguments from function parameter types. This allows us to remove the voidlistener() and wfeoh() helper functions. Hiding VoidListener broke one of the lleventcoro_test.cpp tests. But that test was sort of a lame recap of an earlier implementation of postAndSuspend(), based on LLEventPump events. Recast that test to illustrate how to use a coroutine future to suspend a coroutine for something other than an LLEventPump. But that rubbed my nose in the fact that we MUST wrap future's context switching with proper management of the current coroutine. Introduce LLCoros::Future<T>, which wraps boost::dcoroutines::future<T>. Use LLCoros::Future<T> in postAndSuspend() and postAndSuspend2().
Diffstat (limited to 'indra/llcommon/llmake.h')
-rw-r--r--indra/llcommon/llmake.h63
1 files changed, 63 insertions, 0 deletions
diff --git a/indra/llcommon/llmake.h b/indra/llcommon/llmake.h
new file mode 100644
index 0000000000..9a662a0640
--- /dev/null
+++ b/indra/llcommon/llmake.h
@@ -0,0 +1,63 @@
+/**
+ * @file llmake.h
+ * @author Nat Goodspeed
+ * @date 2015-12-18
+ * @brief Generic llmake<Template>(arg) function to instantiate
+ * Template<decltype(arg)>(arg).
+ *
+ * Many of our class templates have an accompanying helper function to
+ * make an instance with arguments of arbitrary type. llmake()
+ * eliminates the need to declare a new helper function for every such
+ * class template.
+ *
+ * also relevant:
+ *
+ * Template parameter deduction for constructors
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0091r0.html
+ *
+ * https://github.com/viboes/std-make
+ *
+ * but obviously we're not there yet.
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLMAKE_H)
+#define LL_LLMAKE_H
+
+/*==========================================================================*|
+// When we allow ourselves to compile with C++11 features enabled, this form
+// should generically handle an arbitrary number of arguments.
+
+template <template<typename...> class CLASS_TEMPLATE, typename... ARGS>
+CLASS_TEMPLATE<ARGS...> llmake(ARGS && ... args)
+{
+ return CLASS_TEMPLATE<ARGS...>(std::forward<ARGS>(args)...);
+}
+|*==========================================================================*/
+
+// As of 2015-12-18, this is what we'll use instead. Add explicit overloads
+// for different numbers of template parameters as use cases arise.
+
+/**
+ * Usage: llmake<SomeTemplate>(arg)
+ *
+ * Deduces the type T of 'arg' and returns an instance of SomeTemplate<T>
+ * initialized with 'arg'. Assumes a constructor accepting T (by value,
+ * reference or whatever).
+ */
+template <template<typename> class CLASS_TEMPLATE, typename ARG1>
+CLASS_TEMPLATE<ARG1> llmake(const ARG1& arg1)
+{
+ return CLASS_TEMPLATE<ARG1>(arg1);
+}
+
+template <template<typename, typename> class CLASS_TEMPLATE, typename ARG1, typename ARG2>
+CLASS_TEMPLATE<ARG1, ARG2> llmake(const ARG1& arg1, const ARG2& arg2)
+{
+ return CLASS_TEMPLATE<ARG1, ARG2>(arg1, arg2);
+}
+
+#endif /* ! defined(LL_LLMAKE_H) */