Introduce os_localtime_r() and os_get_local_time()

Replace localtime() with os_localtime_r() in `eval.c` and `undo.c`.
This commit is contained in:
Felipe Oliveira Carvalho
2014-05-01 20:24:29 -03:00
parent ee62510d4e
commit 151382d533
5 changed files with 51 additions and 21 deletions

View File

@@ -65,6 +65,7 @@
#include "os/job.h"
#include "os/rstream.h"
#include "os/rstream_defs.h"
#include "os/time.h"
#if defined(FEAT_FLOAT)
# include <math.h>
@@ -14163,7 +14164,6 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv)
static void f_strftime(typval_T *argvars, typval_T *rettv)
{
char_u result_buf[256];
struct tm *curtime;
time_t seconds;
char_u *p;
@@ -14174,9 +14174,11 @@ static void f_strftime(typval_T *argvars, typval_T *rettv)
seconds = time(NULL);
else
seconds = (time_t)get_tv_number(&argvars[1]);
curtime = localtime(&seconds);
struct tm curtime;
struct tm *curtime_ptr = os_localtime_r(&seconds, &curtime);
/* MSVC returns NULL for an invalid value of seconds. */
if (curtime == NULL)
if (curtime_ptr == NULL)
rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
else {
vimconv_T conv;
@@ -14189,7 +14191,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv)
p = string_convert(&conv, p, NULL);
if (p != NULL)
(void)strftime((char *)result_buf, sizeof(result_buf),
(char *)p, curtime);
(char *)p, curtime_ptr);
else
result_buf[0] = NUL;

View File

@@ -11,6 +11,7 @@
#include "misc1.h"
#include "types.h"
#include "os/os.h"
#include "os/time.h"
#define USR_LOG_FILE "$HOME/.nvimlog"
@@ -117,23 +118,13 @@ static bool v_do_log_to_file(FILE *log_file, int log_level,
assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL);
// format current timestamp in local time
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) {
struct tm local_time;
if (os_get_localtime(&local_time) == NULL) {
return false;
}
#ifdef UNIX
// localtime() is not thread-safe. POSIX provides localtime_r() as a
// thread-safe version.
struct tm local_time_allocated;
struct tm *local_time = localtime_r(&tv.tv_sec, &local_time_allocated);
#else
// Windows version of localtime() is thread-safe.
// See http://msdn.microsoft.com/en-us/library/bf12f0hc%28VS.80%29.aspx
struct tm *local_time = localtime(&tv.tv_sec); // NOLINT
#endif
char date_time[20];
if (strftime(date_time, sizeof(date_time), "%Y/%m/%d %H:%M:%S",
local_time) == 0) {
&local_time) == 0) {
return false;
}

View File

@@ -1,5 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <sys/time.h>
#include <uv.h>
@@ -59,3 +60,27 @@ static void microdelay(uint64_t microseconds)
uv_mutex_unlock(&delay_mutex);
}
struct tm *os_localtime_r(const time_t *clock, struct tm *result)
{
#ifdef UNIX
// POSIX provides localtime_r() as a thread-safe version of localtime().
return localtime_r(clock, result);
#else
// Windows version of localtime() is thread-safe.
// See http://msdn.microsoft.com/en-us/library/bf12f0hc%28VS.80%29.aspx
struct tm *local_time = localtime(clock); // NOLINT
*result = *local_time;
return result;
#endif
}
struct tm *os_get_localtime(struct tm *result)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) {
return NULL;
}
return os_localtime_r(&tv.tv_sec, result);
}

View File

@@ -19,6 +19,17 @@ void os_delay(uint64_t milliseconds, bool ignoreinput);
/// @param ignoreinput If true, allow a SIGINT to interrupt us
void os_microdelay(uint64_t microseconds, bool ignoreinput);
/// Portable version of POSIX localtime_r()
///
/// @return NULL in case of error
struct tm *os_localtime_r(const time_t *clock, struct tm *result);
/// Obtains the current UNIX timestamp and adjusts it to local time
///
/// @param result Pointer to a 'struct tm' where the result should be placed
/// @return A pointer to a 'struct tm' in the current time zone (the 'result'
/// argument) or NULL in case of error
struct tm *os_get_localtime(struct tm *result);
#endif // NEOVIM_OS_TIME_H

View File

@@ -103,6 +103,7 @@
#include "screen.h"
#include "sha256.h"
#include "os/os.h"
#include "os/time.h"
static long get_undolevel(void);
static void u_unch_branch(u_header_T *uhp);
@@ -2455,16 +2456,16 @@ void ex_undolist(exarg_T *eap)
*/
static void u_add_time(char_u *buf, size_t buflen, time_t tt)
{
struct tm *curtime;
struct tm curtime;
if (time(NULL) - tt >= 100) {
curtime = localtime(&tt);
os_localtime_r(&tt, &curtime);
if (time(NULL) - tt < (60L * 60L * 12L))
/* within 12 hours */
(void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
(void)strftime((char *)buf, buflen, "%H:%M:%S", &curtime);
else
/* longer ago */
(void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime);
(void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", &curtime);
} else
vim_snprintf((char *)buf, buflen, _("%" PRId64 " seconds ago"),
(int64_t)(time(NULL) - tt));