You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift调用耗时C++异步函数及观测WrapperReturnValue变化的方法

Hey there! Let's tackle your questions about handling the time-consuming processFrame_new function and observing changes to WrapperReturnValue—I’ve got you covered with practical, actionable approaches.

1. Calling processFrame_new and Handling Async Results

Since this function takes time to compute, blocking your main thread isn’t ideal. Here are a few solid ways to handle it asynchronously:

Option 1: Use std::async for Future-Based Results

You can launch the function in a separate thread and retrieve results later using a std::future. Since the function uses reference parameters, wrap the output values in a struct to capture them (references can’t be directly stored in a future).

First, define a struct to hold output data:

struct DetectionResult {
    int state;
    int index;
    int x;
    int y;
    int debug;
};

Then wrap and launch the function asynchronously:

#include <future>

// Launch the async task
auto future_result = std::async(std::launch::async, [&](const unsigned char* frame, int w, int h, uint ts) {
    DetectionResult res;
    processFrame_new(frame, w, h, ts, res.state, res.index, res.x, res.y, res.debug);
    return res;
}, frame_i, width_i, height_i, timestamp);

// Later, check if results are ready (no block if not done yet)
if (future_result.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
    DetectionResult result = future_result.get();
    // Use result.state, result.index, etc.
}

If you don’t want to block, periodically check the future’s status or use a callback-based approach below.

Option 2: Thread Pool + Callback Function

For more control (especially with multiple frames), use a thread pool with callbacks. The function triggers a callback with results once processing finishes.

Example with a basic thread pool setup:

// Define a callback type
using DetectionCallback = std::function<void(DetectionResult)>;

// Submit task to thread pool
void submitDetectionTask(const unsigned char* frame, int w, int h, uint ts, DetectionCallback callback) {
    // Assume a thread pool that accepts tasks
    thread_pool.enqueue([=, callback = std::move(callback)]() {
        DetectionResult res;
        processFrame_new(frame, w, h, ts, res.state, res.index, res.x, res.y, res.debug);
        // Trigger callback with results (ensure thread safety if updating UI)
        callback(res);
    });
}

// Usage
submitDetectionTask(frame_i, width_i, height_i, timestamp, [](DetectionResult res) {
    // Handle results here—runs automatically when processing finishes
    std::cout << "State: " << res.state << ", Position: (" << res.x << ", " << res.y << ")\n";
});

Option 3: Thread-Safe Message Queue

In event-driven systems, have the worker thread push results into a queue, then process the queue in your main thread.

#include <queue>
#include <mutex>
#include <condition_variable>

// Thread-safe queue template
template<typename T>
class SafeQueue {
public:
    void push(T value) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_queue.push(std::move(value));
        m_cv.notify_one();
    }

    bool try_pop(T& value) {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (m_queue.empty()) return false;
        value = std::move(m_queue.front());
        m_queue.pop();
        return true;
    }

private:
    std::queue<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable m_cv;
};

// Global or member queue for results
SafeQueue<DetectionResult> result_queue;

// Worker thread function
void processFrameAsync(const unsigned char* frame, int w, int h, uint ts) {
    DetectionResult res;
    processFrame_new(frame, w, h, ts, res.state, res.index, res.x, res.y, res.debug);
    result_queue.push(res);
}

// In main thread loop
while (running) {
    DetectionResult res;
    if (result_queue.try_pop(res)) {
        // Process the new result
    }
    // Handle other main thread tasks
}
2. Observing Changes to WrapperReturnValue

How you observe changes depends on whether the value is accessed by multiple threads. Here are reliable methods:

Option 1: Callback-Based Observation

Add a callback mechanism to the wrapper class to notify listeners whenever the value updates.

class WrapperReturnValue {
public:
    using ChangeCallback = std::function<void(const WrapperReturnValue&)>;

    void setResult(DetectionResult new_val) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_result = new_val;
        // Notify all registered listeners
        for (auto& callback : m_callbacks) {
            callback(*this);
        }
    }

    void addChangeListener(ChangeCallback callback) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_callbacks.push_back(std::move(callback));
    }

    DetectionResult getResult() const {
        std::lock_guard<std::mutex> lock(m_mutex);
        return m_result;
    }

private:
    DetectionResult m_result;
    std::vector<ChangeCallback> m_callbacks;
    mutable std::mutex m_mutex;
};

// Usage
WrapperReturnValue wrapper;
wrapper.addChangeListener([](const WrapperReturnValue& val) {
    DetectionResult res = val.getResult();
    std::cout << "Wrapper updated: State = " << res.state << "\n";
});

// When you get a new detection result, update the wrapper
wrapper.setResult(result_from_processing);

Option 2: Condition Variable for Waitable Updates

If you need to block until the value changes (instead of polling), use a condition variable.

class WrapperReturnValue {
public:
    void setResult(DetectionResult new_val) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_result = new_val;
        m_cv.notify_all();
    }

    DetectionResult waitForUpdate() {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_cv.wait(lock); // Blocks until notify_all() is called
        return m_result;
    }

private:
    DetectionResult m_result;
    std::mutex m_mutex;
    std::condition_variable m_cv;
};

// In a worker thread
DetectionResult updated_val = wrapper.waitForUpdate();
// Process the updated value

Option 3: Atomic Variables (For Simple Types)

If the wrapper holds simple, atomic-compatible types (like individual ints), use std::atomic for safe, lock-free polling.

#include <atomic>

struct WrapperReturnValue {
    std::atomic<int> state;
    std::atomic<int> index;
    std::atomic<int> x;
    std::atomic<int> y;
    std::atomic<int> debug;
};

// In main thread, check for changes periodically
int last_state = wrapper.state.load();
while (running) {
    int current_state = wrapper.state.load();
    if (current_state != last_state) {
        // Value changed—process it
        last_state = current_state;
        int current_x = wrapper.x.load();
        // ... handle other fields
    }
}

Note: This is polling-based, so it’s less efficient than callbacks but simple for straightforward cases.


内容的提问来源于stack exchange,提问作者FuzzzzyBoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:56:14