Harden message dispatch against cmd+. by using more safely shared state

nix
Owen Green 6 years ago
parent c1f7725d71
commit 253339aac2

@ -847,6 +847,7 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
using FloatControlsIter = impl::FloatControlsIter; using FloatControlsIter = impl::FloatControlsIter;
using SharedState = std::shared_ptr<WrapperState<C>>;
//I would like to template these to something more scaleable, but baby steps //I would like to template these to something more scaleable, but baby steps
friend class impl::RealTime<C,FluidSCWrapper>; friend class impl::RealTime<C,FluidSCWrapper>;
friend class impl::NonRealTime<C,FluidSCWrapper>; friend class impl::NonRealTime<C,FluidSCWrapper>;
@ -1185,7 +1186,7 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
struct MessageDispatch struct MessageDispatch
{ {
static constexpr size_t Message = N; static constexpr size_t Message = N;
FluidSCWrapper* wrapper; SharedState state;
ArgTuple args; ArgTuple args;
Ret result; Ret result;
std::string name; std::string name;
@ -1226,7 +1227,7 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
void* msgptr = ft->fRTAlloc(x->mWorld, sizeof(MessageData)); void* msgptr = ft->fRTAlloc(x->mWorld, sizeof(MessageData));
MessageData* msg = new (msgptr) MessageData; MessageData* msg = new (msgptr) MessageData;
msg->name = '/' + Client::getMessageDescriptors().template name<N>(); msg->name = '/' + Client::getMessageDescriptors().template name<N>();
msg->wrapper = x; msg->state = x->state();
ArgTuple& args = msg->args; ArgTuple& args = msg->args;
// type check OSC message // type check OSC message
@ -1306,10 +1307,10 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
{ {
MessageData* m = static_cast<MessageData*>(data); MessageData* m = static_cast<MessageData*>(data);
m->result = m->result =
ReturnType{invokeImpl<N>(m->wrapper, m->args, IndexList{})}; ReturnType{invokeImpl<N>(m->state, m->args, IndexList{})};
if (!m->result.ok()) if (!m->result.ok())
printResult(m->wrapper, m->result); printResult(m->state, m->result);
return true; return true;
}, },
@ -1321,11 +1322,12 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
world); world);
if(m->result.status() != Result::Status::kError) if(m->result.status() != Result::Status::kError)
messageOutput(m->wrapper, m->name, m->result); messageOutput(m->state, m->name, m->result);
else else
{ {
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
ft->fSendNodeReply(&m->wrapper->mParent->mNode, if(m->state->mNodeAlive)
ft->fSendNodeReply(m->state->mNode,
-1, m->name.c_str(),0, nullptr); -1, m->name.c_str(),0, nullptr);
} }
return true; return true;
@ -1341,54 +1343,59 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
} }
template <size_t N, typename ArgsTuple, size_t... Is> // Call from NRT template <size_t N, typename ArgsTuple, size_t... Is> // Call from NRT
static decltype(auto) invokeImpl(FluidSCWrapper* x, ArgsTuple& args, static decltype(auto) invokeImpl(SharedState& x, ArgsTuple& args,
std::index_sequence<Is...>) std::index_sequence<Is...>)
{ {
return x->client().template invoke<N>(x->client(), std::get<Is>(args)...); return x->client.template invoke<N>(x->client, std::get<Is>(args)...);
} }
template <typename T> // call from RT template <typename T> // call from RT
static void messageOutput(FluidSCWrapper* x, const std::string& s, static void messageOutput(SharedState& x, const std::string& s,
MessageResult<T>& result) MessageResult<T>& result)
{ {
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
// allocate return values // allocate return values
index numArgs = ToFloatArray::allocSize(static_cast<T>(result)); index numArgs = ToFloatArray::allocSize(static_cast<T>(result));
if(!x->mNodeAlive) return;
float* values = static_cast<float*>( float* values = static_cast<float*>(
ft->fRTAlloc(x->mWorld, asUnsigned(numArgs) * sizeof(float))); ft->fRTAlloc(x->mNode->mWorld, asUnsigned(numArgs) * sizeof(float)));
// copy return data // copy return data
ToFloatArray::convert(values, static_cast<T>(result)); ToFloatArray::convert(values, static_cast<T>(result));
ft->fSendNodeReply(&x->mParent->mNode, -1, s.c_str(), ft->fSendNodeReply(x->mNode, -1, s.c_str(),
static_cast<int>(numArgs), values); static_cast<int>(numArgs), values);
} }
static void messageOutput(FluidSCWrapper* x, const std::string& s, static void messageOutput(SharedState& x, const std::string& s,
MessageResult<void>&) MessageResult<void>&)
{ {
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
ft->fSendNodeReply(&x->mParent->mNode, -1, s.c_str(), 0, nullptr); if(!x->mNodeAlive) return;
ft->fSendNodeReply(x->mNode, -1, s.c_str(), 0, nullptr);
} }
template <typename... Ts> template <typename... Ts>
static void messageOutput(FluidSCWrapper* x, const std::string& s, static void messageOutput(SharedState& x, const std::string& s,
MessageResult<std::tuple<Ts...>>& result) MessageResult<std::tuple<Ts...>>& result)
{ {
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
std::array<index, sizeof...(Ts)> offsets; std::array<index, sizeof...(Ts)> offsets;
index numArgs; index numArgs;
if(!x->mNodeAlive) return;
std::tie(offsets, numArgs) = std::tie(offsets, numArgs) =
ToFloatArray::allocSize(static_cast<std::tuple<Ts...>>(result)); ToFloatArray::allocSize(static_cast<std::tuple<Ts...>>(result));
float* values = static_cast<float*>( float* values = static_cast<float*>(
ft->fRTAlloc(x->mWorld, asUnsigned(numArgs) * sizeof(float))); ft->fRTAlloc(x->mNode->mWorld, asUnsigned(numArgs) * sizeof(float)));
ToFloatArray::convert(values, std::tuple<Ts...>(result), offsets, ToFloatArray::convert(values, std::tuple<Ts...>(result), offsets,
std::index_sequence_for<Ts...>()); std::index_sequence_for<Ts...>());
ft->fSendNodeReply(&x->mParent->mNode, -1, s.c_str(), ft->fSendNodeReply(x->mNode, -1, s.c_str(),
static_cast<int>(numArgs), values); static_cast<int>(numArgs), values);
} }
@ -1464,14 +1471,14 @@ public:
return p; return p;
} }
static void printResult(FluidSCWrapper* x, Result& r) static void printResult(SharedState& x, Result& r)
{ {
if (!x) return; if (!x.get() || !x->mNodeAlive) return;
switch (r.status()) switch (r.status())
{ {
case Result::Status::kWarning: { case Result::Status::kWarning: {
if (x->mWorld->mVerbosity > 0) if (x->mNode->mWorld->mVerbosity > 0)
std::cout << "WARNING: " << r.message().c_str() << '\n'; std::cout << "WARNING: " << r.message().c_str() << '\n';
break; break;
} }

Loading…
Cancel
Save