Skip to content

Instantly share code, notes, and snippets.

@amyinorbit
Created March 23, 2025 12:58
Show Gist options
  • Save amyinorbit/dbe1acb3e5ca984c3f82635c4b7935a4 to your computer and use it in GitHub Desktop.
Save amyinorbit/dbe1acb3e5ca984c3f82635c4b7935a4 to your computer and use it in GitHub Desktop.
Thread-safe data access in X-Plane
/*===--------------------------------------------------------------------------------------------===
* xpdata.c
*
* Created by Amy Parent <[email protected]>
* Copyright (c) 2025 Amy Parent. All rights reserved
*
* Licensed under the MIT License
*===--------------------------------------------------------------------------------------------===
*/
#include "xpdata.h"
#include <acfutils/assert.h>
#include <acfutils/dr.h>
#include <acfutils/thread.h>
// This is data that stays in this file and never gets out
// (that's what the static keyword enforces)
// Each bit of data we have is protected by a mutex. Mutexes are a way to ensure that
// only one thread is doing things with a piece of data at a given time.
static mutex_t data_mutex;
static xp_ahrs_t data;
// And this is just a way to get all our dataref objects in the same place, you don't really have
// to do this, that's just how I like to organise my code
static struct {
dr_t ahrs_pitch;
dr_t ahrs_roll;
dr_t ahrs_heading;
dr_t adc_ias;
dr_t adc_tas;
//...
} dr;
static bool is_init = false;
void xp_data_init() {
ASSERT(!is_init);
// Initialise our mutex.
mutex_init(&data_mutex);
// Make sure our saved data is all a known value (0)
BZERO(&data);
// Fetch all our datarefs!
fdr_find(&dr.ahrs_pitch, "...");
fdr_find(&dr.ahrs_roll, "...");
fdr_find(&dr.ahrs_heading, "...");
fdr_find(&dr.adc_ias, "...");
fdr_find(&dr.adc_tas, "...");
// ...
// And mark ourselves as initialised.
is_init = true;
}
void xp_data_fini() {
ASSERT(is_init);
// Clean up our mutex.
mutex_destroy(&data_mutex);
// Mark ourselves as not initialised.
is_init = false;
}
void xp_data_update() {
ASSERT(is_init);
// By "entering" the mutex, we lock it: that means that any other thread that tries to
// enter the mutex will pause until we exit it.
mutex_enter(&data_mutex);
// Now that we know no-one else is touching `data`, we can fetch the values from each
// dataref and store it in there
data.ahrs_pitch = dr_getf(&dr.ahrs_pitch);
data.ahrs_roll = dr_getf(&dr.ahrs_roll);
data.ahrs_heading = dr_getf(&dr.ahrs_heading);
data.adc_ias = dr_getf(&dr.adc_ias);
data.adc_tas = dr_getf(&dr.adc_tas);
// When we're done modifying fields in `data`, we can "exit"/release the mutex
mutex_exit(&data_mutex);
}
void xp_data_get(xp_data_t *out) {
// Since we are about to read from our own copy of data, we need to first enter the mutex!
mutex_enter(&data_mutex);
// Then we can copy our own version of data to `out`
*out = data;
// And release the mutex when we're done so other threads can do things here.
mutex_exit(&data_mutex);
}
/*===--------------------------------------------------------------------------------------------===
* xpdata.h
*
* Created by Amy Parent <[email protected]>
* Copyright (c) 2025 Amy Parent
*
* Licensed under the MIT License
*===--------------------------------------------------------------------------------------------===
*/
#ifndef _XPDATA_H_
#define _XPDATA_H_
#include <stdbool.h>
typedef struct {
float ahrs_pitch;
float ahrs_roll;
float ahrs_heading;
float adc_ias;
float adc_tas;
// ...
} xp_data_t;
// This sets up all the datarefs and all. Call this early, probably in XPluginEnable
void xp_data_init();
// This tears down any data we had to set up. Call this in XPluginDisable.
void xp_data_fini();
// This **must** be called on the X-Plane thread. You probably want to call it every frame
// in a flight loop callback.
void xp_data_update();
// This can be called on any thread, and gives you the data that was obtained from datarefs in
// xp_data_update. The way to call them is:
//
// xp_data_t data = {};
// xp_data_get_data(&data);
// // use the data here!
//
void xp_data_get(xp_data_t *data);
#endif /* ifndef _XPDATA_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment