2

我在多线程应用程序中使用本地时间。

我必须用线程安全的版本替换它,据我了解,它称为 localtime_r。

但是,当我这样做时,由于链接失败,我无法完成构建。

我什至不确定从哪里开始寻找解决方案。

我的系统组件是:

  • 芯片 - STM32(基于 ARM 的皮质)
  • IDE - IAR(意法半导体微控制器的编译器和链接器)
  • 操作系统 - ThreadX

我假设(尽管我不确定)这个函数通常会在与 IDE 一起提供的标准库中提供。我对么?

我是否需要将另一个库添加到我的项目中,或者它是否在项目设置中?

如果没有可行的方法将此函数“导入”到我的代码中,那么对于 localtime 函数的线程安全版本,我还有哪些其他选择?

更新:

我希望避免使用操作系统资源(即互斥体),而是调用一个标准例程,它完全符合“本地时间”的功能,只是没有它使用的静态结构(使其线程不安全)。

我看不出 localtime 一开始就使用静态结构的任何理由,所以我假设相应的 localtime_r 并没有用任何操作系统资源解决它,而只是避免使用静态结构。

如果没有这样的选择是可行的,那么我还不如自己实现它,只是我更喜欢使用已经过正确测试的东西,因为约会系统的“不规则性”。

这里的问题是,如何将 localtime_r' 链接到我的项目中(而不是如何实现 localtime_r)。

谢谢

4

2 回答 2

5

您将需要为 localtime() 创建自己的线程安全包装器,这基本上是实现 localtime_r()。

例如

static TX_MUTEX localtime_lock;
void my_localtime_init(void)
{
  tx_Mutex_create( &localtime_lock, "localtime_lock", TX_INHERIT);
}

struct tm *my_localtime_r(const time_t *tim, struct tm *result)
{
   struct tm *t;

   tx_Mutex_get(&localtime_lock, TX_WAIT_FOREVER);
   t = localtime(tim);
   if (t)
       *result = *t;
   tx_Mutex_put(&localtime_lock);

  return t ? result : NULL;
}

你需要my_localtime_init在启动时打电话给某个地方。

这也意味着您需要用该my_localtime_r函数替换所有地方的所有调用,没有人可以再直接调用 localtime(),因为这可能会导致调用新 my_localtime_r 的代码出现竞争条件。

于 2013-12-28T23:30:51.623 回答
3

如果没有可用的线程安全版本,则必须创建一个具有标准接口localtime_r()但使用互斥锁来确保互斥的版本。我可能会使用相同的名称,但是有一些参数可以使用您总是调用的替代名称,localtime_r如果可用,它会直接调用。

如果您的系统使用与 Pthread 互斥锁不同的互斥锁,则该概念适用;使用本机互斥锁而不是 Pthread 互斥锁。

static pthread_mutex_t mx_localtime_r = PTHREAD_MUTEX_INITIALIZER;

struct tm *localtime_r(const time_t *restrict timer, struct tm *restrict result)
{
    struct tm *r = 0;
    if (pthread_mutex_lock(&mx_localtime_r) == 0)
    {
        r = localtime(timer);
        if (r != 0)
        {
            *result = *r;
            r = result;
        }
        if (pthread_mutex_unlock(&mx_localtime_r) != 0)
            r = 0;
    }
    return r;
}

未编译——测试更少。

如果互斥锁的默认属性不适合您,那么您需要投入更多精力来正确初始化互斥锁。

于 2013-12-28T23:37:08.230 回答