<commit_before>#include "mavlink_commands.h"
#include "device_impl.h"
#include <future>
#include <memory>

namespace dronelink {

MavlinkCommands::MavlinkCommands(DeviceImpl *parent) :
    _parent(parent)
{
    _parent->register_mavlink_message_handler(
        MAVLINK_MSG_ID_COMMAND_ACK,
        std::bind(&MavlinkCommands::receive_command_ack,
                  this, std::placeholders::_1), (void *)this);
}

MavlinkCommands::~MavlinkCommands()
{
    _parent->unregister_all_mavlink_message_handlers((void *)this);
}

MavlinkCommands::Result MavlinkCommands::send_command(uint16_t command,
                                                      const MavlinkCommands::Params params,
                                                      uint8_t target_system_id,
                                                      uint8_t target_component_id)
{
    // Some architectures sadly don't have the promises (yet). Therefore, we have this crude
    // while loop to wait until the async task is done.
#ifdef NO_PROMISES
    {
        std::lock_guard<std::mutex> lock(_promise_mutex);
        // We can't buffer with this implementation.
        if (_promise_state != PromiseState::IDLE) {
            return Result::BUSY;
        }

        _promise_state = PromiseState::BUSY;
        queue_command_async(command, params, target_system_id, target_component_id,
                            std::bind(&MavlinkCommands::_promise_receive_command_result,
                                      this, std::placeholders::_1, std::placeholders::_2));
    }
    while (true) {
        {
            std::lock_guard<std::mutex> lock(_promise_mutex);
            if (_promise_state == PromiseState::DONE) {
                _promise_state = PromiseState::IDLE;
                return _promise_last_result;
            }
        }
        // Check at 100 Hz.
        usleep(10000);
    }
#else
    struct PromiseResult {
        Result result;
        float progress;
    };

    // We wrap the async call with a promise and future.
    std::shared_ptr<std::promise<PromiseResult>> prom =
                                                  std::make_shared<std::promise<PromiseResult>>();

    queue_command_async(command, params, target_system_id, target_component_id,
    [prom](Result result, float progress) {
        PromiseResult promise_result {};
        promise_result.result = result;
        promise_result.progress = progress;
        prom->set_value(promise_result);
    }
                       );

    std::future<PromiseResult> res = prom->get_future();
    while (true) {
        // Block now to wait for result.
        res.wait();

        if (res.get().result == Result::IN_PROGRESS) {
            Debug() << "In progress: " << res.get().progress;
            continue;
        }
        break;
    }
    return res.get().result;
#endif
}

#ifdef NO_PROMISES
void MavlinkCommands::_promise_receive_command_result(Result result, float progress)
{<commit_msg>mavlink_commands: fix segfault with std::move<commit_after>#include "mavlink_commands.h"
#include "device_impl.h"
#include <future>
#include <memory>

namespace dronelink {

MavlinkCommands::MavlinkCommands(DeviceImpl *parent) :
    _parent(parent)
{
    _parent->register_mavlink_message_handler(
        MAVLINK_MSG_ID_COMMAND_ACK,
        std::bind(&MavlinkCommands::receive_command_ack,
                  this, std::placeholders::_1), (void *)this);
}

MavlinkCommands::~MavlinkCommands()
{
    _parent->unregister_all_mavlink_message_handlers((void *)this);
}

MavlinkCommands::Result MavlinkCommands::send_command(uint16_t command,
                                                      const MavlinkCommands::Params params,
                                                      uint8_t target_system_id,
                                                      uint8_t target_component_id)
{
    // Some architectures sadly don't have the promises (yet). Therefore, we have this crude
    // while loop to wait until the async task is done.
#ifdef NO_PROMISES
    {
        std::lock_guard<std::mutex> lock(_promise_mutex);
        // We can't buffer with this implementation.
        if (_promise_state != PromiseState::IDLE) {
            return Result::BUSY;
        }

        _promise_state = PromiseState::BUSY;
        queue_command_async(command, params, target_system_id, target_component_id,
                            std::bind(&MavlinkCommands::_promise_receive_command_result,
                                      this, std::placeholders::_1, std::placeholders::_2));
    }
    while (true) {
        {
            std::lock_guard<std::mutex> lock(_promise_mutex);
            if (_promise_state == PromiseState::DONE) {
                _promise_state = PromiseState::IDLE;
                return _promise_last_result;
            }
        }
        // Check at 100 Hz.
        usleep(10000);
    }
#else
    struct PromiseResult {
        Result result;
        float progress;
    };

    // We wrap the async call with a promise and future.
    std::shared_ptr<std::promise<PromiseResult>> prom =
                                                  std::make_shared<std::promise<PromiseResult>>();

    queue_command_async(command, params, target_system_id, target_component_id,
    [prom](Result result, float progress) {
        PromiseResult promise_result {};
        promise_result.result = result;
        promise_result.progress = progress;
        prom->set_value(promise_result);
    }
                       );

    std::future<PromiseResult> res = prom->get_future();
    while (true) {
        // Block now to wait for result.
        res.wait();

        PromiseResult promise_result = res.get();

        if (promise_result.result == Result::IN_PROGRESS) {
            Debug() << "In progress: " << promise_result.progress;
            continue;
        }
        return promise_result.result;
    }
#endif
}

#ifdef NO_PROMISES
void MavlinkCommands::_promise_receive_command_result(Result result, float progress)
{
{'fraction_non_alphanumeric': 0.0988188321410747, 'fraction_numerical': 0.004990850108135086, 'mean_word_length': 2.182636315510852, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2817128', 'n_tokens_mistral': 1684, 'n_tokens_neox': 1665, 'n_words': 332}