Add acksync helper to wait for acks
This will allow to send requests with sequence numbers to the server and wait for acknowledgements. PR #2814 <https://github.com/Genymobile/scrcpy/pull/2814>
This commit is contained in:
76
app/src/util/acksync.c
Normal file
76
app/src/util/acksync.c
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "acksync.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "util/log.h"
|
||||
|
||||
bool
|
||||
sc_acksync_init(struct sc_acksync *as) {
|
||||
bool ok = sc_mutex_init(&as->mutex);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ok = sc_cond_init(&as->cond);
|
||||
if (!ok) {
|
||||
sc_mutex_destroy(&as->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
as->stopped = false;
|
||||
as->ack = SC_SEQUENCE_INVALID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
sc_acksync_destroy(struct sc_acksync *as) {
|
||||
sc_cond_destroy(&as->cond);
|
||||
sc_mutex_destroy(&as->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
sc_acksync_ack(struct sc_acksync *as, uint64_t sequence) {
|
||||
sc_mutex_lock(&as->mutex);
|
||||
|
||||
// Acknowledgements must be monotonic
|
||||
assert(sequence >= as->ack);
|
||||
|
||||
as->ack = sequence;
|
||||
sc_cond_signal(&as->cond);
|
||||
|
||||
sc_mutex_unlock(&as->mutex);
|
||||
}
|
||||
|
||||
enum sc_acksync_wait_result
|
||||
sc_acksync_wait(struct sc_acksync *as, uint64_t ack, sc_tick deadline) {
|
||||
sc_mutex_lock(&as->mutex);
|
||||
|
||||
bool timed_out = false;
|
||||
while (!as->stopped && as->ack < ack && !timed_out) {
|
||||
timed_out = !sc_cond_timedwait(&as->cond, &as->mutex, deadline);
|
||||
}
|
||||
|
||||
enum sc_acksync_wait_result ret;
|
||||
if (as->stopped) {
|
||||
ret = SC_ACKSYNC_WAIT_INTR;
|
||||
} else if (as->ack >= ack) {
|
||||
ret = SC_ACKSYNC_WAIT_OK;
|
||||
} else {
|
||||
assert(timed_out);
|
||||
ret = SC_ACKSYNC_WAIT_TIMEOUT;
|
||||
}
|
||||
sc_mutex_unlock(&as->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt any `sc_acksync_wait()`
|
||||
*/
|
||||
void
|
||||
sc_acksync_interrupt(struct sc_acksync *as) {
|
||||
sc_mutex_lock(&as->mutex);
|
||||
as->stopped = true;
|
||||
sc_cond_signal(&as->cond);
|
||||
sc_mutex_unlock(&as->mutex);
|
||||
}
|
||||
Reference in New Issue
Block a user