No more comments from me.
Have not reviewed ..\tests files.

Thanks,
Ramesh.

On 3/23/2016 7:20 PM, Hans Nordebäck wrote:
> Hi Anders,
>
> Minor  comments below. /Thanks HansN
>
> -----Original Message-----
> From: Anders Widell [mailto:[email protected]]
> Sent: den 29 februari 2016 12:42
> To: [email protected]
> Cc: [email protected]
> Subject: [devel] [PATCH 1 of 1] base: Add C++ utility functions [#836]
>
>   Makefile.common                                           |    3 +-
>   configure.ac                                              |    3 +
>   osaf/libs/core/Makefile.am                                |    7 +-
>   osaf/libs/core/cplusplus/Makefile.am                      |   21 +
>   osaf/libs/core/cplusplus/base/Makefile.am                 |   42 ++
>   osaf/libs/core/cplusplus/base/getenv.cc                   |  160 ++++++++
>   osaf/libs/core/cplusplus/base/getenv.h                    |   40 ++
>   osaf/libs/core/cplusplus/base/macros.h                    |   33 +
>   osaf/libs/core/cplusplus/base/process.cc                  |  204 ++++++++++
>   osaf/libs/core/cplusplus/base/process.h                   |  113 +++++
>   osaf/libs/core/cplusplus/base/tests/Makefile.am           |   49 ++
>   osaf/libs/core/cplusplus/base/tests/getenv_test.cc        |  105 +++++
>   osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc      |   32 +
>   osaf/libs/core/cplusplus/base/tests/mock_logtrace.h       |   23 +
>   osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc    |   25 +
>   osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h     |   23 +
>   osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc    |   27 +
>   osaf/libs/core/cplusplus/base/tests/mock_osafassert.h     |   23 +
>   osaf/libs/core/cplusplus/base/tests/time_add_test.cc      |   54 ++
>   osaf/libs/core/cplusplus/base/tests/time_compare_test.cc  |  195 +++++++++
>   osaf/libs/core/cplusplus/base/tests/time_convert_test.cc  |   89 ++++
>   osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc |   52 ++
>   osaf/libs/core/cplusplus/base/time.h                      |  275 
> ++++++++++++++
>   23 files changed, 1594 insertions(+), 4 deletions(-)
>
>
> Add the following C++ utility functions to the base component:
>
> * getenv.h - parsing of environment variables with default values
> * macros.h - selecting behaviour of copy constructors and assignment operators
> * process.h - time supervised execution of programs
> * time.h - conversion to/from POSIX timespec structures
>
> diff --git a/Makefile.common b/Makefile.common
> --- a/Makefile.common
> +++ b/Makefile.common
> @@ -6,7 +6,8 @@ CORE_INCLUDES = \
>       -I$(top_srcdir)/osaf/libs/core/include \
>       -I$(top_srcdir)/osaf/libs/core/leap/include \
>       -I$(top_srcdir)/osaf/libs/core/mds/include \
> -     -I$(top_srcdir)/osaf/libs/core/common/include
> +     -I$(top_srcdir)/osaf/libs/core/common/include \
> +     -I$(top_srcdir)/osaf/libs/core/cplusplus
>   
>   AM_CPPFLAGS = \
>       $(CORE_INCLUDES) \
> diff --git a/configure.ac b/configure.ac
> --- a/configure.ac
> +++ b/configure.ac
> @@ -774,6 +774,9 @@ AC_CONFIG_FILES([
>           osaf/libs/saf/libSaSmf/Makefile
>           osaf/libs/saf/libSaSmf/pkgconfig/Makefile
>           osaf/libs/saf/libSaSmf/pkgconfig/opensaf-smf.pc
> +        osaf/libs/core/cplusplus/Makefile
> +        osaf/libs/core/cplusplus/base/Makefile
> +        osaf/libs/core/cplusplus/base/tests/Makefile
>           osaf/services/Makefile
>           osaf/services/infrastructure/Makefile
>           osaf/services/infrastructure/dtms/Makefile
> diff --git a/osaf/libs/core/Makefile.am b/osaf/libs/core/Makefile.am
> --- a/osaf/libs/core/Makefile.am
> +++ b/osaf/libs/core/Makefile.am
> @@ -18,7 +18,7 @@ include $(top_srcdir)/Makefile.common
>   
>   MAINTAINERCLEANFILES = Makefile.in
>   
> -SUBDIRS = include common leap mbcsv mds
> +SUBDIRS = include common leap mbcsv mds cplusplus
>   
>   LIB_VERSION = 0:2:0
>   
> @@ -30,11 +30,12 @@ libopensaf_core_la_CPPFLAGS = \
>       $(AM_CPPFLAGS)
>   
>   libopensaf_core_la_LDFLAGS = \
> -     -lpthread -ldl -lrt \
> +     -pthread -ldl -lrt -lstdc++ \
>       -version-number $(LIB_VERSION)
>   
>   libopensaf_core_la_LIBADD = \
>       $(top_builddir)/osaf/libs/core/common/libopensaf_common.la \
>       $(top_builddir)/osaf/libs/core/leap/libleap.la \
>       $(top_builddir)/osaf/libs/core/mbcsv/libmbca.la \
> -     $(top_builddir)/osaf/libs/core/mds/libmds.la
> +     $(top_builddir)/osaf/libs/core/mds/libmds.la \
> +     $(top_builddir)/osaf/libs/core/cplusplus/base/libbase.la
> diff --git a/osaf/libs/core/cplusplus/Makefile.am 
> b/osaf/libs/core/cplusplus/Makefile.am
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/Makefile.am
> @@ -0,0 +1,21 @@
> +#      -*- OpenSAF  -*-
> +#
> +# (C) Copyright 2016 The OpenSAF Foundation
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> +# under the GNU Lesser General Public License Version 2.1, February 1999.
> +# The complete license can be accessed from the following location:
> +# http://opensource.org/licenses/lgpl-license.php
> +# See the Copying file included with the OpenSAF distribution for full
> +# licensing terms.
> +#
> +# Author(s): Ericsson AB
> +#
> +
> +include $(top_srcdir)/Makefile.common
> +
> +MAINTAINERCLEANFILES = Makefile.in
> +
> +SUBDIRS = base
> diff --git a/osaf/libs/core/cplusplus/base/Makefile.am 
> b/osaf/libs/core/cplusplus/base/Makefile.am
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/Makefile.am
> @@ -0,0 +1,42 @@
> +#      -*- OpenSAF  -*-
> +#
> +# (C) Copyright 2016 The OpenSAF Foundation
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> +# under the GNU Lesser General Public License Version 2.1, February 1999.
> +# The complete license can be accessed from the following location:
> +# http://opensource.org/licenses/lgpl-license.php
> +# See the Copying file included with the OpenSAF distribution for full
> +# licensing terms.
> +#
> +# Author(s): Ericsson AB
> +#
> +
> +include $(top_srcdir)/Makefile.common
> +
> +MAINTAINERCLEANFILES = Makefile.in
> +
> +DEFAULT_INCLUDES =
> +
> +SUBDIRS = tests
> +
> +noinst_HEADERS = \
> +     getenv.h \
> +     macros.h \
> +     process.h \
> +     time.h
> +
> +noinst_LTLIBRARIES = libbase.la
> +
> +libbase_CXXFLAGS =$(AM_CXXFLAGS)
> +
> +libbase_la_CPPFLAGS = \
> +     $(AM_CPPFLAGS)
> +
> +libbase_la_LDFLAGS = -static
> +
> +libbase_la_SOURCES = \
> +     getenv.cc \
> +     process.cc
> diff --git a/osaf/libs/core/cplusplus/base/getenv.cc 
> b/osaf/libs/core/cplusplus/base/getenv.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/getenv.cc
> @@ -0,0 +1,160 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +#include "base/getenv.h"
>
> [HansN] from c++11 you can used #include <cstdint>
>
> +#include <stdint.h>
> +#include <cerrno>
> +#include <cstdlib>
> +#include <cinttypes>
> +#include <climits>
> +#include <string>
> +#include "logtrace.h"
> +
> +namespace {
> +
> +uint64_t GetEnvUnsigned(const char* environment_variable,
> +                        uint64_t default_value, uint64_t max_value);
> +int64_t GetEnvSigned(const char* environment_variable,
> +                     int64_t default_value, int64_t max_value,
> +                     int64_t min_value);
> +char* RemoveLeadingWhitespace(char* str);
> +
> +} // namespace
> +
> +namespace base {
> +
> +template<>
> +const char* GetEnv<const char*>(const char* environment_variable,
> +    const char* default_value) {
> +  const char* str = getenv(environment_variable);
> +  if (str == nullptr) {
> +    TRACE("%s is not set; using default value '%s'", environment_variable,
> +          default_value);
> +    str = default_value;
> +  } else {
> +    TRACE("%s = '%s'", environment_variable, str);
> +  }
> +  return str;
> +}
> +
> +template<>
> +std::string GetEnv<std::string>(const char* environment_variable,
> +    std::string default_value) {
> +  return GetEnv(environment_variable, default_value.c_str());
> +}
> +
> +template<>
> +uint64_t GetEnv<uint64_t>(const char* environment_variable,
> +                          uint64_t default_value) {
> +  return GetEnvUnsigned(environment_variable, default_value, UINT64_MAX);
> +}
> +
> +template<>
> +uint32_t GetEnv<uint32_t>(const char* environment_variable,
> +                          uint32_t default_value) {
> +  return GetEnvUnsigned(environment_variable, default_value, UINT32_MAX);
> +}
> +
> +template<>
> +uint16_t GetEnv<uint16_t>(const char* environment_variable,
> +                          uint16_t default_value) {
> +  return GetEnvUnsigned(environment_variable, default_value, UINT16_MAX);
> +}
> +
> +template<>
> +int64_t GetEnv<int64_t>(const char* environment_variable,
> +                        int64_t default_value) {
> +  return GetEnvSigned(environment_variable, default_value, INT64_MAX,
> +                       INT64_MIN);
> +}
> +
> +template<>
> +int32_t GetEnv<int32_t>(const char* environment_variable,
> +                        int32_t default_value) {
> +  return GetEnvSigned(environment_variable, default_value, INT32_MAX,
> +                       INT32_MIN);
> +}
> +
> +template<>
> +int16_t GetEnv<int16_t>(const char* environment_variable,
> +                        int16_t default_value) {
> +  return GetEnvSigned(environment_variable, default_value, INT16_MAX,
> +                       INT16_MIN);
> +}
> +
> +} // namespace base
> +
> +namespace {
> +
> +uint64_t GetEnvUnsigned(const char* environment_variable,
> +                        uint64_t default_value, uint64_t max_value) {
> +  char* str = RemoveLeadingWhitespace(getenv(environment_variable));
> +  uint64_t retval = default_value;
> +  if (str != nullptr && *str != '\0') {
> +    errno = 0;
> +    char* endptr;
> +    unsigned long long val = strtoull(str, &endptr, 0);
> +    endptr = RemoveLeadingWhitespace(endptr);
> +    if (errno == 0 && val <= max_value && *endptr == '\0') {
> +      retval = val;
> +      TRACE("%s = %" PRIu64, environment_variable, retval);
> +    } else {
> +      LOG_ER("%s has invalid value '%s'; using default value %" PRIu64,
> +             environment_variable, str, default_value);
> +    }
> +  } else {
> +    TRACE("%s is %s; using default value %" PRIu64, environment_variable,
> +          str == nullptr ? "not set" : "empty", default_value);
> +
> +  }
> +  return retval;
> +}
> +
> +int64_t GetEnvSigned(const char* environment_variable, int64_t default_value,
> +                     int64_t max_value, int64_t min_value) {
> +  char* str = RemoveLeadingWhitespace(getenv(environment_variable));
> +  int64_t retval = default_value;
> +  if (str != nullptr && *str != '\0') {
> +    errno = 0;
> +    char* endptr;
> +    long long val = strtoll(str, &endptr, 0);
> +    endptr = RemoveLeadingWhitespace(endptr);
> +    if (errno == 0 && val >= min_value && val <= max_value && *endptr == 
> '\0') {
> +      retval = val;
> +      TRACE("%s = %" PRId64, environment_variable, retval);
> +    } else {
> +      LOG_ER("%s has invalid value '%s'; using default value %" PRId64,
> +             environment_variable, str, default_value);
> +    }
> +  } else {
> +    TRACE("%s is %s; using default value %" PRId64, environment_variable,
> +          str == nullptr ? "not set" : "empty", default_value);
> +  }
> +  return retval;
> +}
> +
> +char* RemoveLeadingWhitespace(char* str) {
> +  if (str != nullptr) {
> +    while (*str == ' ' || *str == '\t' || *str == '\r' || *str == '\n') 
> ++str;
> +  }
> +  return str;
> +}
> +
> +} // namespace
> diff --git a/osaf/libs/core/cplusplus/base/getenv.h 
> b/osaf/libs/core/cplusplus/base/getenv.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/getenv.h
> @@ -0,0 +1,40 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_GETENV_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_GETENV_H_
> +
> +namespace base {
> +
> +/**
> + * @brief Parse an environment variable with a default value.
> + *
> + * Returns the contents of an environment variable. If the variable is not 
> set
> + * or not possible to parse, the @a default_value will be returned. This is a
> + * template functions, and the return type will be the same as the type of 
> the
> + * @a default_value. Supported types are strings (const char*, std::string), 
> as
> + * well as signed and unsigned integer types. When parsing integers, the
> + * prefixes 0x and 0 are supported for indicating that the number is 
> hexadecimal
> + * or octal, respectively. The parsed value is always logged using the 
> OpenSAF
> + * logtrace functionality, and parse errors are logged to syslog.
> + */
> +template<typename T>
> +T GetEnv(const char* environment_variable, T default_value);
> +
> +} // namespace base
> +
> +#endif       /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_GETENV_H_ */
> diff --git a/osaf/libs/core/cplusplus/base/macros.h 
> b/osaf/libs/core/cplusplus/base/macros.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/macros.h
> @@ -0,0 +1,33 @@
> +/*
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_MACROS_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_MACROS_H_
> +
> +#define USE_DEFAULT_COPY_AND_MOVE_OPERATORS(className) \
> +  className(className&&) = default; \
> +  className(const className&) = default; \
> +  className& operator=(className&&) = default; \
> +  className& operator=(const className&) = default
> +
> +#define DELETE_COPY_AND_MOVE_OPERATORS(className) \
> +  className(className&&) = delete; \
> +  className(const className&) = delete; \
> +  className& operator=(className&&) = delete; \
> +  className& operator=(const className&) = delete
> +
> +#endif /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_MACROS_H_ */
> diff --git a/osaf/libs/core/cplusplus/base/process.cc 
> b/osaf/libs/core/cplusplus/base/process.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/process.cc
> @@ -0,0 +1,204 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +#include "base/process.h"
> +#include <sys/resource.h>
> +#include <sys/wait.h>
> +#include <unistd.h>
> +#include <cerrno>
> +#include <cinttypes>
> +#include <climits>
> +#include <cstdlib>
> +#include <cstring>
> +#include <thread>
> +#include "logtrace.h"
> +#include "base/time.h"
> +
> +namespace {
> [HansN] the static in unnamed namespaces is not necessary
> +static char path_environment_variable[] = "PATH=/usr/local/sbin:" \
> +    "/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
> +}
> +
> +namespace base {
> +
> +Process::Process() :
> +    mutex_{},
> +    timer_id_{},
> +    is_timer_created_{false},
> +    process_group_id_{0} {
> +}
> +
> +Process::~Process() {
> +  StopTimer();
> +}
> +
> +void Process::Kill(int sig_no, const Duration& wait_time) {
> +  std::unique_lock<std::mutex> lock(mutex_);
> [HansN] could be made lock free if using std::atomic instead, e.g.
> std::atomic<pid_t> process_group_id_ {1234};
> pid_t pgid {0};
> pgid = process_group_id_.exchange(pgid);
>
> +  pid_t pgid = process_group_id_;
> +  process_group_id_ = 0;
> +  lock.unlock();
> +  if (pgid > 1) KillProc(-pgid, sig_no, wait_time);
> +}
> +
> +void Process::KillProc(pid_t pid, int sig_no, const Duration& wait_time) {
> +  LOG_NO("Sending signal %d to PID %d", sig_no, (int) pid);
> +  if (kill(pid, sig_no) == 0) {
> +    TimePoint timeout = Clock::now() + wait_time;
> +    for (;;) {
> +      int status;
> +      pid_t wait_pid = waitpid(pid, &status, WNOHANG);
> +      if (wait_pid == (pid_t) -1) {
> +        if (errno == ECHILD) break;
> +        if (errno != EINTR) osaf_abort(pid);
> +      }
> +      if (Clock::now() >= timeout) {
> +        if (sig_no == SIGTERM) {
> +          KillProc(pid, SIGKILL, wait_time);
> +        } else {
> +          LOG_WA("Failed to kill %d", (int) pid);
> +        }
> +        break;
> +      }
> +      if (wait_pid == 0) {
> +        std::this_thread::sleep_for(std::chrono::milliseconds(10));
> +      }
> +    }
> +  } else if (errno == EPERM) {
> +    LOG_WA("kill(%d, %d) failed due to EPERM", (int) pid, sig_no);
> +  } else if (errno != ESRCH) {
> +    osaf_abort(pid);
> +  }
> +}
> +
> +void Process::Execute(int argc, char *argv[], const Duration& timeout) {
> +  struct rlimit rlim;
> +  int nofile = 1024;
> +  char *const env[] = { path_environment_variable, nullptr };
> +
> +  TRACE_ENTER();
> +  osafassert(argc >= 1 && argv[argc] == nullptr);
> +  LOG_NO("Running '%s' with %d argument(s)", argv[0], argc - 1);
> +
> +  if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
> +    if (rlim.rlim_cur != RLIM_INFINITY &&
> +        rlim.rlim_cur <= INT_MAX && (int) rlim.rlim_cur >= 0) {
> +      nofile = rlim.rlim_cur;
> +    } else {
> +      LOG_ER("RLIMIT_NOFILE is out of bounds: %llu",
> +             (unsigned long long) rlim.rlim_cur);
> +    }
> +  } else {
> +    LOG_ER("getrlimit(RLIMIT_NOFILE) failed: %s", strerror(errno));
> +  }
> +
> +  pid_t child_pid = fork();
> +  if (child_pid == 0) {
> +    setpgid(0, 0);
> +    for (int fd = 3; fd < nofile; ++fd) close(fd);
> +    execve(argv[0], argv, env);
> +    _Exit(123);
> +  } else if (child_pid != (pid_t) -1 && child_pid != 1) {
> +    if (setpgid(child_pid, 0) != 0) {
> +      LOG_WA("setpgid(%u, 0) failed: %s",
> +             (unsigned) child_pid, strerror(errno));
> +    }
> +    std::unique_lock<std::mutex> lock(mutex_);
> [HansN] see comment above, std::atomic
> +    process_group_id_ = child_pid;
> +    StartTimer(timeout);
> +    lock.unlock();
> +    int status;
> +    pid_t wait_pid;
> +    do {
> +      wait_pid = waitpid(child_pid, &status, 0);
> +    } while (wait_pid == (pid_t) -1 && errno == EINTR);
> +    lock.lock();
> +    StopTimer();
> +    bool killed = process_group_id_ == 0;
> +    process_group_id_ = 0;
> +    lock.unlock();
> +    bool successful = false;
> +    if (!killed && wait_pid != (pid_t) -1) {
> +      if (!WIFEXITED(status)) {
> +        LOG_ER("'%s' terminated abnormally", argv[0]);
> +      } else if (WEXITSTATUS(status) != 0) {
> +        if (WEXITSTATUS(status) == 123) {
> +          LOG_ER("'%s' could not be executed", argv[0]);
> +        } else {
> +          LOG_ER("'%s' failed with exit code %d", argv[0],
> +                 WEXITSTATUS(status));
> +        }
> +      } else {
> +        LOG_IN("'%s' exited successfully", argv[0]);
> +        successful = true;
> +      }
> +    } else if (!killed) {
> +      LOG_ER("'%s' failed in waitpid(%u): %s",
> +             argv[0], (unsigned) child_pid, strerror(errno));
> +    }
> +    if (!successful) KillProc(-child_pid, SIGTERM, std::chrono::seconds(2));
> +  } else {
> +    LOG_ER("'%s' failed in fork(): %s", argv[0],
> +           strerror(errno));
> +  }
> +  TRACE_LEAVE();
> +}
> +
> +void Process::StartTimer(const Duration& timeout) {
> +  if (timeout != std::chrono::seconds(0)) {
> +    if (!is_timer_created_) {
> +      sigevent event;
> +      event.sigev_notify = SIGEV_THREAD;
> +      event.sigev_value.sival_ptr = this;
> +      event.sigev_notify_function = TimerExpirationEvent;
> +      event.sigev_notify_attributes = nullptr;
> +      int result;
> +      do {
> +        result = timer_create(CLOCK_MONOTONIC, &event, &timer_id_);
> +        if (result == -1 && errno == EAGAIN) {
> +          std::this_thread::sleep_for(std::chrono::milliseconds(10));
> +        }
> +      } while (result == -1 && errno == EAGAIN);
> +      if (result != 0) osaf_abort(result);
> +      is_timer_created_ = true;
> +    }
> +    itimerspec tmrspec;
> +    tmrspec.it_interval = kZeroSeconds;
> +    tmrspec.it_value = DurationToTimespec(timeout);
> +    if (timer_settime(timer_id_, 0, &tmrspec, nullptr) != 0) osaf_abort(0);
> +  } else {
> +    StopTimer();
> +  }
> +}
> +
> +void Process::StopTimer() {
> +  if (is_timer_created_) {
> +    if (timer_delete(timer_id_) != 0) osaf_abort(0);
> +    is_timer_created_ = false;
> +  }
> +}
> +
> +void Process::TimerExpirationEvent(sigval notification_data) {
> +  LOG_ER("Process execution timed out; sending SIGTERM to the process 
> group");
> +  Process* instance = static_cast<Process*>(notification_data.sival_ptr);
> +  instance->Kill(SIGTERM, std::chrono::seconds(2));
> +}
> +
> +} // namespace base
> +
> diff --git a/osaf/libs/core/cplusplus/base/process.h 
> b/osaf/libs/core/cplusplus/base/process.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/process.h
> @@ -0,0 +1,113 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_PROCESS_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_PROCESS_H_
> +
> +#include <csignal>
> [HansN] use #include <cstdint>
> +#include <stdint.h>
> +#include <ctime>
> +#include <chrono>
> +#include <mutex>
> +#include "base/macros.h"
> +
> +namespace base {
> +
> +class Process {
> +  DELETE_COPY_AND_MOVE_OPERATORS(Process);
> + public:
> +  using Duration = std::chrono::steady_clock::duration;
> +  Process();
> +  virtual ~Process();
> +  /**
> +   * @brief Execute a program with a timeout.
> +   *
> +   * Execute a program in a new process group, with the parameters specified 
> in
> +   * @a argc and @a argv (analogous to the parameters taken by the main()
> +   * function). The first index in argv must be the full path to the 
> executable
> +   * file. The rest of the parameters shall specify the arguments to the
> +   * program. In addition, argv[argc] must be a NULL pointer. This function
> +   * blocks until the called program has exited or until the @a timeout 
> expires,
> +   * whichever happens first. If the @a timeout expires, all the processes in
> +   * the new process group of the started program will be killed by calling 
> the
> +   * Kill() method of this class with the SIGTERM signal. A @a timeout of 
> zero
> +   * will give an infinite timeout.
> +   *
> +   * The program will be executed with an empty environment containing just a
> +   * PATH variable with the fixed value set to the following string:
> +   * /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
> +   *
> +   * You should not try to execute several programs concurrently using the 
> same
> +   * instance of this class, since the timeout handling only supports waiting
> +   * for one program at a time.
> +   */
> +  void Execute(int argc, char *argv[], const Duration& timeout);
> +  /**
> +   * @brief Check if there is currently an executing process.
> +   *
> +   * Returns true if there is currently an executing process that was started
> +   * using this instance of the Process class. Note that if the process(es) 
> are
> +   * currently being killed (i.e. because of a call to the Kill() method or
> +   * because the timeout has expired), this method may return false even 
> though
> +   * not all processes have yet been killed.
> +   */
> +  bool is_executing() const {
> +    return process_group_id_ > 1;
> +  }
> +  /**
> +   * @brief Kill the currently executing program.
> +   *
> +   * This function kills the currently executing program by calling the
> +   * KillProc() method on the new process group that was created when 
> starting
> +   * the program.
> +   */
> +  void Kill(int sig_no, const Duration& wait_time);
> +  /**
> +   * @brief Send a signal to a process (group) and wait for it to terminate.
> +   *
> +   * This is a utility function that works in a similar way as the 
> killproc(8)
> +   * command. It sends the signal @a sig_no to the process @a pid, and waits 
> for
> +   * @a wait_time or until the process has terminated, whichever happens
> +   * first. If @a sig_no is SIGTERM and the process does not terminate before
> +   * the @a wait_time have passed, this function will retry by sending 
> SIGKILL
> +   * to @a pid and again waiting @a wait_time for it to terminate.  In the 
> worst
> +   * case, the total wait time can thus be two times @a wait_time when @a 
> sig_no
> +   * is SIGTERM; however, in practice the process will terminate very quickly
> +   * after receiving SIGKILL since this signal cannot be caught, and the the
> +   * total wait time should thus not be much longer than @a wait_time.
> +   *
> +   * It is also possible to use this function to send a signal to a process
> +   * group, by passing a negative value as @a pid (in a similar way as with 
> the
> +   * kill(2) function). In that case, this function will wait until all
> +   * processes in the process group have terminated.
> +   */
> +  static void KillProc(pid_t pid, int sig_no, const Duration& wait_time);
> + private:
> +  using Clock = std::chrono::steady_clock;
> +  using TimePoint = std::chrono::steady_clock::time_point;
> +  void StartTimer(const Duration& timeout);
> +  void StopTimer();
> +  static void TimerExpirationEvent(sigval notification_data);
> +  std::mutex mutex_;
> +  timer_t timer_id_;
> +  bool is_timer_created_;
> +  pid_t process_group_id_;
> +};
> +
> +} // namespace base
> +
> +#endif       /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_PROCESS_H_ */
> diff --git a/osaf/libs/core/cplusplus/base/tests/Makefile.am 
> b/osaf/libs/core/cplusplus/base/tests/Makefile.am
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/Makefile.am
> @@ -0,0 +1,49 @@
> +#      -*- OpenSAF  -*-
> +#
> +# (C) Copyright 2016 The OpenSAF Foundation
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> +# under the GNU Lesser General Public License Version 2.1, February 1999.
> +# The complete license can be accessed from the following location:
> +# http://opensource.org/licenses/lgpl-license.php
> +# See the Copying file included with the OpenSAF distribution for full
> +# licensing terms.
> +#
> +# Author(s): Ericsson AB
> +#
> +
> +include $(top_srcdir)/Makefile.common
> +
> +MAINTAINERCLEANFILES = Makefile.in
> +
> +TESTS = libbase_test
> +
> +check_PROGRAMS = $(TESTS)
> +
> +libbase_test_CXXFLAGS =$(AM_CXXFLAGS)
> +
> +libbase_test_CPPFLAGS = \
> +     $(AM_CPPFLAGS) \
> +     -I$(top_srcdir)/osaf/libs/core/cplusplus \
> +     -I$(GTEST_DIR)/include
> +
> +libbase_test_LDFLAGS = \
> +     -pthread -lrt \
> +     $(top_builddir)/osaf/libs/core/cplusplus/base/libbase_la-getenv.o \
> +     $(top_builddir)/osaf/libs/core/cplusplus/base/libbase_la-process.o
> +
> +libbase_test_SOURCES = \
> +     time_add_test.cc \
> +     time_subtract_test.cc \
> +     time_compare_test.cc \
> +     time_convert_test.cc \
> +     getenv_test.cc \
> +     mock_logtrace.cc \
> +     mock_osafassert.cc \
> +     mock_osaf_abort.cc
> +
> +libbase_test_LDADD = \
> +     $(GTEST_DIR)/lib/libgtest.la \
> +     $(GTEST_DIR)/lib/libgtest_main.la
> diff --git a/osaf/libs/core/cplusplus/base/tests/getenv_test.cc 
> b/osaf/libs/core/cplusplus/base/tests/getenv_test.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/getenv_test.cc
> @@ -0,0 +1,105 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include <cstdlib>
> +#include <cstring>
> +#include "base/getenv.h"
> +#include "gtest/gtest.h"
> +
> +TEST(BaseGetEnv, StringDefault) {
> +  unsetenv("HELLO");
> +  std::string default_value{"DEFAULT_VALUE"};
> +  std::string value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, default_value);
> +}
> +
> +TEST(BaseGetEnv, StringValue) {
> +  setenv("HELLO", "THERE", 1);
> +  std::string default_value{"DEFAULT_VALUE"};
> +  std::string value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, std::string{"THERE"});
> +}
> +
> +TEST(BaseGetEnv, CharDefault) {
> +  unsetenv("HELLO");
> +  const char* default_value{"DEFAULT_VALUE"};
> +  const char* value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(strcmp(value, default_value), 0);
> +}
> +
> +TEST(BaseGetEnv, CharValue) {
> +  setenv("HELLO", "THERE", 1);
> +  const char* default_value{"DEFAULT_VALUE"};
> +  const char* value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(strcmp(value, "THERE"), 0);
> +}
> +
> +TEST(BaseGetEnv, NegativeSignedIntegerDefault) {
> +  unsetenv("HELLO");
> +  int64_t default_value{-1234567890123456789ll};
> +  int64_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, default_value);
> +}
> +
> +TEST(BaseGetEnv, NegativeSignedIntegerValue) {
> +  setenv("HELLO", "-2345678901234567890", 1);
> +  int64_t default_value{-1234567890123456789ll};
> +  int64_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, -2345678901234567890ll);
> +}
> +
> +TEST(BaseGetEnv, PositiveSignedIntegerDefault) {
> +  unsetenv("HELLO");
> +  int64_t default_value{1234567890123456789ll};
> +  int64_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, default_value);
> +}
> +
> +TEST(BaseGetEnv, PositiveSignedIntegerValue) {
> +  setenv("HELLO", "2345678901234567890", 1);
> +  int64_t default_value{1234567890123456789ll};
> +  int64_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, 2345678901234567890ll);
> +}
> +
> +TEST(BaseGetEnv, HexadecimalUnsignedIntegerDefault) {
> +  unsetenv("HELLO");
> +  uint64_t default_value{0xfefefefefefefefeull};
> +  uint64_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, default_value);
> +}
> +
> +TEST(BaseGetEnv, HexadecimalUnsignedIntegerValue) {
> +  setenv("HELLO", "0xabababababababab", 1);
> +  uint64_t default_value{0xfefefefefefefefeull};
> +  uint64_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, 0xababababababababull);
> +}
> +
> +TEST(BaseGetEnv, UnparsableInteger) {
> +  setenv("HELLO", "THERE", 1);
> +  uint32_t default_value{0xfefefefeul};
> +  uint32_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, default_value);
> +}
> +
> +TEST(BaseGetEnv, IntegerWithTrailingGarbage) {
> +  setenv("HELLO", "12ab", 1);
> +  uint32_t default_value{0xcdcdcdcdul};
> +  uint32_t value = base::GetEnv("HELLO", default_value);
> +  EXPECT_EQ(value, default_value);
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc 
> b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc
> @@ -0,0 +1,32 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "mock_logtrace.h"
> +
> +void _logtrace_log(const char *file, unsigned int line, int priority, const 
> char *format, ...) {
> +  (void) file;
> +  (void) line;
> +  (void) priority;
> +  (void) format;
> +}
> +
> +void _logtrace_trace(const char *file, unsigned int line, unsigned int 
> category, const char *format, ...) {
> +  (void) file;
> +  (void) line;
> +  (void) category;
> +  (void) format;
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/mock_logtrace.h 
> b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.h
> @@ -0,0 +1,23 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_LOGTRACE_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_LOGTRACE_H_
> +
> +#include "logtrace.h"
> +
> +#endif
> diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc 
> b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc
> @@ -0,0 +1,25 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "mock_osaf_abort.h"
> +#include <cstdlib>
> +
> +void osaf_abort(long i_cause)
> +{
> +  (void) i_cause;
> +  abort();
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h 
> b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h
> @@ -0,0 +1,23 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAF_ABORT_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAF_ABORT_H_
> +
> +#include "osaf_utility.h"
> +
> +#endif
> diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc 
> b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc
> @@ -0,0 +1,27 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "mock_osafassert.h"
> +#include <cstdlib>
> +
> +void __osafassert_fail(const char *file, int line, const char* func, const 
> char *assertion) {
> +  (void) file;
> +  (void) line;
> +  (void) func;
> +  (void) assertion;
> +  abort();
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osafassert.h 
> b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.h
> @@ -0,0 +1,23 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAFASSERT_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAFASSERT_H_
> +
> +#include "ncsgl_defs.h"
> +
> +#endif
> diff --git a/osaf/libs/core/cplusplus/base/tests/time_add_test.cc 
> b/osaf/libs/core/cplusplus/base/tests/time_add_test.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/time_add_test.cc
> @@ -0,0 +1,54 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/time.h"
> +#include "gtest/gtest.h"
> +
> +static const timespec kTwoDotFourSeconds = { 2, 400000000 };
> +static const timespec kFourDotEightSeconds = { 4, 800000000 };
> +static const timespec kNineDotSixSeconds = { 9, 600000000 };
> +static const timespec number1 = { 576315623, 358743382 };
> +static const timespec number2 = { 1279394477, 719128783 };
> +static const timespec sum = { 1855710101,  77872165 };
> +
> +TEST(BaseTimeAdd, ZeroPlusZero) {
> +  timespec result = base::kZeroSeconds + base::kZeroSeconds;
> +  EXPECT_TRUE(result == base::kZeroSeconds);
> +}
> +
> +TEST(BaseTimeAdd, TwoDotFourAddedWithItself) {
> +  timespec result = kTwoDotFourSeconds;
> +  result += result;
> +  EXPECT_TRUE(result == kFourDotEightSeconds);
> +}
> +
> +TEST(BaseTimeAdd, FourDotEightAddedWithItself) {
> +  timespec result = kFourDotEightSeconds;
> +  result += result;
> +  EXPECT_TRUE(result == kNineDotSixSeconds);
> +}
> +
> +TEST(BaseTimeAdd, AddRandomNumbers) {
> +  timespec result = number1 + number2;
> +  EXPECT_TRUE(result == sum);
> +}
> +
> +TEST(BaseTimeAdd, FirstParameterAndResultAtSameAddress) {
> +  timespec result = number1;
> +  result += number2;
> +  EXPECT_TRUE(result == sum);
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/time_compare_test.cc 
> b/osaf/libs/core/cplusplus/base/tests/time_compare_test.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/time_compare_test.cc
> @@ -0,0 +1,195 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/time.h"
> +#include "gtest/gtest.h"
> +
> +static const timespec kZeroDotNineSeconds = { 0, 900000000 };
> +static const timespec kOneDotOneSeconds = { 1, 100000000 };
> +
> +TEST(BaseTimeCompare, ZeroWithZero) {
> +  EXPECT_FALSE(base::kZeroSeconds < base::kZeroSeconds);
> +  EXPECT_TRUE(base::kZeroSeconds <= base::kZeroSeconds);
> +  EXPECT_TRUE(base::kZeroSeconds == base::kZeroSeconds);
> +  EXPECT_FALSE(base::kZeroSeconds != base::kZeroSeconds);
> +  EXPECT_TRUE(base::kZeroSeconds >= base::kZeroSeconds);
> +  EXPECT_FALSE(base::kZeroSeconds > base::kZeroSeconds);
> +}
> +
> +TEST(BaseTimeCompare, ZeroWithZeroDotOne) {
> +  EXPECT_TRUE(base::kZeroSeconds < base::kOneHundredMilliseconds);
> +  EXPECT_TRUE(base::kZeroSeconds <= base::kOneHundredMilliseconds);
> +  EXPECT_FALSE(base::kZeroSeconds == base::kOneHundredMilliseconds);
> +  EXPECT_TRUE(base::kZeroSeconds != base::kOneHundredMilliseconds);
> +  EXPECT_FALSE(base::kZeroSeconds >= base::kOneHundredMilliseconds);
> +  EXPECT_FALSE(base::kZeroSeconds > base::kOneHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, ZeroDotOneWithZero) {
> +  EXPECT_FALSE(base::kOneHundredMilliseconds < base::kZeroSeconds);
> +  EXPECT_FALSE(base::kOneHundredMilliseconds <= base::kZeroSeconds);
> +  EXPECT_FALSE(base::kOneHundredMilliseconds == base::kZeroSeconds);
> +  EXPECT_TRUE(base::kOneHundredMilliseconds != base::kZeroSeconds);
> +  EXPECT_TRUE(base::kOneHundredMilliseconds >= base::kZeroSeconds);
> +  EXPECT_TRUE(base::kOneHundredMilliseconds > base::kZeroSeconds);
> +}
> +
> +TEST(BaseTimeCompare, ZeroWithOne) {
> +  EXPECT_TRUE(base::kZeroSeconds < base::kOneSecond);
> +  EXPECT_TRUE(base::kZeroSeconds <= base::kOneSecond);
> +  EXPECT_FALSE(base::kZeroSeconds == base::kOneSecond);
> +  EXPECT_TRUE(base::kZeroSeconds != base::kOneSecond);
> +  EXPECT_FALSE(base::kZeroSeconds >= base::kOneSecond);
> +  EXPECT_FALSE(base::kZeroSeconds > base::kOneSecond);
> +}
> +
> +TEST(BaseTimeCompare, OneWithZero) {
> +  EXPECT_FALSE(base::kOneSecond < base::kZeroSeconds);
> +  EXPECT_FALSE(base::kOneSecond <= base::kZeroSeconds);
> +  EXPECT_FALSE(base::kOneSecond == base::kZeroSeconds);
> +  EXPECT_TRUE(base::kOneSecond != base::kZeroSeconds);
> +  EXPECT_TRUE(base::kOneSecond >= base::kZeroSeconds);
> +  EXPECT_TRUE(base::kOneSecond > base::kZeroSeconds);
> +}
> +
> +TEST(BaseTimeCompare, OneWithOne) {
> +  EXPECT_FALSE(base::kOneSecond < base::kOneSecond);
> +  EXPECT_TRUE(base::kOneSecond <= base::kOneSecond);
> +  EXPECT_TRUE(base::kOneSecond == base::kOneSecond);
> +  EXPECT_FALSE(base::kOneSecond != base::kOneSecond);
> +  EXPECT_TRUE(base::kOneSecond >= base::kOneSecond);
> +  EXPECT_FALSE(base::kOneSecond > base::kOneSecond);
> +}
> +
> +TEST(BaseTimeCompare, OneWithOneDotOne) {
> +  EXPECT_TRUE(base::kOneSecond < kOneDotOneSeconds);
> +  EXPECT_TRUE(base::kOneSecond <= kOneDotOneSeconds);
> +  EXPECT_FALSE(base::kOneSecond == kOneDotOneSeconds);
> +  EXPECT_TRUE(base::kOneSecond != kOneDotOneSeconds);
> +  EXPECT_FALSE(base::kOneSecond >= kOneDotOneSeconds);
> +  EXPECT_FALSE(base::kOneSecond > kOneDotOneSeconds);
> +}
> +
> +TEST(BaseTimeCompare, OneDotOneWithOne) {
> +  EXPECT_FALSE(kOneDotOneSeconds < base::kOneSecond);
> +  EXPECT_FALSE(kOneDotOneSeconds <= base::kOneSecond);
> +  EXPECT_FALSE(kOneDotOneSeconds == base::kOneSecond);
> +  EXPECT_TRUE(kOneDotOneSeconds != base::kOneSecond);
> +  EXPECT_TRUE(kOneDotOneSeconds >= base::kOneSecond);
> +  EXPECT_TRUE(kOneDotOneSeconds > base::kOneSecond);
> +}
> +
> +TEST(BaseTimeCompare, ZeroDotNineWithZeroDotNine) {
> +  EXPECT_FALSE(kZeroDotNineSeconds < kZeroDotNineSeconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds <= kZeroDotNineSeconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds == kZeroDotNineSeconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds != kZeroDotNineSeconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds >= kZeroDotNineSeconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds > kZeroDotNineSeconds);
> +}
> +
> +TEST(BaseTimeCompare, ZeroDotNineWithOneDotOne) {
> +  EXPECT_TRUE(kZeroDotNineSeconds < kOneDotOneSeconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds <= kOneDotOneSeconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds == kOneDotOneSeconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds != kOneDotOneSeconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds >= kOneDotOneSeconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds > kOneDotOneSeconds);
> +}
> +
> +TEST(BaseTimeCompare, ZeroDotNineWithZeroDotOne) {
> +  EXPECT_FALSE(kZeroDotNineSeconds < base::kOneHundredMilliseconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds <= base::kOneHundredMilliseconds);
> +  EXPECT_FALSE(kZeroDotNineSeconds == base::kOneHundredMilliseconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds != base::kOneHundredMilliseconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds >= base::kOneHundredMilliseconds);
> +  EXPECT_TRUE(kZeroDotNineSeconds > base::kOneHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, OneDotOneWithZeroDotNine) {
> +  EXPECT_FALSE(kOneDotOneSeconds < kZeroDotNineSeconds);
> +  EXPECT_FALSE(kOneDotOneSeconds <= kZeroDotNineSeconds);
> +  EXPECT_FALSE(kOneDotOneSeconds == kZeroDotNineSeconds);
> +  EXPECT_TRUE(kOneDotOneSeconds != kZeroDotNineSeconds);
> +  EXPECT_TRUE(kOneDotOneSeconds >= kZeroDotNineSeconds);
> +  EXPECT_TRUE(kOneDotOneSeconds > kZeroDotNineSeconds);
> +}
> +
> +TEST(BaseTimeCompare, ZeroDotOneWithZeroDotNine) {
> +  EXPECT_TRUE(base::kOneHundredMilliseconds < kZeroDotNineSeconds);
> +  EXPECT_TRUE(base::kOneHundredMilliseconds <= kZeroDotNineSeconds);
> +  EXPECT_FALSE(base::kOneHundredMilliseconds == kZeroDotNineSeconds);
> +  EXPECT_TRUE(base::kOneHundredMilliseconds != kZeroDotNineSeconds);
> +  EXPECT_FALSE(base::kOneHundredMilliseconds >= kZeroDotNineSeconds);
> +  EXPECT_FALSE(base::kOneHundredMilliseconds > kZeroDotNineSeconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfTwoWithLargestLast) {
> +  EXPECT_EQ(base::Max(kZeroDotNineSeconds, kOneDotOneSeconds),
> +            kOneDotOneSeconds);
> +  EXPECT_EQ(base::Max(base::kOneHundredMilliseconds,
> +                      base::kTwoHundredMilliseconds),
> +            base::kTwoHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfTwoWithLargestFirst) {
> +  EXPECT_EQ(base::Max(kOneDotOneSeconds, kZeroDotNineSeconds),
> +            kOneDotOneSeconds);
> +  EXPECT_EQ(base::Max(base::kTwoHundredMilliseconds,
> +                      base::kOneHundredMilliseconds),
> +            base::kTwoHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfTwoEqual) {
> +  EXPECT_EQ(base::Max(kOneDotOneSeconds, kOneDotOneSeconds),
> +            kOneDotOneSeconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfThreeWithLargestLast) {
> +  EXPECT_EQ(base::Max(kZeroDotNineSeconds, base::kOneSecond,
> +                      kOneDotOneSeconds),
> +            kOneDotOneSeconds);
> +  EXPECT_EQ(base::Max(base::kOneHundredMilliseconds,
> +                      base::kTwoHundredMilliseconds,
> +                      base::kThreeHundredMilliseconds),
> +            base::kThreeHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfThreeWithLargestInTheMiddle) {
> +  EXPECT_EQ(base::Max(kZeroDotNineSeconds, kOneDotOneSeconds,
> +                      base::kOneSecond),
> +            kOneDotOneSeconds);
> +  EXPECT_EQ(base::Max(base::kOneHundredMilliseconds,
> +                      base::kThreeHundredMilliseconds,
> +                      base::kTwoHundredMilliseconds),
> +            base::kThreeHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfThreeWithLargestFirst) {
> +  EXPECT_EQ(base::Max(kOneDotOneSeconds, base::kOneSecond,
> +                      kZeroDotNineSeconds),
> +            kOneDotOneSeconds);
> +  EXPECT_EQ(base::Max(base::kThreeHundredMilliseconds,
> +                      base::kOneHundredMilliseconds,
> +                      base::kTwoHundredMilliseconds),
> +            base::kThreeHundredMilliseconds);
> +}
> +
> +TEST(BaseTimeCompare, MaxOfThreeEqual) {
> +  EXPECT_EQ(base::Max(kOneDotOneSeconds, kOneDotOneSeconds, 
> kOneDotOneSeconds),
> +            kOneDotOneSeconds);
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/time_convert_test.cc 
> b/osaf/libs/core/cplusplus/base/tests/time_convert_test.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/time_convert_test.cc
> @@ -0,0 +1,89 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/time.h"
> +#include "gtest/gtest.h"
> +
> +static const timespec kTimespec = { 1576315623, 358743382 };
> +static const timeval kTimeval = { 1576315623, 358743 };
> +static const timespec kTruncatedTimespec = { 1576315623, 358743000 };
> +
> +TEST(BaseTimeConvert, TimespecToTimeval) {
> +  timeval result = base::TimespecToTimeval(kTimespec);
> +  EXPECT_EQ(result.tv_sec, kTimeval.tv_sec);
> +  EXPECT_EQ(result.tv_usec, kTimeval.tv_usec);
> +}
> +
> +TEST(BaseTimeConvert, TimevalToTimespec) {
> +  EXPECT_EQ(base::TimevalToTimespec(kTimeval), kTruncatedTimespec);
> +}
> +
> +TEST(BaseTimeConvert, MillisToTimespec) {
> +  const timespec expected_result = { 1428499100, 961000000 };
> +  EXPECT_EQ(base::MillisToTimespec(1428499100961ull), expected_result);
> +}
> +
> +TEST(BaseTimeConvert, MicrosToTimespec) {
> +  const timespec expected_result = { 2125428499, 100961000 };
> +  EXPECT_EQ(base::MicrosToTimespec(2125428499100961ull), expected_result);
> +}
> +
> +TEST(BaseTimeConvert, NanosToTimespec) {
> +  const struct timespec expected_result = { 1725125428, 499100961 };
> +  EXPECT_EQ(base::NanosToTimespec(1725125428499100961ull), expected_result);
> +}
> +
> +TEST(BaseTimeConvert, DoubleToTimespec) {
> +  const struct timespec expected_result = { 15714713, 125433700 };
> +  const struct timespec expected_result2 = { -15714714, 874566300 };
> +  EXPECT_EQ(base::DoubleToTimespec(15714713.1254337), expected_result);
> +  EXPECT_EQ(base::DoubleToTimespec(-15714713.1254337), expected_result2);
> +}
> +
> +TEST(BaseTimeConvert, DurationToTimespec) {
> +  const struct timespec expected_result = { 1725125428, 499100961 };
> +  std::chrono::nanoseconds duration{1725125428499100961ull};
> +  EXPECT_EQ(base::DurationToTimespec(duration), expected_result);
> +}
> +
> +TEST(BaseTimeConvert, TimespecToMillis) {
> +  const struct timespec ts = { 1428499100, 961923266 };
> +  EXPECT_EQ(base::TimespecToMillis(ts), 1428499100961ull);
> +}
> +
> +TEST(BaseTimeConvert, TimespecToMicros) {
> +  const struct timespec ts = { 1125428499, 100961923 };
> +  EXPECT_EQ(base::TimespecToMicros(ts), 1125428499100961ull);
> +}
> +
> +TEST(BaseTimeConvert, TimespecToNanos) {
> +  const struct timespec ts = { 1725125428, 499100961 };
> +  EXPECT_EQ(base::TimespecToNanos(ts), 1725125428499100961ull);
> +}
> +
> +TEST(BaseTimeConvert, TimespecToDouble) {
> +  const struct timespec ts = { 15714713, 125433700 };
> +  const struct timespec ts2 = { -15714714, 874566300 };
> +  EXPECT_EQ(base::TimespecToDouble(ts), 15714713.1254337);
> +  EXPECT_EQ(base::TimespecToDouble(ts2), -15714713.1254337);
> +}
> +
> +TEST(BaseTimeConvert, TimespecToDuration) {
> +  const struct timespec ts = { 1725125428, 499100961 };
> +  std::chrono::nanoseconds expected_result{1725125428499100961ull};
> +  EXPECT_EQ(base::TimespecToDuration(ts), expected_result);
> +}
> diff --git a/osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc 
> b/osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc
> @@ -0,0 +1,52 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/time.h"
> +#include "gtest/gtest.h"
> +
> [HansN] perhaps unamed namespaces can be used instead of static?
> +static const timespec kOneDotOneSeconds = { 1, 100000000 };
> +static const timespec kZeroDotTwoSeconds = { 0, 200000000 };
> +static const timespec kZeroDotNineSeconds = { 0, 900000000 };
> +static const timespec number1 = { 1576315623, 358743382 };
> +static const timespec number2 = { 279394477, 639614599 };
> +static const timespec difference = { 1296921145, 719128783 };
> +
> +TEST(BaseTimeSubtract, ZeroMinusZero) {
> +  timespec result = base::kZeroSeconds - base::kZeroSeconds;
> +  EXPECT_TRUE(result == base::kZeroSeconds);
> +}
> +
> +TEST(BaseTimeSubtract, FifteenMinusFive) {
> +  timespec result = base::kFifteenSeconds - base::kFiveSeconds;
> +  EXPECT_TRUE(result == base::kTenSeconds);
> +}
> +
> +TEST(BaseTimeSubtract, OneDotOneMinusZeroDotTwo) {
> +  timespec result = kOneDotOneSeconds - kZeroDotTwoSeconds;
> +  EXPECT_TRUE(result == kZeroDotNineSeconds);
> +}
> +
> +TEST(BaseTimeSubtract, SubtractRandomNumbers) {
> +  timespec result = number1 - number2;
> +  EXPECT_TRUE(result == difference);
> +}
> +
> +TEST(BaseTimeSubtract, FirstParameterAndResultAtSameAddress) {
> +  timespec result = number1;
> +  result -= number2;
> +  EXPECT_TRUE(result == difference);
> +}
> diff --git a/osaf/libs/core/cplusplus/base/time.h 
> b/osaf/libs/core/cplusplus/base/time.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/time.h
> @@ -0,0 +1,275 @@
> +/*
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TIME_H_
> +#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TIME_H_
> +
> +#include <stdint.h>
> +#include <cassert>
> +#include <chrono>
> +#include <climits>
> +#include <ctime>
> +#include "osaf_time.h"
> +
> +static inline bool operator<(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) < 0;
> +}
> +
> +static inline bool operator<=(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) <= 0;
> +}
> +
> +static inline bool operator==(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) == 0;
> +}
> +
> +static inline bool operator!=(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) != 0;
> +}
> +
> +static inline bool operator>=(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) >= 0;
> +}
> +
> +static inline bool operator>(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) > 0;
> +}
> +
> +static inline timespec operator+(const timespec& ts1, const timespec& ts2) {
> +  timespec sum;
> +  osaf_timespec_add(&ts1, &ts2, &sum);
> +  return sum;
> +}
> +
> +static inline timespec operator-(const timespec& ts1, const timespec& ts2) {
> +  timespec difference;
> +  assert(ts1 >= ts2);
> +  osaf_timespec_subtract(&ts1, &ts2, &difference);
> +  return difference;
> +}
> +
> +static inline timespec& operator+=(timespec& ts1, const timespec& ts2) {
> +  osaf_timespec_add(&ts1, &ts2, &ts1);
> +  return ts1;
> +}
> +
> +static inline timespec& operator-=(timespec& ts1, const timespec& ts2) {
> +  assert(ts1 >= ts2);
> +  osaf_timespec_subtract(&ts1, &ts2, &ts1);
> +  return ts1;
> +}
> +
> +namespace base {
> +
> +constexpr static const timespec kZeroSeconds{ 0, 0 };
> +constexpr static const timespec kOneMillisecond{ 0, 1000000 };
> +constexpr static const timespec kTenMilliseconds{ 0, 10000000 };
> +constexpr static const timespec kTwentyMilliseconds{ 0, 20000000 };
> +constexpr static const timespec kThirtyMilliseconds{ 0, 30000000 };
> +constexpr static const timespec kFourtyMilliseconds{ 0, 40000000 };
> +constexpr static const timespec kFiftyMilliseconds{ 0, 50000000 };
> +constexpr static const timespec kOneHundredMilliseconds{ 0, 100000000 };
> +constexpr static const timespec kTwoHundredMilliseconds{ 0, 200000000 };
> +constexpr static const timespec kThreeHundredMilliseconds{ 0, 300000000 };
> +constexpr static const timespec kFourHundredMilliseconds{ 0, 400000000 };
> +constexpr static const timespec kFiveHundredMilliseconds{ 0, 500000000 };
> +constexpr static const timespec kOneSecond{ 1, 0 };
> +constexpr static const timespec kFiveSeconds{ 5, 0 };
> +constexpr static const timespec kTenSeconds{ 10, 0 };
> +constexpr static const timespec kFifteenSeconds{ 15, 0 };
> +constexpr static const timespec kTwentySeconds{ 20, 0 };
> +constexpr static const timespec kTwentyfiveSeconds{ 25, 0 };
> +constexpr static const timespec kThirtySeconds{ 30, 0 };
> +constexpr static const timespec kOneMinute{ 1 * 60, 0 };
> +constexpr static const timespec kFiveMinutes{ 5 * 60, 0 };
> +constexpr static const timespec kTenMinutes{ 10 * 60, 0 };
> +constexpr static const timespec kFifteenMinutes{ 15 * 60, 0 };
> +constexpr static const timespec kTwentyMinutes{ 20 * 60, 0 };
> +constexpr static const timespec kTwentyfiveMinutes{ 25 * 60, 0 };
> +constexpr static const timespec kThirtyMinutes{ 30 * 60, 0 };
> +constexpr static const timespec kOneHour{ 60 * 60, 0 };
> +constexpr static const timespec kTimespecMax{ sizeof(time_t) == 8 ? 
> INT64_MAX :
> +  INT32_MAX, 999999999 };
> +
> +/**
> + *  Read the current value of the system's real-time clock. For more
> + *  information, refer to the POSIX function clock_gettime() and the clock id
> + *  CLOCK_REALTIME.
> + */
> +static inline timespec ReadRealtimeClock() {
> +  timespec ts;
> +  osaf_clock_gettime(CLOCK_REALTIME, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Read the current value of the system's monotonic clock. For more
> + *  information, refer to the POSIX function clock_gettime() and the clock id
> + *  CLOCK_MONOTONIC.
> + */
> +static inline timespec ReadMonotonicClock() {
> +  timespec ts;
> +  osaf_clock_gettime(CLOCK_MONOTONIC, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Suspend execution of the calling thread for the specified @a duration.
> + */
> +static inline void Sleep(const timespec& duration) {
> +  osaf_nanosleep(&duration);
> +}
> +
> +/**
> + *  Convert the specified @a duration to a timespec structure.
> + */
> +template<class Rep, class Period>
> +static inline timespec DurationToTimespec(
> +    const std::chrono::duration<Rep, Period>& duration) {
> +  timespec ts;
> +  std::chrono::nanoseconds nanos = duration;
> +  osaf_nanos_to_timespec(nanos.count(), &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Convert the specified timeval structure to a timespec structure.
> + */
> +static inline timespec TimevalToTimespec(const timeval& tv) {
> +  timespec ts;
> +  osaf_timeval_to_timespec(&tv, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Convert the specified number of @a seconds to a timespec structure.
> + */
> +static inline timespec DoubleToTimespec(double seconds) {
> +  timespec ts;
> +  osaf_double_to_timespec(seconds, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Convert the specified number of @a milliseconds to a timespec structure.
> + */
> +static inline timespec MillisToTimespec(uint64_t milliseconds) {
> +  timespec ts;
> +  osaf_millis_to_timespec(milliseconds, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Convert the specified number of @a microseconds to a timespec structure.
> + */
> +static inline timespec MicrosToTimespec(uint64_t microseconds) {
> +  timespec ts;
> +  osaf_micros_to_timespec(microseconds, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Convert the specified number of @a nanoseconds to a timespec structure.
> + */
> +static inline timespec NanosToTimespec(uint64_t nanoseconds) {
> +  timespec ts;
> +  osaf_nanos_to_timespec(nanoseconds, &ts);
> +  return ts;
> +}
> +
> +/**
> + *  Convert the specified timespec structure @a ts to a duration with 
> nanosecond
> + *  resolution.
> + */
> +static inline std::chrono::nanoseconds TimespecToDuration(const timespec& 
> ts) {
> +  return std::chrono::nanoseconds{osaf_timespec_to_nanos(&ts)};
> +}
> +
> +/**
> + *  Convert the specified timeval structure to a timespec structure.
> + */
> +static inline timeval TimespecToTimeval(const timespec& ts) {
> +  timeval tv;
> +  osaf_timespec_to_timeval(&ts, &tv);
> +  return tv;
> +}
> +
> +/**
> + *  Convert the specified timespec structure @a ts to a double representing 
> time
> + *  in the unit of seconds.
> + */
> +static inline double TimespecToDouble(const timespec& ts) {
> +  return osaf_timespec_to_double(&ts);
> +}
> +
> +/**
> + *  Convert the specified timespec structure @a ts to an integer representing
> + *  time in the unit of milliseconds.
> + */
> +static inline uint64_t TimespecToMillis(const timespec& ts) {
> +  return osaf_timespec_to_millis(&ts);
> +}
> +
> +/**
> + *  Convert the specified timespec structure @a ts to an integer representing
> + *  time in the unit of microseconds.
> + */
> +static inline uint64_t TimespecToMicros(const timespec& ts) {
> +  return osaf_timespec_to_micros(&ts);
> +}
> +
> +/**
> + *  Convert the specified timespec structure @a ts to an integer representing
> + *  time in the unit of nanoseconds.
> + */
> +static inline uint64_t TimespecToNanos(const timespec& ts) {
> +  return osaf_timespec_to_nanos(&ts);
> +}
> +
> +/**
> + *  Return the smallest of the two specified timespec structures.
> + */
> +static inline timespec Min(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) <= 0 ? ts1 : ts2;
> +}
> +
> +/**
> + *  Return the smallest of the three specified timespec structures.
> + */
> +static inline timespec Min(const timespec& ts1, const timespec& ts2,
> +                           const timespec& ts3) {
> +  return osaf_timespec_compare(&ts1, &ts2) <= 0 ? Min(ts1, ts3) : Min(ts2, 
> ts3);
> +}
> +
> +/**
> + *  Return the largest of the two specified timespec structures.
> + */
> +static inline timespec Max(const timespec& ts1, const timespec& ts2) {
> +  return osaf_timespec_compare(&ts1, &ts2) >= 0 ? ts1 : ts2;
> +}
> +
> +/**
> + *  Return the largest of the three specified timespec structures.
> + */
> +static inline timespec Max(const timespec& ts1, const timespec& ts2,
> +                           const timespec& ts3) {
> +  return osaf_timespec_compare(&ts1, &ts2) >= 0 ? Max(ts1, ts3) : Max(ts2, 
> ts3);
> +}
> +
> +} // namespace base
> +
> +#endif /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TIME_H_ */
>
> ------------------------------------------------------------------------------
> Site24x7 APM Insight: Get Deep Visibility into Application Performance
> APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
> Monitor end-to-end web transactions and take corrective actions now
> Troubleshoot faster and improve end-user experience. Signup Now!
> http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
> _______________________________________________
> Opensaf-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/opensaf-devel


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785471&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to