-
Notifications
You must be signed in to change notification settings - Fork 221
Open
Description
Hello!
This is a continuation of the discussion here: https://groups.google.com/g/open-lighting/c/6yBsDBnpANU
There are two related issues:
StreamingClient::SendDMX()contains a delay in the form ofm_ss->RunOnce():
Lines 141 to 168 in 9604d48
bool StreamingClient::Send(unsigned int universe, uint8_t priority, const DmxBuffer &data) { if (!m_stub || !m_socket->ValidReadDescriptor()) return false; // We select() on the fd here to see if the remove end has closed the // connection. We could skip this and rely on the EPIPE delivered by the // write() below, but that introduces a race condition in the unittests. m_socket_closed = false; m_ss->RunOnce(); if (m_socket_closed) { Stop(); return false; } ola::proto::DmxData request; request.set_universe(universe); request.set_data(data.Get()); request.set_priority(priority); m_stub->StreamDmxData(NULL, &request, NULL, NULL); if (m_socket_closed) { Stop(); return false; } return true; } - Code comments indicate that this is to prevent a race condition, but it has the (probably) unintended consequence of making it impossible to send multiple universes destined for one frame with this method.
- In my tests of sending 24 universes, this call causes the overhead to balloon to 30ms. Removing this call (I did not happen to experience the race but of course that does not mean it does not exist) dropped the overhead to 0ms.
- A method does not currently exist (although it could be implemented) to call
m_ss->RunOnce()only once and then send multiple universes after that would solve this issue.
- The use of
m_ss->RunOnce()to prevent a race is made unclear by the fact that the corresponding API forOlaClientCore::SendDMX()(called byOlaClient::SendDMX()) does not make the same call tom_ss->RunOnce():
Lines 469 to 496 in 9604d48
void OlaClientCore::SendDMX(unsigned int universe, const DmxBuffer &data, const SendDMXArgs &args) { ola::proto::DmxData request; request.set_universe(universe); request.set_data(data.Get()); request.set_priority(args.priority); if (args.callback) { // Full request RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleGeneralAck, controller, reply, args.callback); m_stub->UpdateDmxData(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleGeneralAck(controller, reply, args.callback); } } else if (m_connected) { // stream data m_stub->StreamDmxData(NULL, &request, NULL, NULL); } } - When called without any callback settings, it makes the same exact call to
m_stub->StreamDmxData()as found inStreamingClientbut without callingRunOnce(). - A key difference is that this function is a returns a
voidand not abool, but it is still able to check if the socket is open prior to callingm_stub->StreamDmxData()by checkingm_connected.
- When called without any callback settings, it makes the same exact call to