Skip to content

Commit ad0bfaa

Browse files
committed
Use TripleBuffer to set RtClientStates
1 parent 2d040e5 commit ad0bfaa

File tree

1 file changed

+35
-36
lines changed

1 file changed

+35
-36
lines changed

include/ableton/link/Controller.hpp

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#pragma once
2121

2222
#include <ableton/discovery/Service.hpp>
23-
#include <ableton/link/CircularFifo.hpp>
2423
#include <ableton/link/ClientSessionTimelines.hpp>
2524
#include <ableton/link/Gateway.hpp>
2625
#include <ableton/link/GhostXForm.hpp>
@@ -317,24 +316,19 @@ class Controller
317316
// This flag ensures that mRtClientState is only updated after all incoming
318317
// client states were processed
319318
mHasPendingRtClientStates = true;
320-
// This will fail in case the Fifo in the RtClientStateSetter is full. This indicates
321-
// a very high rate of calls to the setter. In this case we ignore one value because
322-
// we expect the setter to be called again soon.
323-
if (mRtClientStateSetter.tryPush(newClientState))
319+
mRtClientStateSetter.push(newClientState);
320+
const auto now = mClock.micros();
321+
// Cache the new timeline and StartStopState for serving back to the client
322+
if (newClientState.timeline)
324323
{
325-
const auto now = mClock.micros();
326324
// Cache the new timeline and StartStopState for serving back to the client
327-
if (newClientState.timeline)
328-
{
329-
// Cache the new timeline and StartStopState for serving back to the client
330-
mRtClientState.timeline = *newClientState.timeline;
331-
mRtClientState.timelineTimestamp = makeRtTimestamp(now);
332-
}
333-
if (newClientState.startStopState)
334-
{
335-
mRtClientState.startStopState = *newClientState.startStopState;
336-
mRtClientState.startStopStateTimestamp = makeRtTimestamp(now);
337-
}
325+
mRtClientState.timeline = *newClientState.timeline;
326+
mRtClientState.timelineTimestamp = makeRtTimestamp(now);
327+
}
328+
if (newClientState.startStopState)
329+
{
330+
mRtClientState.startStopState = *newClientState.startStopState;
331+
mRtClientState.startStopStateTimestamp = makeRtTimestamp(now);
338332
}
339333
}
340334

@@ -581,14 +575,23 @@ class Controller
581575
{
582576
}
583577

584-
bool tryPush(const IncomingClientState clientState)
578+
void push(const IncomingClientState clientState)
585579
{
586-
const auto success = mClientStateFifo.push(clientState);
587-
if (success)
580+
if (clientState.timeline)
581+
{
582+
mTimelineBuffer.write(
583+
std::make_pair(clientState.timelineTimestamp, *clientState.timeline));
584+
}
585+
586+
if (clientState.startStopState)
587+
{
588+
mStartStopStateBuffer.write(*clientState.startStopState);
589+
}
590+
591+
if (clientState.timeline || clientState.startStopState)
588592
{
589593
mCallbackDispatcher.invoke();
590594
}
591-
return success;
592595
}
593596

594597
void processPendingClientStates()
@@ -601,27 +604,23 @@ class Controller
601604
IncomingClientState buildMergedPendingClientState()
602605
{
603606
auto clientState = IncomingClientState{};
604-
while (const auto result = mClientStateFifo.pop())
607+
if (auto tl = mTimelineBuffer.readNew())
605608
{
606-
if (result->timeline)
607-
{
608-
clientState.timeline = result->timeline;
609-
clientState.timelineTimestamp = result->timelineTimestamp;
610-
}
611-
if (result->startStopState)
612-
{
613-
clientState.startStopState = result->startStopState;
614-
}
609+
clientState.timelineTimestamp = (*tl).first;
610+
clientState.timeline = OptionalTimeline{(*tl).second};
611+
}
612+
if (auto sss = mStartStopStateBuffer.readNew())
613+
{
614+
clientState.startStopState = sss;
615615
}
616616
return clientState;
617617
}
618618

619619
Controller& mController;
620-
// Assuming a wake up time of one ms for the threads owned by the CallbackDispatcher
621-
// and the ioService, buffering 16 client states allows to set eight client states
622-
// per ms.
623-
static const std::size_t kBufferSize = 16;
624-
CircularFifo<IncomingClientState, kBufferSize> mClientStateFifo;
620+
// Use separate TripleBuffers for the Timeline and the StartStopState so we read the
621+
// latest set value from either optional.
622+
TripleBuffer<std::pair<std::chrono::microseconds, Timeline>> mTimelineBuffer;
623+
TripleBuffer<ClientStartStopState> mStartStopStateBuffer;
625624
CallbackDispatcher mCallbackDispatcher;
626625
};
627626

0 commit comments

Comments
 (0)