mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-02-16 02:21:07 +00:00
Improve locking for batched mouse and gamepad sensor events
By unlocking the mutex before we enqueue the new entry, we can avoid the input thread immediately contending on the mutex after the new item wakes it up.
This commit is contained in:
@@ -724,9 +724,14 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) {
|
|||||||
|
|
||||||
// Queue a packet holder if this is the only pending relative mouse event
|
// Queue a packet holder if this is the only pending relative mouse event
|
||||||
if (!currentRelativeMouseState.dirty) {
|
if (!currentRelativeMouseState.dirty) {
|
||||||
|
// Set the dirty flag to claim ownership of inserting the packet holder
|
||||||
|
// and unlock to allow other threads to enqueue or process input.
|
||||||
|
currentRelativeMouseState.dirty = true;
|
||||||
|
PltUnlockMutex(&batchedInputMutex);
|
||||||
|
|
||||||
holder = allocatePacketHolder(0);
|
holder = allocatePacketHolder(0);
|
||||||
if (holder == NULL) {
|
if (holder == NULL) {
|
||||||
PltUnlockMutex(&batchedInputMutex);
|
currentRelativeMouseState.dirty = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,22 +752,21 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) {
|
|||||||
// Remaining fields are set in the input thread based on the latest currentRelativeMouseState values
|
// Remaining fields are set in the input thread based on the latest currentRelativeMouseState values
|
||||||
|
|
||||||
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
||||||
if (err == LBQ_SUCCESS) {
|
if (err != LBQ_SUCCESS) {
|
||||||
currentRelativeMouseState.dirty = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
||||||
Limelog("Input queue reached maximum size limit\n");
|
Limelog("Input queue reached maximum size limit\n");
|
||||||
freePacketHolder(holder);
|
freePacketHolder(holder);
|
||||||
|
|
||||||
|
// We weren't able to insert the entry, so let the next call try again
|
||||||
|
currentRelativeMouseState.dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// There's already a packet holder queued to send this event
|
// There's already a packet holder queued to send this event
|
||||||
|
PltUnlockMutex(&batchedInputMutex);
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PltUnlockMutex(&batchedInputMutex);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,9 +789,14 @@ int LiSendMousePositionEvent(short x, short y, short referenceWidth, short refer
|
|||||||
|
|
||||||
// Queue a packet holder if this is the only pending absolute mouse event
|
// Queue a packet holder if this is the only pending absolute mouse event
|
||||||
if (!currentAbsoluteMouseState.dirty) {
|
if (!currentAbsoluteMouseState.dirty) {
|
||||||
|
// Set the dirty flag to claim ownership of inserting the packet holder
|
||||||
|
// and unlock to allow other threads to enqueue or process input.
|
||||||
|
currentAbsoluteMouseState.dirty = true;
|
||||||
|
PltUnlockMutex(&batchedInputMutex);
|
||||||
|
|
||||||
holder = allocatePacketHolder(0);
|
holder = allocatePacketHolder(0);
|
||||||
if (holder == NULL) {
|
if (holder == NULL) {
|
||||||
PltUnlockMutex(&batchedInputMutex);
|
currentAbsoluteMouseState.dirty = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -803,22 +812,21 @@ int LiSendMousePositionEvent(short x, short y, short referenceWidth, short refer
|
|||||||
// Remaining fields are set in the input thread based on the latest currentAbsoluteMouseState values
|
// Remaining fields are set in the input thread based on the latest currentAbsoluteMouseState values
|
||||||
|
|
||||||
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
||||||
if (err == LBQ_SUCCESS) {
|
if (err != LBQ_SUCCESS) {
|
||||||
currentAbsoluteMouseState.dirty = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
||||||
Limelog("Input queue reached maximum size limit\n");
|
Limelog("Input queue reached maximum size limit\n");
|
||||||
freePacketHolder(holder);
|
freePacketHolder(holder);
|
||||||
|
|
||||||
|
// We weren't able to insert the entry, so let the next call try again
|
||||||
|
currentAbsoluteMouseState.dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// There's already a packet holder queued to send this event
|
// There's already a packet holder queued to send this event
|
||||||
|
PltUnlockMutex(&batchedInputMutex);
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PltUnlockMutex(&batchedInputMutex);
|
|
||||||
|
|
||||||
// This is not thread safe, but it's not a big deal because callers that want to
|
// This is not thread safe, but it's not a big deal because callers that want to
|
||||||
// use LiSendRelativeMotionAsMousePositionEvent() must not mix these function
|
// use LiSendRelativeMotionAsMousePositionEvent() must not mix these function
|
||||||
// without synchronization (otherwise the state of the cursor on the host is
|
// without synchronization (otherwise the state of the cursor on the host is
|
||||||
@@ -1536,9 +1544,14 @@ int LiSendControllerMotionEvent(uint8_t controllerNumber, uint8_t motionType, fl
|
|||||||
|
|
||||||
// Queue a packet holder if this is the only pending sensor event
|
// Queue a packet holder if this is the only pending sensor event
|
||||||
if (!currentGamepadSensorState[controllerNumber][motionType - 1].dirty) {
|
if (!currentGamepadSensorState[controllerNumber][motionType - 1].dirty) {
|
||||||
|
// Set the dirty flag to claim ownership of inserting the packet holder
|
||||||
|
// and unlock to allow other threads to enqueue or process input.
|
||||||
|
currentGamepadSensorState[controllerNumber][motionType - 1].dirty = true;
|
||||||
|
PltUnlockMutex(&batchedInputMutex);
|
||||||
|
|
||||||
holder = allocatePacketHolder(0);
|
holder = allocatePacketHolder(0);
|
||||||
if (holder == NULL) {
|
if (holder == NULL) {
|
||||||
PltUnlockMutex(&batchedInputMutex);
|
currentGamepadSensorState[controllerNumber][motionType - 1].dirty = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1554,22 +1567,21 @@ int LiSendControllerMotionEvent(uint8_t controllerNumber, uint8_t motionType, fl
|
|||||||
// Remaining fields are set in the input thread based on the latest currentGamepadSensorState values
|
// Remaining fields are set in the input thread based on the latest currentGamepadSensorState values
|
||||||
|
|
||||||
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
||||||
if (err == LBQ_SUCCESS) {
|
if (err != LBQ_SUCCESS) {
|
||||||
currentGamepadSensorState[controllerNumber][motionType - 1].dirty = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
||||||
Limelog("Input queue reached maximum size limit\n");
|
Limelog("Input queue reached maximum size limit\n");
|
||||||
freePacketHolder(holder);
|
freePacketHolder(holder);
|
||||||
|
|
||||||
|
// We weren't able to insert the entry, so let the next call try again
|
||||||
|
currentGamepadSensorState[controllerNumber][motionType - 1].dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// There's already a packet holder queued to send this event
|
// There's already a packet holder queued to send this event
|
||||||
|
PltUnlockMutex(&batchedInputMutex);
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PltUnlockMutex(&batchedInputMutex);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user