首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是灵活的方法来转换C风格的API来使用带块的lib分派

什么是灵活的方法来转换C风格的API来使用带块的lib分派
EN

Stack Overflow用户
提问于 2015-11-24 17:06:17
回答 1查看 167关注 0票数 1

我有一个用C编写的现有的C API,它大量使用从函数返回的状态代码进行错误处理。我正在尝试理解使用lib分派来处理这种情况的首选方法。

下面是一个示例函数。RETURN_ERROR和相关的宏只调用一个函数,该函数返回错误代码并打印消息。

代码语言:javascript
复制
int
mport_db_prepare(sqlite3 *db, sqlite3_stmt **stmt, const char * fmt, ...)
{
  va_list args;
  char *sql;

  va_start(args, fmt);
  sql = sqlite3_vmprintf(fmt, args);
  va_end(args);

  if (sql == NULL)
    RETURN_ERROR(MPORT_ERR_FATAL, "Couldn't allocate memory for sql statement");

  if (sqlite3_prepare_v2(db, sql, -1, stmt, NULL) != SQLITE_OK) {
    SET_ERRORX(MPORT_ERR_FATAL, "sql error preparing '%s': %s", sql, sqlite3_errmsg(db));
    sqlite3_free(sql);
    RETURN_CURRENT_ERROR;
  }

  sqlite3_free(sql);

  return MPORT_OK;
}

我希望在sql访问位周围使用串行队列,并且知道我可以使用dispatch_sync返回值。然而,我也读到过很多同步调用很容易进入死锁。

对于这样一个接口,最佳实践是什么?用一个处理程序传递一个块以获得成功/失败?我会提供一个dispatch_queue_t参数让完成块在用户指定的队列上运行吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-26 05:47:46

这里有一个你可以使用的样本模板。这是我最喜欢的方法。我在浏览器中直接输入这些内容,所以可能会有一些小错误(请编辑):

代码语言:javascript
复制
typedef void (^completion_block_t)(int error_code);

static dispatch_once_t init_once;
static dispatch_queue_t db_queue;

void perform_init(void __unused *ctx) {
    db_queue = dispatch_queue_create("com.mycompany.db_queue", DISPATCH_QUEUE_SERIAL);
}

void perform_some_async_operation(dispatch_queue_t completion_queue, completion_block_t completion_block) {
    dispatch_once_f(&init_once, NULL, perform_init);

    if (completion_block) {
        completion_block = Block_copy(completion_block)

        if (!completion_queue) {
            completion_queue = dispatch_get_global_queue(qos_class_self(), 0);
        }
    }

    dispatch_async(db_queue, ^{
        int error_code = 0;

        ...

        if (completion_block) {
            dispatch_async(completion_queue, ^{
                completion_block(error_code);
            });
        }
    });
}

注意,如果您还想提供API的同步版本,最好使用异步版本而不是相反的方式来实现。这样,系统可以更好地跟踪优先级继承的依赖关系。例:

代码语言:javascript
复制
int perform_some_sync_operation() {
    dispatch_once_f(&init_once, NULL, perform_init);

    __block int error_code = 0;

    dispatch_sync(db_queue, ^{
        ...
    });

    return error_code;
}

void perform_some_async_operation(dispatch_queue_t completion_queue, completion_block_t completion_block) {
    dispatch_queue_t execution_queue = dispatch_get_global_queue(qos_class_self(), 0);

    if (completion_block) {
        completion_block = Block_copy(completion_block)

        if (!completion_queue) {
            completion_queue = execution_queue;
        }
    }

    dispatch_async(execution_queue, ^{
        int error_code = perform_some_sync_operation();

        if (completion_block) {
            dispatch_async(completion_queue, ^{
                completion_block(error_code);
            });
        }
    });
}

如果您的代码被期望运行在比Yosemite或iOS 8更早的系统上,那么当qos_class_self()不可用时,您将需要一个后备方案。例:

代码语言:javascript
复制
completion_queue = dispatch_get_global_queue(&qos_class_self ? qos_class_self() : DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33899690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档