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"
+#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 {
+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_);
+  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_);
+    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>
+#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"
+
+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

Reply via email to