2011-09-06 14 views
30

C++ define las funciones de formato de tiempo en términos de strftime, que requiere un registro de "tiempo descompuesto" struct tm. Sin embargo, los lenguajes C y C++ 03 no proporcionan una forma segura de subprocesos para obtener dicho registro; solo hay un maestro struct tm para todo el programa.C++ 11 alternativa a localtime_r

En C++ 03, esto estuvo más o menos bien, porque el lenguaje no admitía el subprocesamiento múltiple; simplemente admitía plataformas compatibles con subprocesamiento múltiple, que luego proporcionaban instalaciones como POSIX localtime_r.

C++ 11 define también nuevas utilidades de tiempo, que la interfaz con la no averiado time_t tipo, que es lo que se usa para reinicializar el mundial struct tm. Pero obtener un time_t no es el problema.

¿Me está faltando algo o esta tarea todavía requiere dependencia de POSIX?

EDIT: Aquí hay un código de solución. Mantiene compatibilidad con entornos multiproceso que proporcionan ::localtime_r y entornos de subproceso único que proporcionan solo std::localtime. También se puede adaptar fácilmente para verificar otras funciones, como posix::localtime_r o ::localtime_s o lo que quieras.

namespace query { 
    char localtime_r(...); 

    struct has_localtime_r 
     { enum { value = sizeof localtime_r(std::declval< std::time_t * >(), std::declval< std::tm * >()) 
         == sizeof(std::tm *) }; }; 


    template< bool available > struct safest_localtime { 
     static std::tm *call(std::time_t const *t, std::tm *r) 
      { return localtime_r(t, r); } 
    }; 

    template<> struct safest_localtime<false> { 
     static std::tm *call(std::time_t const *t, std::tm *r) 
      { return std::localtime(t); } 
    }; 
} 
std::tm *localtime(std::time_t const *t, std::tm *r) 
    { return query::safest_localtime<query::has_localtime_r::value>().call(t, r); } 
+0

¿No puede simplemente envolver 'localtime' en una función que utiliza un mutex? ¿O alguna otra forma de cerradura más liviana? No veo cómo se requiere POSIX aquí. –

+7

@Nicol: Sí, pero eso solo es seguro mientras nadie más intente hacer lo mismo. En otras palabras, funciona en un programa, no en una biblioteca. – Potatoswatter

+0

Pero entonces estarían llamando a una función no segura para subprocesos de un código de subproceso, para que obtengan lo que se merecen. Simplemente podría exponer una función para que la usen, y si usan la C estándar en su lugar, entonces obtendrán un comportamiento indefinido. –

Respuesta

17

No le falta nada.

El próximo estándar C (probablemente debido a cabo este año) no se han definido en el Anexo K:

struct tm *localtime_s(const time_t * restrict timer, 
         struct tm * restrict result); 

Y esta nueva función es seguro para subprocesos! Pero no te pongas muy feliz. Hay dos problemas principales:

  1. localtime_s es un opcional extensión a C11.

  2. C++ 11 referencias C99, no C11. local_time_s no se encuentra en C++ 11, opcional o no.

actualización

En los 4 años que no respondieron a esta pregunta, también se han visto frustrados por el mal diseño de herramientas de C++ en esta área. Me motivó para crear modernas herramientas de C++ para hacer frente a esto:

http://howardhinnant.github.io/date/tz.html

#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    auto local_time = make_zoned(current_zone(), std::chrono::system_clock::now()); 
    std::cout << local_time << '\n'; 
} 

Esto acaba de salida para mí:

28/10/2015 14: 17: 31.980135 EDT

local_time es un emparejamiento de std::chrono::system_clock::time_point y time_zone que indica la hora local.

Existen utilidades para dividir el std::chrono::system_clock::time_point en tipos de campo legibles por el ser humano, como año, mes, día, hora, minuto, segundo y subsegundos.Aquí está una presentación sobre los (no zona horaria) piezas:

https://www.youtube.com/watch?v=tzyGjOm8AKo

Todo esto es de hilo curso seguro (es moderno C++).

+0

... ¡Y cambiaron el nombre! Gracias por la info. Es posible, de todos modos, consultar si 'localtime_r' está disponible y recurrir a' localtime' de lo contrario. Entonces parece que puedo tener mi torta y comerla también, después de todo. – Potatoswatter