Browse Source

[2202] Minimal thread interface

To test the Mutexes, we'll need to run threads. So this is mostly to
support some tests for now, but it'll be needed later too.
Michal 'vorner' Vaner 12 years ago
parent
commit
ec9e57a32c
3 changed files with 112 additions and 1 deletions
  1. 2 1
      src/lib/util/threads/Makefile.am
  2. 15 0
      src/lib/util/threads/thread.cc
  3. 95 0
      src/lib/util/threads/thread.h

+ 2 - 1
src/lib/util/threads/Makefile.am

@@ -5,7 +5,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 
 lib_LTLIBRARIES = libb10-threads.la
-libb10_threads_la_SOURCES = lock.h lock.cc
+libb10_threads_la_SOURCES  = lock.h lock.cc
+libb10_threads_la_SOURCES += thread.h thread.cc
 libb10_threads_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
 
 CLEANFILES = *.gcno *.gcda

+ 15 - 0
src/lib/util/threads/thread.cc

@@ -0,0 +1,15 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "thread.h"

+ 95 - 0
src/lib/util/threads/thread.h

@@ -0,0 +1,95 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef B10_THREAD_H
+#define B10_THREAD_H
+
+#include <exceptions/exceptions.h>
+
+#include <boost/noncopyable.hpp>
+#include <boost/function.hpp>
+
+namespace isc {
+namespace util {
+namespace thread {
+
+/// \brief A separate thread.
+///
+/// A thread of execution. When created, starts running in the background.
+/// You can wait for it then or just forget it ever existed and leave it
+/// live peacefully.
+///
+/// The interface is minimalistic for now. We may need to extend it later.
+class Thread : public boost::noncopyable {
+public:
+    /// \brief There's an uncaught exception in a thread.
+    ///
+    /// When a thread terminates because it the main function of the thread
+    /// throws, this one is re-thrown out of wait() and contains the what
+    /// of the original exception.
+    class UncaughtException : public isc::Exception {
+    public:
+        UncaughtException(const char* file, size_t line, const char* what) :
+            Exception(file, line, what)
+        {}
+    };
+    /// \brief Create and start a thread.
+    ///
+    /// Create a new thread and run body inside it.
+    ///
+    /// If you need to pass parameters to body, or return some result, you
+    /// may just want to use boost::bind or alike to store them within the
+    /// body functor.
+    ///
+    /// The body should terminate by exiting the function. If it throws, it
+    /// is considered an error. You should generally catch any exceptions form
+    /// within there and handle them somehow.
+    ///
+    /// \param body The code to run inside the thread.
+    ///
+    /// \throw std::bad_alloc if allocation of the new thread or other resources
+    ///     fails.
+    Thread(boost::function<void()> body);
+    /// \brief Destructor.
+    ///
+    /// It is completely legitimate to destroy the thread without calling
+    /// wait() before. In such case, the thread will just live on until it
+    /// terminates. However, if the thread dies due to exception, for example,
+    /// it's up to you to detect that, no error is reported from this class.
+    ///
+    /// \throw isc::InvalidOperation in the rare case of OS reporting a
+    ///     problem. This should not happen unless you messed up with the raw
+    ///     thread by the low-level API.
+    ~ Thread();
+    /// \brief Wait for the thread to terminate.
+    ///
+    /// Waits until the thread terminates. Must be called at most once.
+    ///
+    /// \throw isc::InvalidOperation if the OS API returns error. This usually
+    ///     mean a programmer error (like two threads trying to wait on each
+    ///     other).
+    /// \throw isc::InvalidOperation calling wait a second time.
+    /// \throw UncaughtException if the thread terminated by throwing an
+    ///     exception instead of just returning from the function.
+    void wait();
+private:
+    class Impl;
+    Impl* impl_;
+};
+
+}
+}
+}
+
+#endif