Background
I have the following system set up:
- An
ac::Activity
is the application logic that does stuff. You can think of it as containing the Controller and Model bits in an MVC design. This runs on the main thread [A]. - That has a list of
vc::View
s, which it sends the state of the application. Thevc::View
is essentially an adaptor for theac::Activity
. - The
vc::Endpoint
is something that runs on a different thread [E], which displays the state however it likes. - The
vc::_ac::Listener
is an input listener that runs on yet another thread [L]. I'm not sure this is the right thing to do, but I want a way for [A] to signal that Views should stop sending input (e.g. when the currentActivity
is swapped).
Here is a diagram of the relationships between these objects. Colour denotes thread, dashed lines are mpsc::channel
s, and solid lines are function calls:
With this system, the application can run on its own, and the theory is, whichever view sends it input, it can update all the other views.
Context
Conrod is a GUI library, and I have a Conrod view. What I understand of how it works is, you've got a window, and inside that window, you can swap out different Ui
s to draw different widgets. The Ui
caches things in memory. When you want to update the widgets, if you re-use the Ui
, drawing will be performant, whereas instantiating a new Ui
each time is not performant. Disclaimer: this may be an inaccurate description.
I've put the window inside the vc::Endpoint
, and the vc::View
determines what's drawn inside it by sending a new Ui
to the endpoint whenever the ac::Activity
calls show()
.
Problem
There's no issue when the activity does not send realtime updates, i.e. the ac::Activity
can make a single show()
call, and the vc::View
just needs to construct the Ui
once, and sends it across to the vc::Endpoint
transferring ownership. However, when the activity does send realtime updates such as for a loading activity which sends progress updates, the Ui
needs to change.
Since the Ui
is owned by the vc::Endpoint
, and the vc::Endpoint
has no knowledge of what's in the Ui
it's displaying, the logic to update the Ui
must live outside the vc::Endpoint
, maybe as part of the vc::View
or a separate thing. The following options seem to be available:
- The
vc::View
constructs a newUi
object every time (not performant, I've tried) - The
vc::View
wraps theUi
inArc<Mutex<..>>
so it can claim a mutable handle on updates - The
vc::View
sends a message to thevc::Endpoint
and asks for theUi
back, and then re-sends it to thevc::Endpoint
after changing it (both sides hold anOption<Ui>
or something) - Another separate event loop that the
vc::Endpoint
invokes, which can update theUi
. The event loop isActivity
specific, so it has to be constructed by thevc::View
at the same time it creates theUi
(and thevc::View
sends a wrapping object that contains theUi
and the event loop).
Are there any better options than the ones above, or do any of the above seem better than the others?