Index: uspace/app/cpptest/main.cpp
===================================================================
--- uspace/app/cpptest/main.cpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/app/cpptest/main.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -121,4 +121,5 @@
     ts.add<std::test::functional_test>();
     ts.add<std::test::algorithm_test>();
+    ts.add<std::test::future_test>();
 
     return ts.run(true) ? 0 : 1;
Index: uspace/lib/cpp/Makefile
===================================================================
--- uspace/lib/cpp/Makefile	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/Makefile	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -47,4 +47,5 @@
 	src/mutex.cpp \
 	src/new.cpp \
+	src/refcount_obj.cpp \
 	src/shared_mutex.cpp \
 	src/stdexcept.cpp \
@@ -63,4 +64,5 @@
 	src/__bits/test/deque.cpp \
 	src/__bits/test/functional.cpp \
+	src/__bits/test/future.cpp \
 	src/__bits/test/list.cpp \
 	src/__bits/test/map.cpp \
Index: uspace/lib/cpp/include/__bits/chrono.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/chrono.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/chrono.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -331,5 +331,5 @@
     {
         using CD = common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>;
-        return CD(CD(lhs.count()) + CD(rhs.count()));
+        return CD(CD(lhs).count() + CD(rhs).count());
     }
 
Index: uspace/lib/cpp/include/__bits/functional/functional.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/functional/functional.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/functional/functional.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -46,5 +46,5 @@
     decltype(auto) invoke(F&& f, Args&&... args)
     {
-        return aux::INVOKE(forward<F>(f)(forward<Args>(args)...));
+        return aux::INVOKE(forward<F>(f),forward<Args>(args)...);
     }
 
Index: uspace/lib/cpp/include/__bits/memory/shared_payload.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/memory/shared_payload.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/memory/shared_payload.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -30,4 +30,5 @@
 #define LIBCPP_BITS_MEMORY_SHARED_PAYLOAD
 
+#include <__bits/refcount_obj.hpp>
 #include <cinttypes>
 #include <utility>
@@ -43,10 +44,4 @@
 namespace std::aux
 {
-    /**
-     * At the moment we do not have atomics, change this
-     * to std::atomic<long> once we do.
-     */
-    using refcount_t = long;
-
     /**
      * This allows us to construct shared_ptr from
@@ -66,19 +61,11 @@
 
     template<class T>
-    class shared_payload_base
+    class shared_payload_base: public aux::refcount_obj
     {
         public:
-            virtual void destroy() = 0;
             virtual T* get() const noexcept = 0;
 
             virtual uint8_t* deleter() const noexcept = 0;
 
-            virtual void increment() noexcept = 0;
-            virtual void increment_weak() noexcept = 0;
-            virtual bool decrement() noexcept = 0;
-            virtual bool decrement_weak() noexcept = 0;
-            virtual refcount_t refs() const noexcept = 0;
-            virtual refcount_t weak_refs() const noexcept = 0;
-            virtual bool expired() const noexcept = 0;
             virtual shared_payload_base* lock() noexcept = 0;
 
@@ -91,6 +78,5 @@
         public:
             shared_payload(T* ptr, D deleter = D{})
-                : data_{ptr}, deleter_{deleter},
-                  refcount_{1}, weak_refcount_{1}
+                : data_{ptr}, deleter_{deleter}
             { /* DUMMY BODY */ }
 
@@ -98,5 +84,5 @@
             shared_payload(Args&&... args)
                 : data_{new T{forward<Args>(args)...}},
-                  deleter_{}, refcount_{1}, weak_refcount_{1}
+                  deleter_{}
             { /* DUMMY BODY */ }
 
@@ -104,5 +90,5 @@
             shared_payload(allocator_arg_t, Alloc alloc, Args&&... args)
                 : data_{alloc.allocate(1)},
-                  deleter_{}, refcount_{1}, weak_refcount_{1}
+                  deleter_{}
             {
                 alloc.construct(data_, forward<Args>(args)...);
@@ -112,5 +98,5 @@
             shared_payload(D deleter, Alloc alloc, Args&&... args)
                 : data_{alloc.allocate(1)},
-                  deleter_{deleter}, refcount_{1}, weak_refcount_{1}
+                  deleter_{deleter}
             {
                 alloc.construct(data_, forward<Args>(args)...);
@@ -119,5 +105,5 @@
             void destroy() override
             {
-                if (refs() == 0)
+                if (this->refs() == 0)
                 {
                     if (data_)
@@ -127,5 +113,5 @@
                     }
 
-                    if (weak_refs() == 0)
+                    if (this->weak_refs() == 0)
                         delete this;
                 }
@@ -142,57 +128,10 @@
             }
 
-            void increment() noexcept override
-            {
-                __atomic_add_fetch(&refcount_, 1, __ATOMIC_ACQ_REL);
-            }
-
-            void increment_weak() noexcept override
-            {
-                __atomic_add_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL);
-            }
-
-            bool decrement() noexcept override
-            {
-                if (__atomic_sub_fetch(&refcount_, 1, __ATOMIC_ACQ_REL) == 0)
-                {
-                    /**
-                     * First call to destroy() will delete the held object,
-                     * so it doesn't matter what the weak_refcount_ is,
-                     * but we added one and we need to remove it now.
-                     */
-                    decrement_weak();
-
-                    return true;
-                }
-                else
-                    return false;
-            }
-
-            bool decrement_weak() noexcept override
-            {
-                return __atomic_sub_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL) == 0 && refs() == 0;
-            }
-
-            refcount_t refs() const noexcept override
-            {
-                return __atomic_load_n(&refcount_, __ATOMIC_RELAXED);
-            }
-
-            refcount_t weak_refs() const noexcept override
-            {
-                return __atomic_load_n(&weak_refcount_, __ATOMIC_RELAXED);
-            }
-
-            bool expired() const noexcept override
-            {
-                return refs() == 0;
-            }
-
             shared_payload_base<T>* lock() noexcept override
             {
-                refcount_t rfs = refs();
+                refcount_t rfs = this->refs();
                 while (rfs != 0L)
                 {
-                    if (__atomic_compare_exchange_n(&refcount_, &rfs, rfs + 1,
+                    if (__atomic_compare_exchange_n(&this->refcount_, &rfs, rfs + 1,
                                                     true, __ATOMIC_RELAXED,
                                                     __ATOMIC_RELAXED))
@@ -208,14 +147,4 @@
             T* data_;
             D deleter_;
-
-            /**
-             * We're using a trick where refcount_ > 0
-             * means weak_refcount_ has 1 added to it,
-             * this makes it easier for weak_ptrs that
-             * can't decrement the weak_refcount_ to
-             * zero with shared_ptrs using this object.
-             */
-            refcount_t refcount_;
-            refcount_t weak_refcount_;
     };
 }
Index: uspace/lib/cpp/include/__bits/refcount_obj.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/refcount_obj.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/refcount_obj.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_REFCOUNT_OBJ
+#define LIBCPP_BITS_REFCOUNT_OBJ
+
+namespace std::aux
+{
+    /**
+     * At the moment we do not have atomics, change this
+     * to std::atomic<long> once we do.
+     */
+    using refcount_t = long;
+
+    class refcount_obj
+    {
+        public:
+            refcount_obj() = default;
+
+            void increment() noexcept;
+            void increment_weak() noexcept;
+            bool decrement() noexcept;
+            bool decrement_weak() noexcept;
+            refcount_t refs() const noexcept;
+            refcount_t weak_refs() const noexcept;
+            bool expired() const noexcept;
+
+            virtual ~refcount_obj() = default;
+            virtual void destroy() = 0;
+
+        protected:
+            /**
+             * We're using a trick where refcount_ > 0
+             * means weak_refcount_ has 1 added to it,
+             * this makes it easier for weak_ptrs that
+             * can't decrement the weak_refcount_ to
+             * zero with shared_ptrs using this object.
+             */
+            refcount_t refcount_{1};
+            refcount_t weak_refcount_{1};
+    };
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/result_of.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/result_of.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * Copyright (c) 2018 Jaroslav Jindrak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LIBCPP_BITS_RESULT_OF
-#define LIBCPP_BITS_RESULT_OF
-
-/**
- * TODO: We have two implementations and I can't remember which
- *       one is the correnct one, investigate!
- */
-#include <__bits/invoke.hpp>
-
-namespace std
-{
-    /**
-     * Note: This doesn't work, C++14 standard allows for F
-     *       to be any complete type, our implementation
-     *       currently works like the C++11 version where
-     *       F has to be callable.
-     * TODO: Fix this.
-     */
-
-    template<class>
-    struct result_of;
-
-    template<class F, class... Args>
-    class result_of<F(Args...)>: aux::type_is<
-        decltype(aux::invoke(declval<F>(), declval<ArgTypes>()...))
-    >
-    { /* DUMMY BODY */ };
-
-    template<class T>
-    using result_of_t = typename result_of<T>::type;
-}
-
-#endif
Index: uspace/lib/cpp/include/__bits/system_error.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/system_error.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/system_error.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -33,4 +33,5 @@
 #include <__bits/string/stringfwd.hpp>
 #include <stdexcept>
+#include <type_traits>
 
 namespace std
Index: uspace/lib/cpp/include/__bits/test/tests.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/test/tests.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/test/tests.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2018 Jaroslav Jindrak
+ * Copyright (c) 2019 Jaroslav Jindrak
  * All rights reserved.
  *
@@ -295,4 +295,18 @@
             void test_mutating();
     };
+
+    class future_test: public test_suite
+    {
+        public:
+            bool run(bool) override;
+            const char* name() override;
+        private:
+            void test_future();
+            void test_promise();
+            void test_future_promise();
+            void test_async();
+            void test_packaged_task();
+            void test_shared_future();
+    };
 }
 
Index: uspace/lib/cpp/include/__bits/thread/async.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/async.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/thread/async.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_THREAD_ASYNC
+#define LIBCPP_BITS_THREAD_ASYNC
+
+#include <__bits/thread/future.hpp>
+#include <__bits/thread/future_common.hpp>
+#include <__bits/thread/shared_state.hpp>
+#include <__bits/type_traits/result_of.hpp>
+#include <__bits/utility/forward_move.hpp>
+#include <cassert>
+
+namespace std
+{
+
+    enum class launch
+    {
+        async = 1,
+        deferred
+    };
+
+    namespace aux
+    {
+        /**
+         * Note: The reason we keep the actual function
+         *       within the aux namespace is that were the non-policy
+         *       version of the function call the other one in the std
+         *       namespace, we'd get resolution conflicts. This way
+         *       aux::async is properly called even if std::async is
+         *       called either with or without a launch policy.
+         */
+        template<class F, class... Args>
+        future<result_of_t<decay_t<F>(decay_t<Args>...)>>
+        async(launch policy, F&& f, Args&&... args)
+        {
+            using result_t = result_of_t<decay_t<F>(decay_t<Args>...)>;
+
+            bool async = (static_cast<int>(policy) &
+                          static_cast<int>(launch::async)) != 0;
+            bool deferred = (static_cast<int>(policy) &
+                             static_cast<int>(launch::deferred)) != 0;
+
+            /**
+             * Note: The case when async | deferred is set in policy
+             *       is implementation defined, feel free to change.
+             * Rationale: We chose the 'deferred' policy, because unlike
+             *            the 'async' policy it carries no possible
+             *            surprise ('async' can fail due to thread
+             *            creation error).
+             */
+            if (async && deferred)
+            {
+                return future<result_t>{
+                    new aux::deferred_shared_state<
+                        result_t, F, Args...
+                    >{forward<F>(f), forward<Args>(args)...}
+                };
+            }
+            else if (async)
+            {
+                return future<result_t>{
+                    new aux::async_shared_state<
+                        result_t, F, Args...
+                    >{forward<F>(f), forward<Args>(args)...}
+                };
+            }
+            else if (deferred)
+            {
+               /**
+                * Duplicated on purpose because of the default.
+                * Do not remove!
+                */
+                return future<result_t>{
+                    new aux::deferred_shared_state<
+                        result_t, F, Args...
+                    >{forward<F>(f), forward<Args>(args)...}
+                };
+            }
+
+            /**
+             * This is undefined behaviour, abandon ship!
+             */
+            abort();
+        }
+    }
+
+    template<class F>
+    decltype(auto) async(F&& f)
+    {
+        launch policy = static_cast<launch>(
+            static_cast<int>(launch::async) |
+            static_cast<int>(launch::deferred)
+        );
+
+        return aux::async(policy, forward<F>(f));
+    }
+
+    /**
+     * The async(launch, F, Args...) and async(F, Args...)
+     * overloards must not collide, so we check the first template
+     * argument and handle the special case of just a functor
+     * above.
+     */
+    template<class F, class Arg, class... Args>
+    decltype(auto) async(F&& f, Arg&& arg, Args&&... args)
+    {
+        if constexpr (is_same_v<decay_t<F>, launch>)
+            return aux::async(f, forward<Arg>(arg), forward<Args>(args)...);
+        else
+        {
+            launch policy = static_cast<launch>(
+                static_cast<int>(launch::async) |
+                static_cast<int>(launch::deferred)
+            );
+
+            return aux::async(policy, forward<F>(f), forward<Arg>(arg), forward<Args>(args)...);
+        }
+    }
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/thread/future.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/future.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/thread/future.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -30,156 +30,208 @@
 #define LIBCPP_BITS_THREAD_FUTURE
 
+#include <__bits/thread/future_common.hpp>
+#include <__bits/thread/shared_state.hpp>
+#include <__bits/utility/forward_move.hpp>
 #include <cassert>
-#include <memory>
-#include <system_error>
-#include <type_traits>
 
 namespace std
 {
     /**
-     * 30.6, futures:
+     * 30.6.6, class template future:
      */
 
-    enum class future_errc
-    { // The 5001 start is to not collide with system_error's codes.
-        broken_promise = 5001,
-        future_already_retrieved,
-        promise_already_satisfied,
-        no_state
+    namespace aux
+    {
+        /**
+         * Note: Because of shared_future, this base class
+         *       does implement copy constructor and copy
+         *       assignment operator. This means that the
+         *       children (std::future) need to delete this
+         *       constructor and operator themselves.
+         */
+        template<class R>
+        class future_base
+        {
+            public:
+                future_base() noexcept
+                    : state_{nullptr}
+                { /* DUMMY BODY */ }
+
+                future_base(const future_base& rhs)
+                    : state_{rhs.state_}
+                {
+                    state_->increment();
+                }
+
+                future_base(future_base&& rhs) noexcept
+                    : state_{move(rhs.state_)}
+                {
+                    rhs.state_ = nullptr;
+                }
+
+                future_base(aux::shared_state<R>* state)
+                    : state_{state}
+                {
+                    /**
+                     * Note: This is a custom non-standard constructor that allows
+                     *       us to create a future directly from a shared state. This
+                     *       should never be a problem as aux::shared_state is a private
+                     *       type and future has no constructor templates.
+                     */
+                }
+
+                virtual ~future_base()
+                {
+                    release_state_();
+                }
+
+                future_base& operator=(const future_base& rhs)
+                {
+                    release_state_();
+                    state_ = rhs.state_;
+
+                    state_->increment();
+
+                    return *this;
+                }
+
+                future_base& operator=(future_base&& rhs) noexcept
+                {
+                    release_state_();
+                    state_ = move(rhs.state_);
+                    rhs.state_ = nullptr;
+
+                    return *this;
+                }
+
+                bool valid() const noexcept
+                {
+                    return state_ != nullptr;
+                }
+
+                void wait() const noexcept
+                {
+                    assert(state_);
+
+                    state_->wait();
+                }
+
+                template<class Rep, class Period>
+                future_status
+                wait_for(const chrono::duration<Rep, Period>& rel_time) const
+                {
+                    assert(state_);
+
+                    return state_->wait_for(rel_time);
+                }
+
+                template<class Clock, class Duration>
+                future_status
+                wait_until(
+                    const chrono::time_point<Clock, Duration>& abs_time
+                ) const
+                {
+                    assert(state_);
+
+                    return state_->wait_until(abs_time);
+                }
+
+            protected:
+                void release_state_()
+                {
+                    if (!state_)
+                        return;
+
+                    /**
+                     * Note: This is the 'release' move described in
+                     *       30.6.4 (5).
+                     * Last reference to state -> destroy state.
+                     * Decrement refcount of state otherwise.
+                     * Will not block, unless all following hold:
+                     *  1) State was created by call to std::async.
+                     *  2) State is not yet ready.
+                     *  3) This was the last reference to the shared state.
+                     */
+                    if (state_->decrement())
+                    {
+                        /**
+                         * The destroy call handles the special case
+                         * when 1) - 3) hold.
+                         */
+                        state_->destroy();
+                        delete state_;
+                        state_ = nullptr;
+                    }
+                }
+
+                aux::shared_state<R>* state_;
+        };
+    }
+
+    template<class R>
+    class shared_future;
+
+    template<class R>
+    class future: public aux::future_base<aux::future_inner_t<R>>
+    {
+        friend class shared_future<R>;
+
+        public:
+            future() noexcept
+                : aux::future_base<aux::future_inner_t<R>>{}
+            { /* DUMMY BODY */ }
+
+            future(const future&) = delete;
+
+            future(future&& rhs) noexcept
+                : aux::future_base<aux::future_inner_t<R>>{move(rhs)}
+            { /* DUMMY BODY */ }
+
+            future(aux::shared_state<aux::future_inner_t<R>>* state)
+                : aux::future_base<aux::future_inner_t<R>>{state}
+            { /* DUMMY BODY */ }
+
+            future& operator=(const future&) = delete;
+
+            future& operator=(future&& rhs) noexcept = default;
+
+            shared_future<R> share()
+            {
+                return shared_future<R>{move(*this)};
+            }
+
+            R get()
+            {
+                assert(this->state_);
+
+                this->wait();
+
+                if (this->state_->has_exception())
+                    this->state_->throw_stored_exception();
+
+                if constexpr (!is_same_v<R, void>)
+                {
+                    if constexpr (is_reference_v<R>)
+                    {
+                        assert(this->state_->get());
+
+                        return *this->state_->get();
+                    }
+                    else
+                        return this->state_->get();
+                }
+            }
+
+            /**
+             * Useful for testing as we can check some information
+             * otherwise unavailable to us without waiting, e.g.
+             * to check whether the state is ready, its reference
+             * count etc.
+             */
+            aux::shared_state<aux::future_inner_t<R>>* __state() noexcept
+            {
+                return this->state_;
+            }
     };
-
-    enum class launch
-    {
-        async,
-        deferred
-    };
-
-    enum class future_status
-    {
-        ready,
-        timeout,
-        deferred
-    };
-
-    /**
-     * 30.6.2, error handling:
-     */
-
-    template<>
-    struct is_error_code_enum<future_errc>: true_type
-    { /* DUMMY BODY */ };
-
-    error_code make_error_code(future_errc) noexcept;
-    error_condition make_error_condition(future_errc) noexcept;
-
-    const error_category& future_category() noexcept;
-
-    /**
-     * 30.6.3, class future_error:
-     */
-
-    class future_error: public logic_error
-    {
-        public:
-            future_error(error_code ec);
-
-            const error_code& code() const noexcept;
-
-        private:
-            error_code code_;
-    };
-
-    /**
-     * 30.6.4, shared state:
-     */
-
-    template<class R>
-    class promise
-    {
-    };
-
-    template<class R>
-    class promise<R&>
-    {
-    };
-
-    template<>
-    class promise<void>
-    {
-    };
-
-    template<class R>
-    void swap(promise<R>& lhs, promise<R>& rhs) noexcept
-    {
-        lhs.swap(rhs);
-    }
-
-    template<class R, class Alloc>
-    struct uses_allocator<promise<R>, Alloc>: true_type
-    { /* DUMMY BODY */ };
-
-    template<class R>
-    class future
-    {
-    };
-
-    template<class R>
-    class future<R&>
-    {
-    };
-
-    template<>
-    class future<void>
-    {
-    };
-
-    template<class R>
-    class shared_future
-    {
-    };
-
-    template<class R>
-    class shared_future<R&>
-    {
-    };
-
-    template<>
-    class shared_future<void>
-    {
-    };
-
-    template<class>
-    class packaged_task; // undefined
-
-    template<class R, class... Args>
-    class packaged_task<R(Args...)>
-    {
-    };
-
-    template<class R, class... Args>
-    void swap(packaged_task<R(Args...)>& lhs, packaged_task<R(Args...)>& rhs) noexcept
-    {
-        lhs.swap(rhs);
-    };
-
-    template<class R, class Alloc>
-    struct uses_allocator<packaged_task<R>, Alloc>: true_type
-    { /* DUMMY BODY */ };
-
-    template<class F, class... Args>
-    future<result_of_t<decay_t<F>(decay_t<Args>...)>>
-    async(F&& f, Args&&... args)
-    {
-        // TODO: implement
-        __unimplemented();
-    }
-
-    template<class F, class... Args>
-    future<result_of_t<decay_t<F>(decay_t<Args>...)>>
-    async(launch, F&& f, Args&&... args)
-    {
-        // TODO: implement
-        __unimplemented();
-    }
 }
 
Index: uspace/lib/cpp/include/__bits/thread/future_common.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/future_common.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/thread/future_common.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_THREAD_FUTURE_COMMON
+#define LIBCPP_BITS_THREAD_FUTURE_COMMON
+
+#include <__bits/aux.hpp>
+#include <system_error>
+#include <stdexcept>
+
+namespace std
+{
+    /**
+     * 30.6, futures:
+     */
+
+    enum class future_errc
+    { // The 5001 start is to not collide with system_error's codes.
+        broken_promise = 5001,
+        future_already_retrieved,
+        promise_already_satisfied,
+        no_state
+    };
+
+    enum class future_status
+    {
+        ready,
+        timeout,
+        deferred
+    };
+
+    /**
+     * 30.6.2, error handling:
+     */
+
+    template<>
+    struct is_error_code_enum<future_errc>: true_type
+    { /* DUMMY BODY */ };
+
+    error_code make_error_code(future_errc) noexcept;
+    error_condition make_error_condition(future_errc) noexcept;
+
+    const error_category& future_category() noexcept;
+
+    /**
+     * 30.6.3, class future_error:
+     */
+
+    class future_error: public logic_error
+    {
+        public:
+            future_error(error_code ec);
+
+            const error_code& code() const noexcept;
+            const char* what() const noexcept;
+
+        private:
+            error_code code_;
+    };
+
+    namespace aux
+    {
+        /**
+         * Auxilliary metafunctions that let us avoid
+         * specializations in some cases. They represent
+         * the inner stored type and the return type of
+         * the get() member function, respectively.
+         */
+
+        template<class T>
+        struct future_inner: aux::type_is<T>
+        { /* DUMMY BODY */ };
+
+        template<class T>
+        struct future_inner<T&>: aux::type_is<T*>
+        { /* DUMMY BODY */ };
+
+        template<class T>
+        using future_inner_t = typename future_inner<T>::type;
+
+        template<class T>
+        struct future_return_shared: aux::type_is<const T&>
+        { /* DUMMY BODY */ };
+
+        template<class T>
+        struct future_return_shared<T&>: aux::type_is<T&>
+        { /* DUMMY BODY */ };
+
+        template<>
+        struct future_return_shared<void>: aux::type_is<void>
+        { /* DUMMY BODY */ };
+
+        template<class T>
+        using future_return_shared_t = typename future_return_shared<T>::type;
+    }
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/thread/packaged_task.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/packaged_task.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/thread/packaged_task.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_THREAD_PACKAGED_TASK
+#define LIBCPP_BITS_THREAD_PACKAGED_TASK
+
+#include <__bits/exception.hpp>
+#include <__bits/functional/function.hpp>
+#include <__bits/memory/allocator_traits.hpp>
+#include <__bits/thread/future.hpp>
+#include <__bits/thread/future_common.hpp>
+#include <__bits/thread/shared_state.hpp>
+#include <type_traits>
+#include <utility>
+
+namespace std
+{
+    /**
+     * 30.6.9, class template packaged_task:
+     */
+
+    /**
+     * Note: The base template is not defined because
+     *       we require the template parameter to be
+     *       a callable object (e.g. a function). This
+     *       is achieved by the R(Args...) specialization
+     *       below.
+     */
+    template<class>
+    class packaged_task;
+
+    template<class R, class... Args>
+    class packaged_task<R(Args...)>
+    {
+        public:
+            packaged_task() noexcept
+                : func_{}, state_{}
+            { /* DUMMY BODY */ }
+
+            template<
+                class F, enable_if_t<
+                    !is_same_v<
+                        decay_t<F>, packaged_task<R(Args...)>
+                    >, int
+                > = 0
+            >
+            explicit packaged_task(F&& f)
+                : func_{forward<F>(f)}, state_{new aux::shared_state<R>{}}
+            { /* DUMMY BODY */ }
+
+            template<
+                class F, class Allocator, enable_if_t<
+                    is_same_v<
+                        decay_t<F>, packaged_task<R(Args...)>
+                    >, int
+                > = 0
+            >
+            explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f)
+                : func_{forward<F>(f)}, state_{}
+            {
+                typename allocator_traits<
+                    Allocator
+                >::template rebind_alloc<aux::shared_state<R>> rebound{a};
+
+                state_ = rebound.allocate(1);
+                rebound.construct(state_);
+            }
+
+            ~packaged_task()
+            {
+                if (state_)
+                {
+                    if (!state_->is_set())
+                    {
+                        state_->set_exception(make_exception_ptr(
+                            future_error{make_error_code(future_errc::broken_promise)}
+                        ));
+                        state_->mark_set(true);
+                    }
+
+                    if (state_->decrement())
+                    {
+                        state_->destroy();
+                        delete state_;
+                        state_ = nullptr;
+                    }
+                }
+            }
+
+            packaged_task(const packaged_task&) = delete;
+            packaged_task& operator=(const packaged_task&) = delete;
+
+            packaged_task(packaged_task&& rhs)
+                : func_{move(rhs.func_)}, state_{move(rhs.state_)}
+            { /* DUMMY BODY */ }
+
+            packaged_task& operator=(packaged_task&& rhs)
+            {
+                if (state_)
+                {
+                    if (state_->decrement())
+                    {
+                        state_->destroy();
+                        delete state_;
+                        state_ = nullptr;
+                    }
+                }
+
+                func_ = move(rhs.func_);
+                state_ = move(rhs.state_);
+                rhs.state_ = nullptr;
+
+                return *this;
+            }
+
+            void swap(packaged_task& other) noexcept
+            {
+                std::swap(func_, other.func_);
+                std::swap(state_, other.state_);
+            }
+
+            bool valid() const noexcept
+            {
+                return state_ != nullptr;
+            }
+
+            future<R> get_future()
+            {
+                if (!state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+
+                state_->increment();
+
+                return future<R>{state_};
+            }
+
+            /**
+             * Note: This is how the signature is in the standard,
+             *       should be investigated and verified.
+             */
+            void operator()(Args... args)
+            {
+                if (!state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                try
+                {
+                    state_->set_value(invoke(func_, args...));
+                }
+                catch(const exception& __exception)
+                {
+                    state_->set_exception(make_exception_ptr(__exception));
+                }
+            }
+
+            void make_ready_at_thread_exit(Args... args)
+            {
+                if (!state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                try
+                {
+                    state_->set_value(invoke(func_, args...), false);
+                    aux::set_state_value_at_thread_exit(this->state_);
+                }
+                catch(const exception& __exception)
+                {
+                    state_->set_exception(make_exception_ptr(__exception), false);
+                    aux::set_state_exception_at_thread_exit(this->state_);
+                }
+            }
+
+            void reset()
+            {
+                if (!state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+
+                *this = packaged_task{move(func_)};
+            }
+
+        private:
+            function<R(Args...)> func_;
+
+            aux::shared_state<R>* state_;
+    };
+
+    template<class R, class... Args>
+    void swap(packaged_task<R(Args...)>& lhs, packaged_task<R(Args...)>& rhs) noexcept
+    {
+        lhs.swap(rhs);
+    };
+
+    template<class R, class Alloc>
+    struct uses_allocator<packaged_task<R>, Alloc>: true_type
+    { /* DUMMY BODY */ };
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/thread/promise.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/promise.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/thread/promise.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_THREAD_PROMISE
+#define LIBCPP_BITS_THREAD_PROMISE
+
+#include <__bits/exception.hpp>
+#include <__bits/memory/allocator_traits.hpp>
+#include <__bits/thread/future.hpp>
+#include <__bits/thread/shared_state.hpp>
+#include <__bits/aux.hpp>
+#include <utility>
+
+namespace std
+{
+    /**
+     * 30.6.5, class template promise:
+     */
+
+    namespace aux
+    {
+        template<class R>
+        class promise_base
+        {
+            public:
+                promise_base()
+                    : state_{new aux::shared_state<R>{}}
+                { /* DUMMY BODY */ }
+
+                template<class Allocator>
+                promise_base(allocator_arg_t, const Allocator& a)
+                    : state_{}
+                {
+                    typename allocator_traits<
+                        Allocator
+                    >::template rebind_alloc<aux::shared_state<R>> rebound{a};
+
+                    state_ = rebound.allocate(1);
+                    rebound.construct(state_);
+                }
+
+                promise_base(promise_base&& rhs) noexcept
+                    : state_{}
+                {
+                    state_ = rhs.state_;
+                    rhs.state_ = nullptr;
+                }
+
+                promise_base(const promise_base&) = delete;
+
+                virtual ~promise_base()
+                {
+                    this->abandon_state_();
+                }
+
+                promise_base& operator=(promise_base&& rhs) noexcept
+                {
+                    abandon_state_();
+                    promise_base{move(rhs)}.swap(*this);
+
+                    return *this;
+                }
+
+                promise_base& operator=(const promise_base&) = delete;
+
+                void swap(promise_base& other) noexcept
+                {
+                    std::swap(state_, other.state_);
+                }
+
+                void set_exception(exception_ptr ptr)
+                {
+                    assert(state_);
+
+                    state_->set_exception(ptr);
+                }
+
+                void set_exception_at_thread_exit(exception_ptr ptr)
+                {
+                    assert(state_);
+
+                    state_->set_exception_ptr(ptr, false);
+                    aux::set_state_exception_at_thread_exit(state_);
+                }
+
+                /**
+                 * Useful for testing as we can check some information
+                 * otherwise unavailable to us without waiting, e.g.
+                 * to check whether the state is ready, its reference
+                 * count etc.
+                 */
+                aux::shared_state<R>* __state()
+                {
+                    return state_;
+                }
+
+            protected:
+                void abandon_state_()
+                {
+                    if (!state_)
+                        return;
+
+                    /**
+                     * Note: This is the 'abandon' move described in
+                     *       30.6.4 (7).
+                     * 1) If state is not ready:
+                     *   a) Store exception of type future_error with
+                     *      error condition broken_promise.
+                     *   b) Mark state as ready.
+                     * 2) Release the state.
+                     */
+
+                    if (!state_->is_set())
+                    {
+                        state_->set_exception(make_exception_ptr(
+                            future_error{make_error_code(future_errc::broken_promise)}
+                        ));
+                        state_->mark_set(true);
+                    }
+
+                    if (state_->decrement())
+                    {
+                        state_->destroy();
+                        delete state_;
+                        state_ = nullptr;
+                    }
+                }
+
+                aux::shared_state<R>* state_;
+        };
+    }
+
+    template<class R>
+    class promise: public aux::promise_base<R>
+    {
+        public:
+            promise()
+                : aux::promise_base<R>{}
+            { /* DUMMY BODY */ }
+
+            template<class Allocator>
+            promise(allocator_arg_t tag, const Allocator& a)
+                : aux::promise_base<R>{tag, a}
+            { /* DUMMY BODY */ }
+
+            promise(promise&& rhs) noexcept
+                : aux::promise_base<R>{move(rhs)}
+            { /* DUMMY BODY */ }
+
+            promise(const promise&) = delete;
+
+            ~promise() override = default;
+
+            promise& operator=(promise&& rhs) noexcept = default;
+
+            promise& operator=(const promise&) = delete;
+
+            future<R> get_future()
+            {
+                assert(this->state_);
+
+                /**
+                 * Note: Future constructor that takes a shared
+                 *       state as its argument does not call increment
+                 *       because a future can be created as the only
+                 *       owner of that state (e.g. when created by
+                 *       std::async), so we have to do it here.
+                 */
+                this->state_->increment();
+
+                return future<R>{this->state_};
+            }
+
+            void set_value(const R& val)
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                this->state_->set_value(val, true);
+            }
+
+            void set_value(R&& val)
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                this->state_->set_value(forward<R>(val), true);
+            }
+
+            void set_value_at_thread_exit(const R& val)
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                try
+                {
+                    this->state_->set_value(val, false);
+                    aux::set_state_value_at_thread_exit(this->state_);
+                }
+                catch(const exception& __exception)
+                {
+                    this->state_->set_exception(make_exception_ptr(__exception), false);
+                    aux::set_state_exception_at_thread_exit(this->state_);
+                }
+            }
+
+            void set_value_at_thread_exit(R&& val)
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                try
+                {
+                    this->state_->set_value(forward<R>(val), false);
+                    aux::set_state_value_at_thread_exit(this->state_);
+                }
+                catch(const exception& __exception)
+                {
+                    this->state_->set_exception(make_exception_ptr(__exception), false);
+                    aux::set_state_exception_at_thread_exit(this->state_);
+                }
+            }
+    };
+
+    template<class R>
+    class promise<R&>: public aux::promise_base<R*>
+    {
+        public:
+            promise()
+                : aux::promise_base<R*>{}
+            { /* DUMMY BODY */ }
+
+            template<class Allocator>
+            promise(allocator_arg_t tag, const Allocator& a)
+                : aux::promise_base<R*>{tag, a}
+            { /* DUMMY BODY */ }
+
+            promise(promise&& rhs) noexcept
+                : aux::promise_base<R*>{move(rhs)}
+            { /* DUMMY BODY */ }
+
+            promise(const promise&) = delete;
+
+            ~promise() override = default;
+
+            promise& operator=(promise&& rhs) noexcept = default;
+
+            promise& operator=(const promise&) = delete;
+
+            future<R&> get_future()
+            {
+                assert(this->state_);
+
+                /**
+                 * Note: Future constructor that takes a shared
+                 *       state as its argument does not call increment
+                 *       because a future can be created as the only
+                 *       owner of that state (e.g. when created by
+                 *       std::async), so we have to do it here.
+                 */
+                this->state_->increment();
+
+                return future<R&>{this->state_};
+            }
+
+            void set_value(R& val)
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                this->state_->set_value(&val, true);
+            }
+
+            void set_value_at_thread_exit(R& val)
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                try
+                {
+                    this->state_->set_value(&val, false);
+                    aux::set_state_value_at_thread_exit(this->state_);
+                }
+                catch(const exception& __exception)
+                {
+                    this->state_->set_exception(make_exception_ptr(__exception), false);
+                    aux::set_state_exception_at_thread_exit(this->state_);
+                }
+            }
+    };
+
+    template<>
+    class promise<void>: public aux::promise_base<void>
+    {
+        public:
+            promise()
+                : aux::promise_base<void>{}
+            { /* DUMMY BODY */ }
+
+            template<class Allocator>
+            promise(allocator_arg_t tag, const Allocator& a)
+                : aux::promise_base<void>{tag, a}
+            { /* DUMMY BODY */ }
+
+            promise(promise&& rhs) noexcept
+                : aux::promise_base<void>{move(rhs)}
+            { /* DUMMY BODY */ }
+
+            promise(const promise&) = delete;
+
+            ~promise() override = default;
+
+            promise& operator=(promise&& rhs) noexcept = default;
+
+            promise& operator=(const promise&) = delete;
+
+            future<void> get_future()
+            {
+                assert(this->state_);
+
+                /**
+                 * Note: Future constructor that takes a shared
+                 *       state as its argument does not call increment
+                 *       because a future can be created as the only
+                 *       owner of that state (e.g. when created by
+                 *       std::async), so we have to do it here.
+                 */
+                this->state_->increment();
+
+                return future<void>{this->state_};
+            }
+
+            void set_value()
+            {
+                if (!this->state_)
+                    throw future_error{make_error_code(future_errc::no_state)};
+                if (this->state_->is_set())
+                {
+                    throw future_error{
+                        make_error_code(future_errc::promise_already_satisfied)
+                    };
+                }
+
+                this->state_->set_value();
+            }
+    };
+
+    template<class R>
+    void swap(promise<R>& lhs, promise<R>& rhs) noexcept
+    {
+        lhs.swap(rhs);
+    }
+
+    template<class R, class Alloc>
+    struct uses_allocator<promise<R>, Alloc>: true_type
+    { /* DUMMY BODY */ };
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/thread/shared_future.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/shared_future.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/thread/shared_future.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_THREAD_SHARED_FUTURE
+#define LIBCPP_BITS_THREAD_SHARED_FUTURE
+
+#include <__bits/thread/future.hpp>
+#include <__bits/thread/future_common.hpp>
+#include <type_traits>
+
+/**
+ * Note: We do synchronization directly on the shared
+ *       state, this means that with the exception of
+ *       some member functions (which are only defined
+ *       for specializations anyway) our future and
+ *       shared_future are basically identical. Because
+ *       of that, we can use aux::future_base for
+ *       shared_future as well.
+ */
+
+namespace std
+{
+    /**
+     * 30.6.7, class template shared_future:
+     */
+
+    template<class R>
+    class shared_future: public aux::future_base<aux::future_inner_t<R>>
+    {
+        public:
+            shared_future() noexcept = default;
+
+            shared_future(const shared_future&) = default;
+
+            shared_future(shared_future&&) noexcept = default;
+
+            shared_future(future<R>&& rhs)
+                : aux::future_base<aux::future_inner_t<R>>{move(rhs.state_)}
+            {
+                rhs.state_ = nullptr;
+            }
+
+            shared_future& operator=(const shared_future&) = default;
+
+            shared_future& operator=(shared_future&&) noexcept = default;
+
+            aux::future_return_shared_t<R> get() const
+            {
+                assert(this->state_);
+
+                this->wait();
+
+                if (this->state_->has_exception())
+                    this->state_->throw_stored_exception();
+
+                /**
+                 * Using constexpr if and the future_inner and future_result
+                 * metafunctions we can actually avoid having to create specializations
+                 * for R& and void in this case.
+                 */
+                if constexpr (!is_same_v<R, void>)
+                {
+                    if constexpr (is_reference_v<R>)
+                    {
+                        assert(this->state_->get());
+
+                        return *this->state_->get();
+                    }
+                    else
+                        return this->state_->get();
+                }
+            }
+
+            /**
+             * Useful for testing as we can check some information
+             * otherwise unavailable to us without waiting, e.g.
+             * to check whether the state is ready, its reference
+             * count etc.
+             */
+            aux::shared_state<aux::future_inner_t<R>>* __state() noexcept
+            {
+                return this->state_;
+            }
+    };
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/thread/shared_state.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/thread/shared_state.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/include/__bits/thread/shared_state.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_BITS_THREAD_SHARED_STATE
+#define LIBCPP_BITS_THREAD_SHARED_STATE
+
+/**
+ * 30.6.4, shared state:
+ */
+
+#include <__bits/exception.hpp>
+#include <__bits/functional/function.hpp>
+#include <__bits/functional/invoke.hpp>
+#include <__bits/refcount_obj.hpp>
+#include <__bits/thread/future_common.hpp>
+#include <__bits/thread/threading.hpp>
+#include <cerrno>
+#include <thread>
+#include <tuple>
+
+namespace std::aux
+{
+    class shared_state_base: public aux::refcount_obj
+    {
+        public:
+            shared_state_base()
+                : mutex_{}, condvar_{}, value_set_{false},
+                  exception_{}, has_exception_{false}
+            {
+                threading::mutex::init(mutex_);
+                threading::condvar::init(condvar_);
+            }
+
+            void destroy() override
+            {
+                /**
+                 * Note: No need to act in this case, async shared
+                 *       state is the object that needs to sometimes
+                 *       invoke its payload.
+                 */
+            }
+
+            void mark_set(bool set = true) noexcept
+            {
+                value_set_ = set;
+            }
+
+            bool is_set() const noexcept
+            {
+                return value_set_;
+            }
+
+            void set_exception(exception_ptr ptr, bool set = true)
+            {
+                exception_ = ptr;
+                has_exception_ = set;
+            }
+
+            bool has_exception() const noexcept
+            {
+                return has_exception_;
+            }
+
+            void throw_stored_exception() const
+            {
+                if (has_exception_)
+                    rethrow_exception(exception_);
+            }
+
+            virtual void wait() const
+            {
+                aux::threading::mutex::lock(
+                    const_cast<aux::mutex_t&>(mutex_)
+                );
+
+                while (!value_set_)
+                {
+                    aux::threading::condvar::wait(
+                        const_cast<aux::condvar_t&>(condvar_),
+                        const_cast<aux::mutex_t&>(mutex_)
+                    );
+                }
+
+                aux::threading::mutex::unlock(
+                    const_cast<aux::mutex_t&>(mutex_)
+                );
+            }
+
+            template<class Rep, class Period>
+            future_status
+            wait_for(const chrono::duration<Rep, Period>& rel_time) const
+            {
+                if (value_set_)
+                    return future_status::ready;
+
+                aux::threading::mutex::lock(
+                    const_cast<aux::mutex_t&>(mutex_)
+                );
+
+                auto res = timed_wait_(
+                    aux::threading::time::convert(rel_time)
+                );
+
+                aux::threading::mutex::unlock(
+                    const_cast<aux::mutex_t&>(mutex_)
+                );
+
+                return res;
+            }
+
+            template<class Clock, class Duration>
+            future_status
+            wait_until(const chrono::time_point<Clock, Duration>& abs_time)
+            {
+                if (value_set_)
+                    return future_status::ready;
+
+                aux::threading::mutex::lock(
+                    const_cast<aux::mutex_t&>(mutex_)
+                );
+
+                auto res = timed_wait_(
+                    aux::threading::time::convert(abs_time - Clock::now())
+                );
+
+                aux::threading::mutex::unlock(
+                    const_cast<aux::mutex_t&>(mutex_)
+                );
+
+                return res;
+            }
+
+            ~shared_state_base() override = default;
+
+        protected:
+            aux::mutex_t mutex_;
+            aux::condvar_t condvar_;
+
+            bool value_set_;
+
+            exception_ptr exception_;
+            bool has_exception_;
+
+            /**
+             * Note: wait_for and wait_until are templates and as such
+             *       cannot be virtual and overriden by the deferred_ and
+             *       async_ children. However, we are using aux::time_unit_t
+             *       in the end anyway, so we can work around that
+             *       by using the 'template method' design pattern
+             *       (i.e. by providing a virtual function called by these
+             *       templates and then overriding that function in the
+             *       children).
+             */
+            virtual future_status timed_wait_(aux::time_unit_t time) const
+            {
+                auto res = aux::threading::condvar::wait_for(
+                    const_cast<aux::condvar_t&>(condvar_),
+                    const_cast<aux::mutex_t&>(mutex_), time
+                );
+
+                return res == ETIMEOUT ? future_status::timeout
+                                       : future_status::ready;
+            }
+    };
+
+    template<class R>
+    class shared_state: public shared_state_base
+    {
+        public:
+            shared_state()
+                : shared_state_base{}
+            { /* DUMMY BODY */ }
+
+            void set_value(const R& val, bool set)
+            {
+                /**
+                 * Note: This is the 'mark ready' move described
+                 *       in 30.6.4 (6).
+                 */
+
+                aux::threading::mutex::lock(mutex_);
+                value_ = val;
+                value_set_ = set;
+                aux::threading::mutex::unlock(mutex_);
+
+                if (set)
+                    aux::threading::condvar::broadcast(condvar_);
+            }
+
+            void set_value(R&& val, bool set = true)
+            {
+                aux::threading::mutex::lock(mutex_);
+                value_ = std::move(val);
+                value_set_ = set;
+                aux::threading::mutex::unlock(mutex_);
+
+                if (set)
+                    aux::threading::condvar::broadcast(condvar_);
+            }
+
+            R& get()
+            {
+                return value_;
+            }
+
+        protected:
+            R value_;
+    };
+
+    template<>
+    class shared_state<void>: public shared_state_base
+    {
+        public:
+            shared_state()
+                : shared_state_base{}
+            { /* DUMMY BODY */ }
+
+            void set_value()
+            {
+                value_set_ = true;
+                aux::threading::condvar::broadcast(condvar_);
+            }
+
+            void get()
+            { /* DUMMY BODY */ }
+    };
+
+    /**
+     * We could make one state for both async and
+     * deferred policies, but then we would be wasting
+     * memory and the only benefit would be the ability
+     * for additional implementation defined policies done
+     * directly in that state (as opposed to making new
+     * states for them).
+     *
+     * But since we have no plan (nor need) to make those,
+     * this approach seems to be the best one.
+     *
+     * Also note that unlike the parent class shared_state,
+     * we do not need to specialize these for void. This is because
+     * the difference in class contents are handled by the parent
+     * specialization and setting the value can be handled easily
+     * by if constexpr and checking for the equivalence of the
+     * R template parameter and void.
+     */
+
+    template<class R, class F, class... Args>
+    class async_shared_state: public shared_state<R>
+    {
+        public:
+            async_shared_state(F&& f, Args&&... args)
+                : shared_state<R>{}, thread_{}
+            {
+                thread_ = thread{
+                    [=](){
+                        try
+                        {
+                            if constexpr (!is_same_v<R, void>)
+                                this->set_value(invoke(f, args...));
+                            else
+                            {
+                                invoke(f, args...);
+                                this->mark_set(true);
+                            }
+                        }
+                        catch(const exception& __exception)
+                        {
+                            this->set_exception(make_exception_ptr(__exception));
+                        }
+                    }
+                };
+            }
+
+            void destroy() override
+            {
+                if (!this->is_set())
+                    thread_.join();
+            }
+
+            void wait() const override
+            {
+                if (!this->is_set())
+                    const_cast<thread&>(thread_).join();
+            }
+
+            ~async_shared_state() override
+            {
+                destroy();
+            }
+
+        protected:
+            future_status timed_wait_(aux::time_unit_t time) const override
+            {
+                /**
+                 * Note: Currently we have no timed join, but this
+                 *       behaviour should be compliant.
+                 */
+                aux::threading::time::sleep(time);
+                if (this->value_set_)
+                    return future_status::ready;
+                else
+                    return future_status::timeout;
+            }
+
+        private:
+            thread thread_;
+    };
+
+    template<class R, class F, class... Args>
+    class deferred_shared_state: public shared_state<R>
+    {
+        public:
+            template<class G>
+            deferred_shared_state(G&& f, Args&&... args)
+                : shared_state<R>{}, func_{forward<F>(f)},
+                  args_{forward<Args>(args)...}
+            { /* DUMMY BODY */ }
+
+            void destroy() override
+            {
+                aux::threading::mutex::lock(this->mutex_);
+                if (!this->is_set())
+                    invoke_(make_index_sequence<sizeof...(Args)>{});
+                aux::threading::mutex::unlock(this->mutex_);
+            }
+
+            void wait() const override
+            {
+                /**
+                 * Note: Synchronization done in invoke_ -> set_value.
+                 */
+                if (!this->is_set())
+                {
+                    const_cast<
+                        deferred_shared_state<R, F, Args...>*
+                    >(this)->invoke_(make_index_sequence<sizeof...(Args)>{});
+                }
+            }
+
+            ~deferred_shared_state() override
+            {
+                destroy();
+            }
+
+        protected:
+            function<R(decay_t<Args>...)> func_;
+            tuple<decay_t<Args>...> args_;
+
+            template<size_t... Is>
+            void invoke_(index_sequence<Is...>)
+            {
+                try
+                {
+                    if constexpr (!is_same_v<R, void>)
+                        this->set_value(invoke(move(func_), get<Is>(move(args_))...));
+                    else
+                    {
+                        invoke(move(func_), get<Is>(move(args_))...);
+                        this->mark_set(true);
+                    }
+                }
+                catch(const exception& __exception)
+                {
+                    this->set_exception(make_exception_ptr(__exception));
+                }
+            }
+
+            future_status timed_wait_(aux::time_unit_t) const override
+            {
+                /**
+                 * Note: Neither of the wait_ functions has any effect
+                 *       for deferred functions spawned by async (which
+                 *       are the only users of this state type).
+                 */
+                return future_status::deferred;
+            }
+    };
+
+    /**
+     * Note: The following two functions should:
+     *   1) Increment refcount.
+     *   2) Store ptr to a vector of shared_state_base ptrs
+     *      (as those have ::mark_set member functions).
+     *   3) If not done already, register a function
+     *      executing all these in the thread_atexit function
+     *      once that is implemented.
+     */
+
+    template<class R>
+    void set_state_value_at_thread_exit(shared_state<R>* state)
+    {
+        // TODO: implement
+        __unimplemented();
+    }
+
+    template<class R>
+    void set_state_exception_at_thread_exit(shared_state<R>* state)
+    {
+        // TODO: implement
+        __unimplemented();
+    }
+}
+
+#endif
Index: uspace/lib/cpp/include/__bits/trycatch.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/trycatch.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/trycatch.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -67,4 +67,22 @@
 
 /**
+ * The language allows us to odr-use a variable
+ * that is not defined. We use this to support
+ * macros redefining the catch keyword that are
+ * followed by a block that uses that symbol.
+ *
+ * Normally, that would produce a compiler error
+ * as the declaration of that variale would be removed
+ * with the catch statement, but if we use the following
+ * declaration's name as the name of the caught exception,
+ * all will work well because of this extern declaration.
+ *
+ * Note: We do not follow our usual convention of using
+ * the aux:: namespace because that cannot be used in
+ * variable declaration.
+ */
+extern int __exception;
+
+/**
  * These macros allow us to choose how the program
  * should behave when an exception is thrown
@@ -87,5 +105,5 @@
 #define LIBCPP_EXCEPTION_IGNORE       /* IGNORE */
 #define LIBCPP_EXCEPTION_HANDLE_THROW LIBCPP_EXCEPTION_IGNORE
-#define LIBCPP_EXCEPTION_HANDLE_CATCH LIBCPP_EXCEPTION_HANG
+#define LIBCPP_EXCEPTION_HANDLE_CATCH LIBCPP_EXCEPTION_ABORT
 
 #define try if constexpr (::std::aux::try_blocks_allowed)
Index: uspace/lib/cpp/include/__bits/tuple/tuple.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/tuple/tuple.hpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/__bits/tuple/tuple.hpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -433,4 +433,23 @@
     };
 
+    template<>
+    class tuple<>
+    {
+        /**
+         * In some cases, e.g. for async() calls
+         * without argument to the functors, we need
+         * zero length tuples, which are provided by
+         * the following specialization.
+         * (Without it we get a resolution conflict between
+         * the default constructor and the Ts... constructor
+         * in the original tuple.)
+         */
+
+        tuple() = default;
+
+        void swap(tuple&) noexcept
+        { /* DUMMY BODY */ }
+    };
+
     /**
      * 20.4.2.7, relational operators:
Index: uspace/lib/cpp/include/future
===================================================================
--- uspace/lib/cpp/include/future	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/include/future	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -27,3 +27,9 @@
  */
 
+#include <__bits/thread/async.hpp>
 #include <__bits/thread/future.hpp>
+#include <__bits/thread/future_common.hpp>
+#include <__bits/thread/packaged_task.hpp>
+#include <__bits/thread/promise.hpp>
+#include <__bits/thread/shared_future.hpp>
+#include <__bits/thread/shared_state.hpp>
Index: uspace/lib/cpp/src/__bits/runtime.cpp
===================================================================
--- uspace/lib/cpp/src/__bits/runtime.cpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/src/__bits/runtime.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -28,4 +28,5 @@
 
 #include <__bits/abi.hpp>
+#include <cassert>
 #include <cstdlib>
 #include <cstdint>
@@ -207,3 +208,10 @@
     extern "C" void __cxa_end_cleanup()
     { /* DUMMY BODY */ }
+
+    extern "C" int __cxa_thread_atexit(void(*)(void*), void*, void*)
+    {
+        // TODO: needed for thread_local variables
+        __unimplemented();
+        return 0;
+    }
 }
Index: uspace/lib/cpp/src/__bits/test/future.cpp
===================================================================
--- uspace/lib/cpp/src/__bits/test/future.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/src/__bits/test/future.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <__bits/test/mock.hpp>
+#include <__bits/test/tests.hpp>
+#include <chrono>
+#include <exception>
+#include <future>
+#include <tuple>
+#include <utility>
+
+using namespace std::chrono_literals;
+
+namespace
+{
+    template<class R>
+    auto prepare()
+    {
+        auto res = std::tuple<
+            std::promise<R>, std::future<R>,
+            std::aux::shared_state<R>*
+        >{};
+        std::get<0>(res) = std::promise<R>{};
+        std::get<1>(res) = std::get<0>(res).get_future();
+        std::get<2>(res) = std::get<1>(res).__state();
+
+        return res;
+    }
+}
+
+namespace std::test
+{
+    bool future_test::run(bool report)
+    {
+        report_ = report;
+        start();
+
+        test_future();
+        test_promise();
+        test_future_promise();
+        test_async();
+        test_packaged_task();
+        test_shared_future();
+
+        return end();
+    }
+
+    const char* future_test::name()
+    {
+        return "future";
+    }
+
+    void future_test::test_future()
+    {
+        std::future<int> f1{};
+        test("default constructed invalid", !f1.valid());
+
+        std::future<int> f2{new std::aux::shared_state<int>{}};
+        test("state constructed valid", f2.valid());
+
+        f1 = std::move(f2);
+        test("move assignment source invalid", !f2.valid());
+        test("move assignment destination valid", f1.valid());
+
+        std::future<int> f3{std::move(f1)};
+        test("move construction source invalid", !f1.valid());
+        test("move construction destination valid", f3.valid());
+    }
+
+    void future_test::test_promise()
+    {
+        std::promise<int> p1{};
+        test("default constructed promise has state", p1.__state());
+
+        std::promise<int> p2{};
+        auto* s1 = p1.__state();
+        auto* s2 = p2.__state();
+        p2.swap(p1);
+        std::swap(s1, s2);
+
+        test_eq("swap switches states pt1", s1, p1.__state());
+        test_eq("swap switches states pt2", s2, p2.__state());
+
+        std::promise<int> p3{std::move(p1)};
+        test_eq("move construction state moved", s1, p3.__state());
+        test_eq("move construction source empty", p1.__state(), nullptr);
+
+        p1 = std::move(p3);
+        test_eq("move assignment state move", s1, p1.__state());
+        test_eq("move assignment source empty", p3.__state(), nullptr);
+
+        p1.set_value(42);
+        test("set_value marks state as ready", s1->is_set());
+        test_eq("set_value sets value", s1->get(), 42);
+    }
+
+    void future_test::test_future_promise()
+    {
+        /**
+         * Note: As we currently have no exception
+         *       propagation support, we do not test
+         *       exceptions here. However, the logic there
+         *       is basically identical to that of the value
+         *       setting.
+         */
+        auto [p1, f1, s1] = prepare<int>();
+        test_eq("refcount in basic case", s1->refs(), 2);
+
+        p1.set_value(1);
+        test("simple case valid", f1.valid());
+        test_eq("simple case get", f1.get(), 1);
+
+        auto [p2, f2, s2] = prepare<int>();
+        std::thread t2{
+            [&p2](){
+                std::this_thread::sleep_for(20ms);
+                p2.set_value(42);
+            }
+        };
+
+        test_eq("parallel get waits and has correct value", f2.get(), 42);
+
+        auto [p3, f3, s3] = prepare<int>();
+        std::thread t3{
+            [&p3](){
+                std::this_thread::sleep_for(20ms);
+                p3.set_value(42);
+            }
+        };
+
+        f3.wait();
+        test("after wait value is set", s3->is_set());
+        test_eq("after wait value is correct", s3->get(), 42);
+
+        auto [p4, f4, s4] = prepare<int>();
+        std::thread t4{
+            [&p4](){
+                /* p4.set_value_at_thread_exit(42); */
+            }
+        };
+        std::this_thread::sleep_for(10ms); // Let the value be set inside state.
+
+        /* test("shared state marked as ready at thread exit", s4->is_set()); */
+        /* test_eq("value set inside state while in thread", s4->get(), 42); */
+        /* test_eq("value set at thread exit", f4.get(), 42); */
+
+        mock::clear();
+        std::aux::shared_state<std::test::mock>* s5{};
+        {
+            std::promise<std::test::mock> p5{};
+            s5 = p5.__state();
+            test_eq("refcount with just promise", s5->refs(), 1);
+            {
+                auto f5 = p5.get_future();
+                test_eq("refcount after creating future", s5->refs(), 2);
+            }
+            test_eq("refcount after future is destroyed", s5->refs(), 1);
+            test_eq("state not destroyed with future", mock::destructor_calls, 0U);
+        }
+        test_eq("state destroyed with promise", mock::destructor_calls, 1U);
+
+        mock::clear();
+        {
+            std::aux::shared_state<std::test::mock>* s6{};
+            std::future<std::test::mock> f6{};
+            {
+                std::promise<std::test::mock> p6{};
+                s6 = p6.__state();
+                {
+                    f6 = p6.get_future();
+                    test_eq("move construction only increments refcount once", s6->refs(), 2);
+                }
+            }
+            test_eq("refcount after promise is destroyed", s6->refs(), 1);
+            test_eq("state not destroyed with promise", mock::destructor_calls, 0U);
+        }
+        test_eq("state destroyed with future", mock::destructor_calls, 1U);
+
+        auto [p7, f7, s7] = prepare<int>();
+        auto res7 = f7.wait_for(5ms);
+        test_eq("wait_for timeout", res7, std::future_status::timeout);
+
+        res7 = f7.wait_until(std::chrono::system_clock::now() + 5ms);
+        test_eq("wait_until timeout", res7, std::future_status::timeout);
+
+        std::thread t7{
+            [&p7](){
+                std::this_thread::sleep_for(5ms);
+                p7.set_value(42);
+            }
+        };
+        res7 = f7.wait_for(10ms);
+        test_eq("wait_for ready", res7, std::future_status::ready);
+
+        auto [p8, f8, s8] = prepare<int>();
+        std::thread t8{
+            [&p8](){
+                std::this_thread::sleep_for(5ms);
+                p8.set_value(42);
+            }
+        };
+
+        auto res8 = f8.wait_until(std::chrono::system_clock::now() + 10ms);
+        test_eq("wait_until ready", res8, std::future_status::ready);
+
+        int x{};
+        std::promise<int&> p9{};
+        std::future<int&> f9 = p9.get_future();
+        p9.set_value(x);
+        int& y = f9.get();
+
+        test_eq("reference equal to original", x, y);
+
+        ++x;
+        test_eq("equal after modifying original", x, y);
+
+        ++y;
+        test_eq("equal after modifying reference", x, y);
+    }
+
+    void future_test::test_async()
+    {
+        auto res1 = std::async(
+            [](){
+                return 42;
+            }
+        );
+        test_eq("ret async default policy", res1.get(), 42);
+
+        auto res2 = std::async(
+            std::launch::deferred, [](){
+                return 42;
+            }
+        );
+        test_eq("ret async deferred policy", res2.get(), 42);
+
+        auto res3 = std::async(
+            std::launch::async, [](){
+                return 42;
+            }
+        );
+        test_eq("ret async async policy", res3.get(), 42);
+
+        int x{};
+        auto res4 = std::async(
+            [&x](){
+                x = 42;
+            }
+        );
+
+        res4.get();
+        test_eq("void async", x, 42);
+    }
+
+    void future_test::test_packaged_task()
+    {
+        std::packaged_task<int(int)> pt1{};
+        test("default constructed packaged_task not valid", !pt1.valid());
+
+        pt1 = std::packaged_task<int(int)>{
+            [](int x){
+                return x + 1;
+            }
+        };
+        test("packaged_task default constructed and move assigned valid", pt1.valid());
+
+        auto f1 = pt1.get_future();
+        test("future from valid packaged_task valid", f1.valid());
+
+        pt1(10);
+        test_eq("result stored in future correct", f1.get(), 11);
+
+        std::packaged_task<int()> pt2{
+            [](){
+                return 42;
+            }
+        };
+        auto f2 = pt2.get_future();
+        pt2();
+        test_eq("no argument packaged_task return value correct", f2.get(), 42);
+
+        pt2.reset();
+        test_eq("reset causes refcount decrement", f2.__state()->refs(), 1);
+
+        auto f3 = pt2.get_future();
+        pt2();
+        test_eq("invocation after reset returns correct value", f3.get(), 42);
+        test("reset recreates state", (f2.__state() != f3.__state()));
+    }
+
+    void future_test::test_shared_future()
+    {
+        auto [p1, f1, s1] = prepare<int>();
+        auto sf1 = f1.share();
+
+        test("future invalid after share", !f1.valid());
+        test_eq("shared state moved on share", sf1.__state(), s1);
+        test_eq("no refcount increment on share", s1->refs(), 2);
+
+        {
+            auto sf2 = sf1;
+            test_eq("refcount increment on copy", s1->refs(), 3);
+            test_eq("shared state shared between copies", sf1.__state(), sf2.__state());
+        }
+        test_eq("refcount decrement when copy gets destroyed", s1->refs(), 2);
+
+        auto sf2 = sf1;
+        int res1{}, res2{};
+        std::thread t1{
+            [&](){
+                res1 = sf1.get();
+            }
+        };
+        std::thread t2{
+            [&](){
+                res2 = sf2.get();
+            }
+        };
+
+        std::this_thread::sleep_for(20ms);
+        p1.set_value(42);
+        std::this_thread::sleep_for(20ms);
+        test_eq("first result correct", res1, 42);
+        test_eq("second result correct", res2, 42);
+    }
+}
Index: uspace/lib/cpp/src/future.cpp
===================================================================
--- uspace/lib/cpp/src/future.cpp	(revision 9fb280c18d7a3aadce7085e013cc9625098ea17e)
+++ uspace/lib/cpp/src/future.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -81,3 +81,8 @@
         return code_;
     }
+
+    const char* future_error::what() const noexcept
+    {
+        return code().message().c_str();
+    }
 }
Index: uspace/lib/cpp/src/refcount_obj.cpp
===================================================================
--- uspace/lib/cpp/src/refcount_obj.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
+++ uspace/lib/cpp/src/refcount_obj.cpp	(revision a44893729478a3123b0209d0ff41f8365447c092)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <__bits/refcount_obj.hpp>
+
+namespace std::aux
+{
+    void refcount_obj::increment()
+    {
+        __atomic_add_fetch(&refcount_, 1, __ATOMIC_ACQ_REL);
+    }
+
+    void refcount_obj::increment_weak()
+    {
+        __atomic_add_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL);
+    }
+
+    bool refcount_obj::decrement()
+    {
+        if (__atomic_sub_fetch(&refcount_, 1, __ATOMIC_ACQ_REL) == 0)
+        {
+            /**
+             * First call to destroy() will delete the held object,
+             * so it doesn't matter what the weak_refcount_ is,
+             * but we added one and we need to remove it now.
+             */
+            decrement_weak();
+
+            return true;
+        }
+        else
+            return false;
+    }
+
+    bool refcount_obj::decrement_weak()
+    {
+        return __atomic_sub_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL) == 0 && refs() == 0;
+    }
+
+    refcount_t refcount_obj::refs() const
+    {
+        return __atomic_load_n(&refcount_, __ATOMIC_RELAXED);
+    }
+
+    refcount_t refcount_obj::weak_refs() const
+    {
+        return __atomic_load_n(&weak_refcount_, __ATOMIC_RELAXED);
+    }
+
+    bool refcount_obj::expired() const
+    {
+        return refs() == 0;
+    }
+}
