1. 11 Feb, 2019 8 commits
    • Steffen Müthing's avatar
    • Steffen Müthing's avatar
    • Steffen Müthing's avatar
      Add DestructibleSingletonHolder utility · 2d6c17dd
      Steffen Müthing authored
      DestructibleSingletonHolder is a little utility that helps in building
      singletons that can be created and destroyed multiple times during the lifetime
      of a program. The class holds a unique_ptr to the actual singleton
      implementation and an instance of a factory for allocating that unique_ptr and
      initializing the singleton.
      The class is accompanied by a function template that stores an instance of the
      class in a static variable, which provides for the singleton. This function must
      always be called with the factory function, as it is templated on it. This makes
      it possible to keep the singleton private to a class by using a private static
      member function as the factory.
    • Steffen Müthing's avatar
    • Steffen Müthing's avatar
      [doc] Fix typo · ca9bd55d
      Steffen Müthing authored
    • Steffen Müthing's avatar
      Use localtime_r() if available · 0ddb9737
      Steffen Müthing authored
      That function is reentrant and also saves us one round of memcpy().
    • Steffen Müthing's avatar
      [logging] Improve PatternFormatSink configuration · 183bd02f
      Steffen Müthing authored
      Use a regular member function instead of a static one, and explicitly put the
      name of the class into the function name in case there will be more mixins.
    • Steffen Müthing's avatar
      [logging] Make sure sink pattern arguments live through the {fmt} call · e5284569
      Steffen Müthing authored
      The PatternFormatSink crashes in optimized builds because the arguments
      retrieved from the arguments() function are always invalid. This is due to two
      object lifetime problems:
      - fmt::format_args is only a view onto an externally allocated array of
        type-erased format arguments. We allocated this array in a temporary object of
        type fmt::format_arg_store in arguments(), but that became invalid as soon as
        that function ended.
      - The type-erased format arguments in fmt::format_arg_store only store
        references to existing data, which causes yet another problem, as some of the
        data that we want to provide is returned as temporary objects from the
        LogMessage etc.
      To work around this problem, we need to store both the data and an instance of
      fmt::format_arg_store for the duration of the {fmt} calls in a derived sink.
      This patch adds a new member type `Arguments` for this purpose. Arguments
      stores this data without exposing the details to the user (the object only
      contains two char* buffers for it), which keeps user code away from the code
      bloat of captured lambda functions et. al. Arguments **must** be stored as a
      named variable (to guarantee a sufficient lifetime) and implicitly casts into
      fmt::format_args if used that way.
  2. 09 Feb, 2019 5 commits
  3. 06 Feb, 2019 2 commits
  4. 05 Feb, 2019 10 commits
    • Steffen Müthing's avatar
    • Steffen Müthing's avatar
    • Steffen Müthing's avatar
      Improve {fmt} build system support · 7662b3e4
      Steffen Müthing authored
      - Make it possible to force vendoring
      - Better error message if submodule was not checked out
    • Steffen Müthing's avatar
      Split file logging sink config into two · d9990d22
      Steffen Müthing authored
      There's now a strategy for only logging on rank 0 and one for logging into
      rank-specific files.
    • Steffen Müthing's avatar
      Add NullSink class · 677838be
      Steffen Müthing authored
      NullSink is a sink that just does nothing. Useful if you only want to actually
      log on some ranks, but need the sink under that name to be available everywhere.
    • Steffen Müthing's avatar
    • Steffen Müthing's avatar
      Improve logger factory functions · 2c20ce06
      Steffen Müthing authored
      - Convert stdlib errors into logging exceptions
      - Add a new function `tryLogger()` for components that want to request an
        optionally present default logger.
    • Steffen Müthing's avatar
      Switch to a more useful default logging pattern · 2364ce2c
      Steffen Müthing authored
      This change makes the default stdout and stderr sinks log the relative program
      run time.
    • Steffen Müthing's avatar
      Make basic logging infrastructure reentrant · aa67696d
      Steffen Müthing authored
      When using logging in a multi-threaded program, it would be ideal for most calls
      to be reentrant, avoiding expensive and error-prone locking. While it will in
      general not be possible to get thread-safe sinks without locking (they normally
      have to coordinate parallel access to a shared resource), we can remove some
      roadblocks in the front-end part (logger backend and message formatting).
      The lazy backend item used in the `PatternFormatSink` needs a buffer for storing
      the padded logger for the duration of the formatting operation (in particular,
      the storage needs to be valid after exiting the lambda). Previously this was
      solved by passing an externally owned buffer to the `backend()` function, but
      that is messy because callers have to provide a buffer with sufficient lifetime
      and because it becomes difficult to write a re-entrant caller (for e.g. logging
      in a multithreaded environment).
      So we instead go ahead and create a buffer in the closure, which we then have to
      make `mutable`. As the buffer is normally statically allocated, there shouldn't
      be any performance issues.
      Likewise, `LoggerBackend::handle()` now creates a stack-allocated buffer for
      each message instead of using a globally shared buffer instance.
    • Steffen Müthing's avatar
      [fmt] Make the LazyFormatArgumentFactory work with mutable lambdas · 00ccc346
      Steffen Müthing authored
      Mutable lambdas are movable, but not copyable, so don't try to create a copy.
      Also, as the operator() of a mutable lambda modifies the lambda, we have to
      capture the factory in a mutable variable (which seems useful anyway).
  5. 04 Feb, 2019 15 commits