diff --git a/Builds/VisualStudio2013/beast.vcxproj b/Builds/VisualStudio2013/beast.vcxproj
index 6bceab509..6e32692d5 100644
--- a/Builds/VisualStudio2013/beast.vcxproj
+++ b/Builds/VisualStudio2013/beast.vcxproj
@@ -21,6 +21,7 @@
+
@@ -86,8 +87,10 @@
+
+
@@ -133,6 +136,7 @@
+
@@ -152,7 +156,6 @@
-
@@ -185,14 +188,12 @@
-
-
@@ -214,7 +215,6 @@
-
@@ -333,7 +333,6 @@
-
@@ -362,10 +361,7 @@
-
-
-
@@ -433,6 +429,30 @@
true
true
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
@@ -1115,12 +1135,6 @@
true
true
-
- true
- true
- true
- true
-
true
true
@@ -1163,12 +1177,6 @@
true
true
-
- true
- true
- true
- true
-
true
true
@@ -1277,12 +1285,6 @@
true
true
-
- true
- true
- true
- true
-
true
true
diff --git a/Builds/VisualStudio2013/beast.vcxproj.filters b/Builds/VisualStudio2013/beast.vcxproj.filters
index 09b0c43b5..dab2e43ca 100644
--- a/Builds/VisualStudio2013/beast.vcxproj.filters
+++ b/Builds/VisualStudio2013/beast.vcxproj.filters
@@ -76,6 +76,9 @@
scripts
+
+ beast\asio
+
@@ -309,6 +312,9 @@
{1271ee71-5754-46ef-845b-84e53eed11c0}
+
+ {f2594738-6447-447b-8f51-2d42fbe8a6ee}
+
@@ -419,9 +425,6 @@
beast_core\network
-
- beast_core\network
-
beast_core\network
@@ -482,18 +485,9 @@
beast_core\threads
-
- beast_core\threads
-
beast_core\threads
-
- beast_core\threads
-
-
- beast_core\threads
-
beast_core\time
@@ -956,9 +950,6 @@
beast
-
- beast
-
beast\utility
@@ -1014,9 +1005,6 @@
beast\net
-
- beast\net
-
beast_asio\http
@@ -1032,9 +1020,6 @@
beast
-
- beast\threads
-
beast\threads
@@ -1149,9 +1134,6 @@
beast\insight
-
- beast
-
beast\threads
@@ -1323,6 +1305,15 @@
beast\http\impl
+
+ beast\container
+
+
+ beast\asio
+
+
+ beast\asio
+
@@ -1406,9 +1397,6 @@
beast_core\native
-
- beast_core\native
-
beast_core\native
@@ -1427,9 +1415,6 @@
beast_core\network
-
- beast_core\network
-
beast_core\network
@@ -1475,9 +1460,6 @@
beast_core\threads
-
- beast_core\threads
-
beast_core\time
@@ -1910,6 +1892,18 @@
beast\asio
+
+ beast\asio\tests
+
+
+ beast\asio\tests
+
+
+ beast\asio\tests
+
+
+ beast\asio\tests
+
diff --git a/TODO.txt b/TODO.txt
index 32bdb06ae..169787991 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -58,8 +58,6 @@ BEAST TODO
- Rename SharedData to SharedState or something?
-- Figure out what to do with ReadWriteLock, and NamedPipe which uses it?
-
- Put BEAST_PUBLIC_FUNCTION in front of all loose functions
- restructure the repo sources to look like this:
diff --git a/beast/Net.h b/beast/Net.h
index cd03ad112..6c4862d88 100644
--- a/beast/Net.h
+++ b/beast/Net.h
@@ -20,7 +20,6 @@
#ifndef BEAST_NET_H_INCLUDED
#define BEAST_NET_H_INCLUDED
-#include "net/BufferType.h"
#include "net/DynamicBuffer.h"
#include "net/IPEndpoint.h"
diff --git a/beast/SafeBool.h b/beast/SafeBool.h
deleted file mode 100644
index fbae19592..000000000
--- a/beast/SafeBool.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_SAFEBOOL_H_INCLUDED
-#define BEAST_SAFEBOOL_H_INCLUDED
-
-namespace beast {
-
-namespace detail {
-
-class SafeBoolBase
-{
-private:
- void disallowed () const { }
-
-public:
- void allowed () const { }
-
-protected:
- typedef void (SafeBoolBase::*boolean_t) () const;
-
- SafeBoolBase () { }
- SafeBoolBase (SafeBoolBase const&) { }
- SafeBoolBase& operator= (SafeBoolBase const&)
- {
- return *this;
- }
- ~SafeBoolBase () { }
-};
-
-}
-
-/** Safe evaluation of class as `bool`.
-
- This allows a class to be safely evaluated as a bool without the usual
- harmful side effects of the straightforward operator conversion approach.
- To use it, derive your class from SafeBool and implement `asBoolean()` as:
-
- @code
-
- bool asBoolean () const;
-
- @endcode
-
- Ideas from http://www.artima.com/cppsource/safebool.html
-
- @class SafeBool
-*/
-template
-class SafeBool : public detail::SafeBoolBase
-{
-public:
- operator detail::SafeBoolBase::boolean_t () const
- {
- return (static_cast (this))->asBoolean ()
- ? &SafeBoolBase::allowed : 0;
- }
-
-protected:
- ~SafeBool () { }
-};
-
-template
-void operator== (SafeBool const& lhs, SafeBool const& rhs)
-{
- lhs.disallowed ();
-}
-
-template
-void operator!= (SafeBool const& lhs, SafeBool const& rhs)
-{
- lhs.disallowed ();
-}
-
-}
-
-#endif
-
-
diff --git a/beast/Threads.h b/beast/Threads.h
index bd7a9c814..756376a2f 100644
--- a/beast/Threads.h
+++ b/beast/Threads.h
@@ -20,7 +20,6 @@
#ifndef BEAST_THREADS_H_INCLUDED
#define BEAST_THREADS_H_INCLUDED
-#include "threads/LockGuard.h"
#include "threads/UnlockGuard.h"
#include "threads/TryLockGuard.h"
#include "threads/SharedLockGuard.h"
diff --git a/beast/asio/Asio.cpp b/beast/asio/Asio.cpp
index aada5e4b3..d578299ff 100644
--- a/beast/asio/Asio.cpp
+++ b/beast/asio/Asio.cpp
@@ -23,6 +23,7 @@
#include "tests/wrap_handler_tests.cpp"
#include "tests/bind_handler_tests.cpp"
+#include "tests/enable_wait_for_async.test.cpp"
#include "tests/shared_handler_tests.cpp"
#include "abstract_socket.cpp" // TEMPORARY!
diff --git a/beast/asio/README.md b/beast/asio/README.md
new file mode 100644
index 000000000..5344652e2
--- /dev/null
+++ b/beast/asio/README.md
@@ -0,0 +1,14 @@
+# beast::asio
+
+Wrappers and utilities to make working with boost::asio easier.
+
+## Rules for asynchronous objects
+
+If an object calls asynchronous initiating functions it must either:
+
+ 1. Manage its lifetime by being reference counted
+
+ or
+
+ 2. Wait for all pending completion handlers to be called before
+ allowing itself to be destroyed.
diff --git a/beast/asio/buffer_sequence.h b/beast/asio/buffer_sequence.h
index b392e1ed5..3efec2230 100644
--- a/beast/asio/buffer_sequence.h
+++ b/beast/asio/buffer_sequence.h
@@ -99,6 +99,21 @@ public:
{
return m_buffers.end ();
}
+
+#if 0
+ template
+ void
+ assign (ConstBufferSequence const& buffers)
+ {
+ auto const n (std::distance (
+ std::begin (buffers), std::end (buffers)));
+
+ for (int i = 0, auto iter (std::begin (buffers));
+ iter != std::end (buffers); ++iter, ++i)
+ m_buffers[i] = Buffer (boost::asio::buffer_cast (
+ *iter), boost::asio::buffer_size (*iter));
+ }
+#endif
};
typedef buffer_sequence const_buffers;
diff --git a/beast/asio/enable_wait_for_async.h b/beast/asio/enable_wait_for_async.h
new file mode 100644
index 000000000..f6b877a80
--- /dev/null
+++ b/beast/asio/enable_wait_for_async.h
@@ -0,0 +1,265 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_ASIO_ENABLE_WAIT_FOR_ASYNC_H_INCLUDED
+#define BEAST_ASIO_ENABLE_WAIT_FOR_ASYNC_H_INCLUDED
+
+#include "wrap_handler.h"
+
+#include "../mpl/IsCallPossible.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include "../cxx14/type_traits.h" //
+
+namespace beast {
+namespace asio {
+
+namespace detail {
+
+template
+class ref_counted_wrapped_handler
+{
+private:
+ static_assert (std::is_same , Owner>::value,
+ "Owner cannot be a const or reference type");
+
+ Handler m_handler;
+ std::reference_wrapper m_owner;
+ bool m_continuation;
+
+public:
+ ref_counted_wrapped_handler (Owner& owner,
+ Handler&& handler, bool continuation)
+ : m_handler (std::move (handler))
+ , m_owner (owner)
+ , m_continuation (continuation ? true :
+ boost_asio_handler_cont_helpers::is_continuation (m_handler))
+ {
+ m_owner.get().increment();
+ }
+
+ ref_counted_wrapped_handler (Owner& owner,
+ Handler const& handler, bool continuation)
+ : m_handler (handler)
+ , m_owner (owner)
+ , m_continuation (continuation ? true :
+ boost_asio_handler_cont_helpers::is_continuation (m_handler))
+ {
+ m_owner.get().increment();
+ }
+
+ ~ref_counted_wrapped_handler ()
+ {
+ m_owner.get().decrement();
+ }
+
+ ref_counted_wrapped_handler (ref_counted_wrapped_handler const& other)
+ : m_handler (other.m_handler)
+ , m_owner (other.m_owner)
+ , m_continuation (other.m_continuation)
+ {
+ m_owner.get().increment();
+ }
+
+ ref_counted_wrapped_handler (ref_counted_wrapped_handler&& other)
+ : m_handler (std::move (other.m_handler))
+ , m_owner (other.m_owner)
+ , m_continuation (other.m_continuation)
+ {
+ m_owner.get().increment();
+ }
+
+ ref_counted_wrapped_handler& operator= (
+ ref_counted_wrapped_handler const&) = delete;
+
+ template
+ void
+ operator() (Args&&... args)
+ {
+ m_handler (std::forward (args)...);
+ }
+
+ template
+ void
+ operator() (Args&&... args) const
+ {
+ m_handler (std::forward (args)...);
+ }
+
+ template
+ friend
+ void
+ asio_handler_invoke (Function& f,
+ ref_counted_wrapped_handler* h)
+ {
+ boost_asio_handler_invoke_helpers::
+ invoke (f, h->m_handler);
+ }
+
+ template
+ friend
+ void
+ asio_handler_invoke (Function const& f,
+ ref_counted_wrapped_handler* h)
+ {
+ boost_asio_handler_invoke_helpers::
+ invoke (f, h->m_handler);
+ }
+
+ friend
+ void*
+ asio_handler_allocate (std::size_t size,
+ ref_counted_wrapped_handler* h)
+ {
+ return boost_asio_handler_alloc_helpers::
+ allocate (size, h->m_handler);
+ }
+
+ friend
+ void
+ asio_handler_deallocate (void* p, std::size_t size,
+ ref_counted_wrapped_handler* h)
+ {
+ boost_asio_handler_alloc_helpers::
+ deallocate (p, size, h->m_handler);
+ }
+
+ friend
+ bool
+ asio_handler_is_continuation (ref_counted_wrapped_handler* h)
+ {
+ return h->m_continuation;
+ }
+};
+
+}
+
+//------------------------------------------------------------------------------
+
+/** Facilitates blocking until no completion handlers are remaining.
+ If Derived has this member function:
+
+ @code
+ void on_wait_for_async (void)
+ @endcode
+
+ Then it will be called every time the number of pending completion
+ handlers transitions to zero from a non-zero value. The call is made
+ while holding the internal mutex.
+*/
+template
+class enable_wait_for_async
+{
+private:
+ BEAST_DEFINE_IS_CALL_POSSIBLE(
+ has_on_wait_for_async,on_wait_for_async);
+
+ void increment()
+ {
+ std::lock_guard lock (m_mutex);
+ ++m_count;
+ }
+
+ void notify (std::true_type)
+ {
+ static_cast (this)->on_wait_for_async();
+ }
+
+ void notify (std::false_type)
+ {
+ }
+
+ void decrement()
+ {
+ std::lock_guard lock (m_mutex);
+ --m_count;
+ if (m_count == 0)
+ {
+ m_cond.notify_all();
+ notify (std::integral_constant ::value>());
+ }
+ }
+
+ template
+ friend class detail::ref_counted_wrapped_handler;
+
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+ std::size_t m_count;
+
+public:
+ /** Blocks if there are any pending completion handlers. */
+ void
+ wait_for_async()
+ {
+ std::unique_lock lock (m_mutex);
+ while (m_count != 0)
+ m_cond.wait (lock);
+ }
+
+protected:
+ enable_wait_for_async()
+ : m_count (0)
+ {
+ }
+
+ ~enable_wait_for_async()
+ {
+ assert (m_count == 0);
+ }
+
+ /** Wraps the specified handler so it can be counted. */
+ /** @{ */
+ template
+ detail::ref_counted_wrapped_handler <
+ enable_wait_for_async,
+ std::remove_reference_t
+ >
+ wrap_with_counter (Handler&& handler, bool continuation = false)
+ {
+ return detail::ref_counted_wrapped_handler > (*this,
+ std::forward (handler), continuation);
+ }
+
+ template
+ detail::ref_counted_wrapped_handler <
+ enable_wait_for_async,
+ std::remove_reference_t
+ >
+ wrap_with_counter (continuation_t, Handler&& handler)
+ {
+ return detail::ref_counted_wrapped_handler > (*this,
+ std::forward (handler), true);
+ }
+ /** @} */
+};
+
+}
+}
+
+#endif
diff --git a/beast/asio/memory_buffer.h b/beast/asio/memory_buffer.h
new file mode 100644
index 000000000..e77d1d420
--- /dev/null
+++ b/beast/asio/memory_buffer.h
@@ -0,0 +1,423 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_ASIO_MEMORY_BUFFER_H_INCLUDED
+#define BEAST_ASIO_MEMORY_BUFFER_H_INCLUDED
+
+#include "../utility/empty_base_optimization.h"
+
+#include
+
+#include
+#include
+
+namespace beast {
+namespace asio {
+
+template <
+ class T,
+ class Alloc = std::allocator
+>
+class memory_buffer
+ : private empty_base_optimization
+{
+private:
+ static_assert (std::is_trivially_constructible ::value,
+ "T must be trivially constructible");
+
+ typedef empty_base_optimization Base;
+
+ using AllocTraits = std::allocator_traits ;
+
+ T* m_base;
+ std::size_t m_size;
+
+public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef Alloc allocator_type;
+ typedef T* iterator;
+ typedef T const* const_iterator;
+ typedef std::reverse_iterator reverse_iterator;
+ typedef std::reverse_iterator const_reverse_iterator;
+
+ memory_buffer ()
+ : m_base (nullptr)
+ , m_size (0)
+ {
+ }
+
+ memory_buffer (memory_buffer&& other)
+ : Base (std::move (other))
+ , m_base (other.m_base)
+ , m_size (other.m_size)
+ {
+ other.m_base = nullptr;
+ other.m_size = 0;
+ }
+
+ explicit memory_buffer (size_type n)
+ : m_base (AllocTraits::allocate (Base::member(), n))
+ , m_size (n)
+ {
+ }
+
+ explicit memory_buffer (Alloc const& alloc)
+ : Base (alloc)
+ , m_base (nullptr)
+ , m_size (0)
+ {
+ }
+
+ memory_buffer (size_type n, Alloc const& alloc)
+ : Base (alloc)
+ , m_base (AllocTraits::allocate (Base::member(), n))
+ , m_size (n)
+ {
+ }
+
+ ~memory_buffer()
+ {
+ if (m_base != nullptr)
+ AllocTraits::deallocate (Base::member(), m_base, m_size);
+ }
+
+ memory_buffer& operator= (memory_buffer const&) = delete;
+
+ allocator_type
+ get_allocator() const
+ {
+ return Base::member;
+ }
+
+ //
+ // asio support
+ //
+
+ boost::asio::mutable_buffer
+ buffer()
+ {
+ return boost::asio::mutable_buffer (
+ data(), bytes());
+ }
+
+ boost::asio::const_buffer
+ buffer() const
+ {
+ return boost::asio::const_buffer (
+ data(), bytes());
+ }
+
+ boost::asio::mutable_buffers_1
+ buffers()
+ {
+ return boost::asio::mutable_buffers_1 (
+ data(), bytes());
+ }
+
+ boost::asio::const_buffers_1
+ buffers() const
+ {
+ return boost::asio::const_buffers_1 (
+ data(), bytes());
+ }
+
+ operator boost::asio::mutable_buffer()
+ {
+ return buffer();
+ }
+
+ operator boost::asio::const_buffer() const
+ {
+ return buffer();
+ }
+
+ operator boost::asio::mutable_buffers_1()
+ {
+ return buffers();
+ }
+
+ operator boost::asio::const_buffers_1() const
+ {
+ return buffers();
+ }
+
+ //
+ // Element access
+ //
+
+ reference
+ at (size_type pos)
+ {
+ if (! (pos < size()))
+ throw std::out_of_range ("bad array index");
+ return m_base [pos];
+ }
+
+ const_reference
+ at (size_type pos) const
+ {
+ if (! (pos < size()))
+ throw std::out_of_range ("bad array index");
+ return m_base [pos];
+ }
+
+ reference
+ operator[] (size_type pos) noexcept
+ {
+ return m_base [pos];
+ }
+
+ const_reference
+ operator[] (size_type pos) const noexcept
+ {
+ return m_base [pos];
+ }
+
+ reference
+ back() noexcept
+ {
+ return m_base [m_size - 1];
+ }
+
+ const_reference
+ back() const noexcept
+ {
+ return m_base [m_size - 1];
+ }
+
+ reference
+ front() noexcept
+ {
+ return *m_base;
+ }
+
+ const_reference
+ front() const noexcept
+ {
+ return *m_base;
+ }
+
+ pointer
+ data() noexcept
+ {
+ return m_base;
+ }
+
+ const_pointer
+ data() const noexcept
+ {
+ return m_base;
+ }
+
+ //
+ // Iterators
+ //
+
+ iterator
+ begin() noexcept
+ {
+ return m_base;
+ }
+
+ const_iterator
+ begin() const noexcept
+ {
+ return m_base;
+ }
+
+ const_iterator
+ cbegin() const noexcept
+ {
+ return m_base;
+ }
+
+ iterator
+ end() noexcept
+ {
+ return m_base + m_size;
+ }
+
+ const_iterator
+ end() const noexcept
+ {
+ return m_base + m_size;
+ }
+
+ const_iterator
+ cend() const noexcept
+ {
+ return m_base + m_size;
+ }
+
+ reverse_iterator
+ rbegin() noexcept
+ {
+ return reverse_iterator (end());
+ }
+
+ const_reverse_iterator
+ rbegin() const noexcept
+ {
+ return const_reverse_iterator (cend());
+ }
+
+ const_reverse_iterator
+ crbegin() const noexcept
+ {
+ return const_reverse_iterator (cend());
+ }
+
+ reverse_iterator
+ rend() noexcept
+ {
+ return reverse_iterator (begin());
+ }
+
+ const_reverse_iterator
+ rend() const noexcept
+ {
+ return const_reverse_iterator (cbegin());
+ }
+
+ const_reverse_iterator
+ crend() const noexcept
+ {
+ return const_reverse_iterator (cbegin());
+ }
+
+ //
+ // Capacity
+ //
+
+ bool
+ empty() const noexcept
+ {
+ return m_size == 0;
+ }
+
+ size_type
+ size() const noexcept
+ {
+ return m_size;
+ }
+
+ size_type
+ max_size() const noexcept
+ {
+ return size();
+ }
+
+ size_type
+ capacity() const noexcept
+ {
+ return size();
+ }
+
+ size_type bytes() const
+ {
+ return m_size * sizeof(T);
+ }
+
+ //
+ // Modifiers
+ //
+
+ template
+ friend
+ void
+ swap (memory_buffer & lhs,
+ memory_buffer & rhs) noexcept;
+};
+
+//------------------------------------------------------------------------------
+
+template
+void
+swap (memory_buffer & lhs,
+ memory_buffer & rhs) noexcept
+{
+ std::swap (lhs.m_base, rhs.m_base);
+ std::swap (lhs.m_size, rhs.m_size);
+}
+
+template
+inline
+bool
+operator== (memory_buffer const& lhs,
+ memory_buffer const& rhs)
+{
+ return std::equal (lhs.cbegin(), lhs.cend(),
+ rhs.cbegin(), rhs.cend());
+}
+
+template
+inline
+bool
+operator!= (memory_buffer const& lhs,
+ memory_buffer const& rhs)
+{
+ return ! (lhs == rhs);
+}
+
+template
+inline
+bool
+operator< (memory_buffer const& lhs,
+ memory_buffer const& rhs)
+{
+ return std::lexicographical_compare (
+ lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
+}
+
+template
+inline
+bool
+operator>= (memory_buffer const& lhs,
+ memory_buffer const& rhs)
+{
+ return ! (lhs < rhs);
+}
+
+template
+inline
+bool
+operator> (memory_buffer const& lhs,
+ memory_buffer const& rhs)
+{
+ return rhs < lhs;
+}
+
+template
+inline
+bool
+operator<= (memory_buffer const& lhs,
+ memory_buffer const& rhs)
+{
+ return ! (rhs < lhs);
+}
+
+}
+}
+
+#endif
diff --git a/beast/asio/shared_handler.h b/beast/asio/shared_handler.h
index 21a9c4aaf..78e56d19c 100644
--- a/beast/asio/shared_handler.h
+++ b/beast/asio/shared_handler.h
@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_SHARED_HANDLER_H_INCLUDED
#define BEAST_ASIO_SHARED_HANDLER_H_INCLUDED
+#include "../Config.h"
+
#include "../mpl/IsCallPossible.h"
#include
@@ -260,9 +262,7 @@ public:
//------------------------------------------------------------------------------
/** Handler shared reference that provides io_service execution guarantees. */
-template <
- class Signature
->
+template
class shared_handler
{
private:
@@ -318,6 +318,7 @@ public:
operator= (std::nullptr_t)
{
m_ptr = nullptr;
+ return *this;
}
shared_handler&
@@ -327,15 +328,17 @@ public:
return *this;
}
- bool
- empty() const
+ shared_handler&
+ operator= (shared_handler&& rhs)
{
- return ! m_ptr.operator bool();
+ m_ptr = std::move (rhs.m_ptr);
+ return *this;
}
- operator bool() const
+ explicit
+ operator bool() const noexcept
{
- return !empty();
+ return m_ptr.operator bool();
}
void
diff --git a/beast/asio/socket_wrapper.h b/beast/asio/socket_wrapper.h
index 9182943c5..136ad0898 100644
--- a/beast/asio/socket_wrapper.h
+++ b/beast/asio/socket_wrapper.h
@@ -225,14 +225,9 @@ private:
boost::asio::io_service& get_io_service () override
{
-#if 0
- // Apparently has_get_io_service always results in false
return get_io_service (
Enabled > ());
-#else
- return get_io_service (std::true_type ());
-#endif
}
boost::asio::io_service& get_io_service (
diff --git a/beast/asio/tests/enable_wait_for_async.test.cpp b/beast/asio/tests/enable_wait_for_async.test.cpp
new file mode 100644
index 000000000..1822e446d
--- /dev/null
+++ b/beast/asio/tests/enable_wait_for_async.test.cpp
@@ -0,0 +1,108 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "BeastConfig.h"
+
+#include "../../../modules/beast_core/beast_core.h" // for UnitTest
+
+#include "../bind_handler.h"
+#include "../enable_wait_for_async.h"
+
+#include
+
+namespace beast {
+
+class enable_wait_for_async_Tests : public UnitTest
+{
+public:
+ typedef boost::system::error_code error_code;
+
+ void test()
+ {
+ struct handler
+ {
+ void operator()(error_code)
+ {
+ }
+ };
+
+ struct owner : asio::enable_wait_for_async
+ {
+ bool notified;
+
+ owner()
+ : notified (false)
+ {
+ }
+
+ void operator()()
+ {
+ {
+ boost::asio::io_service ios;
+ ios.post (asio::bind_handler (handler(),
+ error_code()));
+ ios.run();
+ ios.reset();
+ wait_for_async();
+ }
+
+ {
+ boost::asio::io_service ios;
+ ios.post (wrap_with_counter (asio::bind_handler (
+ handler(), error_code())));
+ ios.run();
+ wait_for_async();
+ }
+
+ {
+ boost::asio::io_service ios;
+ handler h;
+ ios.post (wrap_with_counter (std::bind (
+ &handler::operator(), &h,
+ error_code())));
+ ios.run();
+ wait_for_async();
+ }
+ }
+
+ void on_wait_for_async()
+ {
+ notified = true;
+ }
+ };
+
+ beginTestCase ("wait_for_async");
+ owner o;
+ o();
+ expect (o.notified);
+ }
+
+ void runTest()
+ {
+ test();
+ }
+
+ enable_wait_for_async_Tests() : UnitTest ("enable_wait_for_async", "beast")
+ {
+ }
+};
+
+static enable_wait_for_async_Tests enable_wait_for_async_tests;
+
+}
diff --git a/beast/cyclic_iterator.h b/beast/container/cyclic_iterator.h
similarity index 100%
rename from beast/cyclic_iterator.h
rename to beast/container/cyclic_iterator.h
diff --git a/beast/crypto/UnsignedInteger.h b/beast/crypto/UnsignedInteger.h
index 09a87c74f..b276e1286 100644
--- a/beast/crypto/UnsignedInteger.h
+++ b/beast/crypto/UnsignedInteger.h
@@ -20,7 +20,6 @@
#ifndef BEAST_CRYPTO_UNSIGNEDINTEGER_H_INCLUDED
#define BEAST_CRYPTO_UNSIGNEDINTEGER_H_INCLUDED
-#include "../SafeBool.h"
#include "UnsignedIntegerCalc.h"
#include "MurmurHash.h"
@@ -38,7 +37,7 @@ namespace beast {
may not be aligned.
*/
template
-class UnsignedInteger : public SafeBool >
+class UnsignedInteger
{
public:
/** Constant for determining the number of bytes. */
@@ -201,9 +200,9 @@ public:
/** Support conversion to `bool`.
@return `true` if any bit is non-zero.
- @see SafeBool
*/
- bool asBoolean () const
+ explicit
+ operator bool() const
{
return isNotZero ();
}
diff --git a/beast/crypto/UnsignedIntegerCalc.h b/beast/crypto/UnsignedIntegerCalc.h
index fffadfab7..ef1d48120 100644
--- a/beast/crypto/UnsignedIntegerCalc.h
+++ b/beast/crypto/UnsignedIntegerCalc.h
@@ -60,7 +60,7 @@ struct DoubleWidthUInt
which return results by value cannot be included in the interface.
*/
template
-class UnsignedIntegerCalc : public SafeBool >
+class UnsignedIntegerCalc
{
public:
typedef typename detail::DoubleWidthUInt ::type UIntBig;
@@ -182,7 +182,8 @@ public:
}
/** Safe conversion to `bool`, `true` means a non-zero value. */
- bool asBoolean () const
+ explicit
+ operator bool() const
{
return isNotZero ();
}
diff --git a/beast/mpl/IsCallPossible.h b/beast/mpl/IsCallPossible.h
index bc85184ae..ae40180fc 100644
--- a/beast/mpl/IsCallPossible.h
+++ b/beast/mpl/IsCallPossible.h
@@ -20,6 +20,8 @@
#ifndef BEAST_MPL_ISCALLPOSSIBLE_H_INCLUDED
#define BEAST_MPL_ISCALLPOSSIBLE_H_INCLUDED
+#include "../cxx14/type_traits.h" //
+
namespace beast {
namespace mpl {
@@ -160,10 +162,11 @@ struct trait_name##_detail
BEAST_DEFINE_HAS_MEMBER_FUNCTION(has_member, member_function_name); \
}; \
\
-template \
+template \
struct trait_name \
{ \
- private: \
+private: \
+ typedef std::remove_reference_t T; \
class yes {}; \
class no { yes m[2]; }; \
struct derived : public T \
@@ -197,6 +200,18 @@ struct trait_name
static const bool value = false; \
}; \
\
+ template \
+ struct impl \
+ { \
+ static typename beast::mpl::is_call_possible_detail::add_reference::type test_me; \
+ \
+ static const bool value = \
+ sizeof( \
+ return_value_check::deduce( \
+ (test_me.member_function_name(), beast::mpl::is_call_possible_detail::void_exp_result())) \
+ ) == sizeof(yes); \
+ }; \
+ \
template \
struct impl \
{ \
diff --git a/beast/net/BufferType.h b/beast/net/BufferType.h
deleted file mode 100644
index ae5c24004..000000000
--- a/beast/net/BufferType.h
+++ /dev/null
@@ -1,106 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_NET_BASICS_BUFFERTYPE_H_INCLUDED
-#define BEAST_NET_BASICS_BUFFERTYPE_H_INCLUDED
-
-#include
-
-namespace beast {
-
-/** General linear memory buffer.
- This wraps the underlying buffer type and provides additional methods
- to create a uniform interface. Specializations allow asio-compatible
- buffers without having to include boost/asio.h.
-*/
-/** @{ */
-template
-class BufferType
-{
-private:
- typedef typename std::conditional ::type pointer_type;
-
- typedef typename std::conditional ::type byte_type;
-
-public:
- typedef std::size_t size_type;
-
- BufferType ()
- : m_data (nullptr)
- , m_size (0)
- {
- }
-
- template
- BufferType (BufferType const& other)
- : m_data (other.template cast ())
- , m_size (other.size ())
- {
- }
-
- BufferType (pointer_type data, std::size_t size) noexcept
- : m_data (data)
- , m_size (size)
- {
- }
-
- BufferType& operator= (BufferType const& other) noexcept
- {
- m_data = other.cast ();
- m_size = other.size ();
- return *this;
- }
-
- template
- BufferType& operator= (
- BufferType const& other) noexcept
- {
- m_data = other.template cast ();
- m_size = other.size ();
- return *this;
- }
-
- template
- T cast () const noexcept
- {
- return static_cast (m_data);
- }
-
- size_type size () const
- {
- return m_size;
- }
-
- BufferType operator+ (size_type n) const noexcept
- {
- return BufferType (cast (),
- size () - std::min (size(), n));
- }
-
-private:
- pointer_type m_data;
- std::size_t m_size;
-};
-/** @} */
-
-}
-
-#endif
diff --git a/beast/net/IPAddress.h b/beast/net/IPAddress.h
index 0211677af..65e8c32b5 100644
--- a/beast/net/IPAddress.h
+++ b/beast/net/IPAddress.h
@@ -40,61 +40,159 @@ class Address
{
public:
/** Create an unspecified IPv4 address. */
- Address ();
+ Address ()
+ : m_type (ipv4)
+ {
+ }
/** Create an IPv4 address. */
- Address (AddressV4 const& addr);
+ Address (AddressV4 const& addr)
+ : m_type (ipv4)
+ , m_v4 (addr)
+ {
+ }
/** Create an IPv6 address. */
- Address (AddressV6 const& addr);
+ Address (AddressV6 const& addr)
+ : m_type (ipv6)
+ , m_v6 (addr)
+ {
+ }
/** Assign a copy from another address in any format. */
/** @{ */
- Address& operator= (AddressV4 const& addr);
- Address& operator= (AddressV6 const& addr);
+ Address&
+ operator= (AddressV4 const& addr)
+ {
+ m_type = ipv4;
+ m_v6 = AddressV6();
+ m_v4 = addr;
+ return *this;
+ }
+
+ Address&
+ operator= (AddressV6 const& addr)
+ {
+ m_type = ipv6;
+ m_v4 = AddressV4();
+ m_v6 = addr;
+ return *this;
+ }
/** @} */
/** Create an Address from a string.
@return A pair with the address, and bool set to `true` on success.
*/
- static std::pair from_string (std::string const& s);
+ static
+ std::pair
+ from_string (std::string const& s);
/** Returns a string representing the address. */
- std::string to_string () const;
+ std::string
+ to_string () const
+ {
+ return (is_v4 ())
+ ? IP::to_string (to_v4())
+ : IP::to_string (to_v6());
+ }
/** Returns `true` if this address represents an IPv4 address. */
- bool is_v4 () const
- { return m_type == ipv4; }
+ bool
+ is_v4 () const
+ {
+ return m_type == ipv4;
+ }
/** Returns `true` if this address represents an IPv6 address. */
- bool is_v6 () const
- { return m_type == ipv6; }
+ bool
+ is_v6() const
+ {
+ return m_type == ipv6;
+ }
/** Returns the IPv4 address.
Precondition:
- is_v4() returns true
+ is_v4() == `true`
*/
- AddressV4 const& to_v4 () const;
+ AddressV4 const&
+ to_v4 () const
+ {
+ if (m_type != ipv4)
+ throw std::bad_cast();
+ return m_v4;
+ }
+
/** Returns the IPv6 address.
Precondition:
- is_v6() returns true
+ is_v6() == `true`
*/
- AddressV6 const& to_v6 () const;
+ AddressV6 const&
+ to_v6 () const
+ {
+ if (m_type != ipv6)
+ throw std::bad_cast();
+ return m_v6;
+ }
/** Arithmetic comparison. */
/** @{ */
- friend bool operator== (Address const& lhs, Address const& rhs);
- friend bool operator< (Address const& lhs, Address const& rhs);
+ friend
+ bool
+ operator== (Address const& lhs, Address const& rhs)
+ {
+ if (lhs.is_v4 ())
+ {
+ if (rhs.is_v4 ())
+ return lhs.to_v4() == rhs.to_v4();
+ }
+ else
+ {
+ if (rhs.is_v6 ())
+ return lhs.to_v6() == rhs.to_v6();
+ }
- friend bool operator!= (Address const& lhs, Address const& rhs)
- { return ! (lhs == rhs); }
- friend bool operator> (Address const& lhs, Address const& rhs)
- { return rhs < lhs; }
- friend bool operator<= (Address const& lhs, Address const& rhs)
- { return ! (lhs > rhs); }
- friend bool operator>= (Address const& lhs, Address const& rhs)
- { return ! (rhs > lhs); }
+ return false;
+ }
+
+ friend
+ bool
+ operator< (Address const& lhs, Address const& rhs)
+ {
+ if (lhs.m_type < rhs.m_type)
+ return true;
+ if (lhs.is_v4 ())
+ return lhs.to_v4() < rhs.to_v4();
+ return lhs.to_v6() < rhs.to_v6();
+ }
+
+ friend
+ bool
+ operator!= (Address const& lhs, Address const& rhs)
+ {
+ return ! (lhs == rhs);
+ }
+
+ friend
+ bool
+ operator> (Address const& lhs, Address const& rhs)
+ {
+ return rhs < lhs;
+ }
+
+ friend
+ bool
+ operator<= (Address const& lhs, Address const& rhs)
+ {
+ return ! (lhs > rhs);
+ }
+
+ friend
+ bool
+ operator>= (Address const& lhs, Address const& rhs)
+ {
+ return ! (rhs > lhs);
+ }
/** @} */
private:
@@ -114,36 +212,104 @@ private:
// Properties
/** Returns `true` if this is a loopback address. */
-bool is_loopback (Address const& addr);
+inline
+bool
+is_loopback (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_loopback (addr.to_v4 ())
+ : is_loopback (addr.to_v6 ());
+}
/** Returns `true` if the address is unspecified. */
-bool is_unspecified (Address const& addr);
+inline
+bool
+is_unspecified (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_unspecified (addr.to_v4 ())
+ : is_unspecified (addr.to_v6 ());
+}
/** Returns `true` if the address is a multicast address. */
-bool is_multicast (Address const& addr);
+inline
+bool
+is_multicast (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_multicast (addr.to_v4 ())
+ : is_multicast (addr.to_v6 ());
+}
/** Returns `true` if the address is a private unroutable address. */
-bool is_private (Address const& addr);
+inline
+bool
+is_private (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_private (addr.to_v4 ())
+ : is_private (addr.to_v6 ());
+}
/** Returns `true` if the address is a public routable address. */
-bool is_public (Address const& addr);
+inline
+bool
+is_public (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_public (addr.to_v4 ())
+ : is_public (addr.to_v6 ());
+}
//------------------------------------------------------------------------------
/** boost::hash support. */
-std::size_t hash_value (Address const& addr);
+inline
+std::size_t
+hash_value (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? hash_value (addr.to_v4())
+ : hash_value (addr.to_v6());
+}
/** Returns the address represented as a string. */
inline std::string to_string (Address const& addr)
- { return addr.to_string (); }
+{
+ return addr.to_string ();
+}
/** Output stream conversion. */
template
-OutputStream& operator<< (OutputStream& os, Address const& addr)
- { return os << to_string (addr); }
+OutputStream&
+operator<< (OutputStream& os, Address const& addr)
+{
+ return os << to_string (addr);
+}
/** Input stream conversion. */
-std::istream& operator>> (std::istream& is, Address& addr);
+inline
+std::istream&
+operator>> (std::istream& is, Address& addr)
+{
+ // VFALCO TODO Support ipv6!
+ AddressV4 addrv4;
+ is >> addrv4;
+ addr = Address (addrv4);
+ return is;
+}
+
+inline
+std::pair
+Address::from_string (std::string const& s)
+{
+ std::stringstream is (s);
+ Address addr;
+ is >> addr;
+ if (! is.fail() && is.rdbuf()->in_avail() == 0)
+ return std::make_pair (addr, true);
+ return std::make_pair (Address (), false);
+}
}
}
@@ -154,8 +320,11 @@ namespace std {
template <>
struct hash
{
- std::size_t operator() (beast::IP::Address const& addr) const
- { return hash_value (addr); }
+ std::size_t
+ operator() (beast::IP::Address const& addr) const
+ {
+ return hash_value (addr);
+ }
};
}
diff --git a/beast/net/impl/IPAddress.cpp b/beast/net/impl/IPAddress.cpp
index e01e74c8b..f1edc2a8b 100644
--- a/beast/net/impl/IPAddress.cpp
+++ b/beast/net/impl/IPAddress.cpp
@@ -25,150 +25,6 @@
namespace beast {
namespace IP {
-Address::Address ()
- : m_type (ipv4)
-{
-}
-
-Address::Address (AddressV4 const& addr)
- : m_type (ipv4)
- , m_v4 (addr)
-{
-}
-
-Address::Address (AddressV6 const& addr)
- : m_type (ipv6)
- , m_v6 (addr)
-{
-}
-
-Address& Address::operator= (AddressV4 const& addr)
-{
- m_type = ipv4;
- m_v6 = AddressV6();
- m_v4 = addr;
- return *this;
-}
-
-Address& Address::operator= (AddressV6 const& addr)
-{
- m_type = ipv6;
- m_v4 = AddressV4();
- m_v6 = addr;
- return *this;
-}
-
-std::pair Address::from_string (std::string const& s)
-{
- std::stringstream is (s);
- Address addr;
- is >> addr;
- if (! is.fail() && is.rdbuf()->in_avail() == 0)
- return std::make_pair (addr, true);
- return std::make_pair (Address (), false);
-}
-
-std::string Address::to_string () const
-{
- return (is_v4 ())
- ? IP::to_string (to_v4())
- : IP::to_string (to_v6());
-}
-
-AddressV4 const& Address::to_v4 () const
-{
- if (m_type != ipv4)
- throw std::bad_cast();
- return m_v4;
-}
-
-AddressV6 const& Address::to_v6 () const
-{
- if (m_type != ipv6)
- throw std::bad_cast();
- return m_v6;
-}
-
-bool operator== (Address const& lhs, Address const& rhs)
-{
- if (lhs.is_v4 ())
- {
- if (rhs.is_v4 ())
- return lhs.to_v4() == rhs.to_v4();
- }
- else
- {
- if (rhs.is_v6 ())
- return lhs.to_v6() == rhs.to_v6();
- }
-
- return false;
-}
-
-bool operator< (Address const& lhs, Address const& rhs)
-{
- if (lhs.m_type < rhs.m_type)
- return true;
- if (lhs.is_v4 ())
- return lhs.to_v4() < rhs.to_v4();
- return lhs.to_v6() < rhs.to_v6();
-}
-
-//------------------------------------------------------------------------------
-
-bool is_loopback (Address const& addr)
-{
- return (addr.is_v4 ())
- ? is_loopback (addr.to_v4 ())
- : is_loopback (addr.to_v6 ());
-}
-
-bool is_unspecified (Address const& addr)
-{
- return (addr.is_v4 ())
- ? is_unspecified (addr.to_v4 ())
- : is_unspecified (addr.to_v6 ());
-}
-
-bool is_multicast (Address const& addr)
-{
- return (addr.is_v4 ())
- ? is_multicast (addr.to_v4 ())
- : is_multicast (addr.to_v6 ());
-}
-
-bool is_private (Address const& addr)
-{
- return (addr.is_v4 ())
- ? is_private (addr.to_v4 ())
- : is_private (addr.to_v6 ());
-}
-
-bool is_public (Address const& addr)
-{
- return (addr.is_v4 ())
- ? is_public (addr.to_v4 ())
- : is_public (addr.to_v6 ());
-}
-
-//------------------------------------------------------------------------------
-
-std::size_t hash_value (Address const& addr)
-{
- return (addr.is_v4 ())
- ? hash_value (addr.to_v4())
- : hash_value (addr.to_v6());
-}
-
-std::istream& operator>> (std::istream& is, Address& addr)
-{
- // VFALCO TODO Support ipv6!
- AddressV4 addrv4;
- is >> addrv4;
- addr = Address (addrv4);
- return is;
-}
-
//------------------------------------------------------------------------------
class IPAddressTests : public UnitTest
diff --git a/beast/threads/LockGuard.h b/beast/threads/LockGuard.h
deleted file mode 100644
index a90895ae0..000000000
--- a/beast/threads/LockGuard.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_THREADS_LOCKGUARD_H_INCLUDED
-#define BEAST_THREADS_LOCKGUARD_H_INCLUDED
-
-#include "../Uncopyable.h"
-
-namespace beast {
-
-template
-class LockGuard : public Uncopyable
-{
-public:
- typedef Mutex MutexType;
-
- explicit LockGuard (Mutex const& mutex)
- : m_mutex (mutex)
- {
- m_mutex.lock();
- }
-
- ~LockGuard ()
- {
- m_mutex.unlock();
- }
-
-private:
- Mutex const& m_mutex;
-};
-
-}
-
-#endif
diff --git a/beast/threads/RecursiveMutex.h b/beast/threads/RecursiveMutex.h
index 15a233058..3f7cb59ab 100644
--- a/beast/threads/RecursiveMutex.h
+++ b/beast/threads/RecursiveMutex.h
@@ -25,10 +25,11 @@
#define BEAST_THREADS_RECURSIVEMUTEX_H_INCLUDED
#include "../Config.h"
-#include "LockGuard.h"
#include "UnlockGuard.h"
#include "TryLockGuard.h"
+#include
+
#if ! BEAST_WINDOWS
#include
#endif
@@ -38,7 +39,7 @@ namespace beast {
class RecursiveMutex
{
public:
- typedef LockGuard ScopedLockType;
+ typedef std::lock_guard ScopedLockType;
typedef UnlockGuard ScopedUnlockType;
typedef TryLockGuard ScopedTryLockType;
diff --git a/beast/threads/ScopedWrapperContext.h b/beast/threads/ScopedWrapperContext.h
index 6a0b88324..b8094bfdf 100644
--- a/beast/threads/ScopedWrapperContext.h
+++ b/beast/threads/ScopedWrapperContext.h
@@ -30,19 +30,20 @@ template
class ScopedWrapper
{
public:
- ScopedWrapper (Context const& context, Handler const& handler)
+ ScopedWrapper (Context& context, Handler const& handler)
: m_context (context)
, m_handler (handler)
- { }
+ {
+ }
void operator() ()
{
- ScopedType const scope (m_context);
+ ScopedType scope (m_context);
m_handler();
}
private:
- Context const& m_context;
+ Context& m_context;
Handler m_handler;
};
@@ -55,17 +56,19 @@ template
class ScopedWrapperContext
{
public:
- typedef Context context_type;
- typedef ScopedType scoped_type;
+ typedef Context context_type;
+ typedef ScopedType scoped_type;
class Scope
{
public:
explicit Scope (ScopedWrapperContext const& owner)
: m_scope (owner.m_context)
- { }
+ {
+ }
+
private:
- scoped_type m_scope;
+ scoped_type mutable m_scope;
};
ScopedWrapperContext ()
@@ -74,7 +77,8 @@ public:
template
explicit ScopedWrapperContext (Arg& arg)
: m_context (arg)
- { }
+ {
+ }
template
detail::ScopedWrapper wrap (
@@ -85,7 +89,7 @@ public:
}
private:
- Context m_context;
+ Context mutable m_context;
};
}
diff --git a/beast/threads/SharedMutexAdapter.h b/beast/threads/SharedMutexAdapter.h
index cb28ea51a..8147dc3a1 100644
--- a/beast/threads/SharedMutexAdapter.h
+++ b/beast/threads/SharedMutexAdapter.h
@@ -20,9 +20,10 @@
#ifndef BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED
#define BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED
-#include "LockGuard.h"
#include "SharedLockGuard.h"
+#include
+
namespace beast {
/** Adapts a regular Lockable to conform to the SharedMutex concept.
@@ -35,7 +36,7 @@ class SharedMutexAdapter
{
public:
typedef Mutex MutexType;
- typedef LockGuard LockGuardType;
+ typedef std::lock_guard LockGuardType;
typedef SharedLockGuard SharedLockGuardType;
void lock() const
diff --git a/beast/threads/SpinLock.h b/beast/threads/SpinLock.h
index cbc6e0e95..88e21fcdb 100644
--- a/beast/threads/SpinLock.h
+++ b/beast/threads/SpinLock.h
@@ -25,9 +25,10 @@
#define BEAST_THREADS_SPINLOCK_H_INCLUDED
#include "../Atomic.h"
-#include "LockGuard.h"
#include "UnlockGuard.h"
+#include
+
namespace beast {
//==============================================================================
@@ -47,7 +48,7 @@ class BEAST_API SpinLock : public Uncopyable
{
public:
/** Provides the type of scoped lock to use for locking a SpinLock. */
- typedef LockGuard ScopedLockType;
+ typedef std::lock_guard ScopedLockType;
/** Provides the type of scoped unlocker to use with a SpinLock. */
typedef UnlockGuard ScopedUnlockType;
diff --git a/beast/threads/ThreadLocalValue.h b/beast/threads/ThreadLocalValue.h
index 751062efe..ac8310cd1 100644
--- a/beast/threads/ThreadLocalValue.h
+++ b/beast/threads/ThreadLocalValue.h
@@ -187,8 +187,8 @@ private:
Type object;
};
- mutable Atomic first;
- SpinLock lock;
+ Atomic mutable first;
+ SpinLock mutable lock;
#endif
};
diff --git a/beast/type_traits/maybe_const.h b/beast/type_traits/maybe_const.h
index b72d08e72..95c136b54 100644
--- a/beast/type_traits/maybe_const.h
+++ b/beast/type_traits/maybe_const.h
@@ -33,6 +33,10 @@ struct maybe_const
typename std::remove_const ::type>::type type;
};
+/** Alias for omitting `typename`. */
+template
+using maybe_const_t = typename maybe_const ::type;
+
}
#endif
diff --git a/beast/utility/Error.h b/beast/utility/Error.h
index f9b188925..0c095bfc2 100644
--- a/beast/utility/Error.h
+++ b/beast/utility/Error.h
@@ -22,7 +22,6 @@
#include "../Config.h"
-#include "../SafeBool.h"
#include "../strings/String.h"
#include
@@ -43,7 +42,6 @@ namespace beast {
*/
class Error
: public std::exception
- , public SafeBool
{
public:
/** Numeric code.
@@ -88,7 +86,10 @@ public:
Code code () const;
bool failed () const;
- bool asBoolean () const;
+ explicit operator bool () const
+ {
+ return code () != success;
+ }
String const getReasonText () const;
String const getSourceFilename () const;
diff --git a/beast/utility/Journal.h b/beast/utility/Journal.h
index d052a59ab..c0782d360 100644
--- a/beast/utility/Journal.h
+++ b/beast/utility/Journal.h
@@ -20,8 +20,6 @@
#ifndef BEAST_UTILITY_JOURNAL_H_INCLUDED
#define BEAST_UTILITY_JOURNAL_H_INCLUDED
-#include "../SafeBool.h"
-
#include
namespace beast {
@@ -150,7 +148,7 @@ public:
//--------------------------------------------------------------------------
- class Stream : public SafeBool
+ class Stream
{
public:
/** Create a stream which produces no output. */
@@ -177,7 +175,12 @@ public:
/** Returns `true` if sink logs anything at this stream's severity. */
/** @{ */
bool active() const;
- bool asBoolean() const;
+
+ explicit
+ operator bool() const
+ {
+ return ! m_disabled;
+ }
/** @} */
/** Output stream support. */
diff --git a/beast/utility/impl/Error.cpp b/beast/utility/impl/Error.cpp
index 9083413fe..7751c4176 100644
--- a/beast/utility/impl/Error.cpp
+++ b/beast/utility/impl/Error.cpp
@@ -81,11 +81,6 @@ bool Error::failed () const
return code () != success;
}
-bool Error::asBoolean () const
-{
- return code () != success;
-}
-
String const Error::getReasonText () const
{
return m_reasonText;
diff --git a/beast/utility/impl/Journal.cpp b/beast/utility/impl/Journal.cpp
index ed115b07c..42dd56273 100644
--- a/beast/utility/impl/Journal.cpp
+++ b/beast/utility/impl/Journal.cpp
@@ -211,11 +211,6 @@ bool Journal::Stream::active () const
return ! m_disabled && m_sink->active (m_level);
}
-bool Journal::Stream::asBoolean () const
-{
- return active();
-}
-
Journal::Stream& Journal::Stream::operator= (Stream const& other)
{
m_sink = other.m_sink;
diff --git a/modules/beast_asio/protocol/InputParser.h b/modules/beast_asio/protocol/InputParser.h
index 9ab0a0248..97962b7ef 100644
--- a/modules/beast_asio/protocol/InputParser.h
+++ b/modules/beast_asio/protocol/InputParser.h
@@ -30,7 +30,7 @@ namespace InputParser {
Or you can use stop() to decide if you should return.
After a stop you can use failed () to determine if parsing failed.
*/
-struct State : SafeBool
+struct State
{
enum State_t
{
@@ -54,7 +54,7 @@ struct State : SafeBool
bool stop () const noexcept { return m_state != pass; }
bool passed () const noexcept { return m_state == pass; }
bool failed () const noexcept { return m_state == fail; }
- bool asBoolean () const noexcept { return m_state == pass; } // for SafeBool<>
+ explicit operator bool() const noexcept { return m_state == pass; }
private:
State_t m_state;
diff --git a/modules/beast_core/beast_core.cpp b/modules/beast_core/beast_core.cpp
index 156cf509c..37a36b738 100644
--- a/modules/beast_core/beast_core.cpp
+++ b/modules/beast_core/beast_core.cpp
@@ -163,7 +163,6 @@ namespace beast
#include "misc/Uuid.cpp"
#include "network/MACAddress.cpp"
-#include "network/NamedPipe.cpp"
#include "network/Socket.cpp"
#include "streams/BufferedInputStream.cpp"
@@ -188,7 +187,6 @@ namespace beast
#include "thread/Workers.cpp"
#include "threads/ChildProcess.cpp"
-#include "threads/ReadWriteLock.cpp"
#include "threads/SpinDelay.cpp"
#include "time/PerformanceCounter.cpp"
@@ -218,7 +216,6 @@ namespace beast
#if ! BEAST_WINDOWS
#include "native/posix_SharedCode.h"
-#include "native/posix_NamedPipe.cpp"
#endif
#if BEAST_MAC || BEAST_IOS
diff --git a/modules/beast_core/beast_core.h b/modules/beast_core/beast_core.h
index de35a6be8..a5d6ab17c 100644
--- a/modules/beast_core/beast_core.h
+++ b/modules/beast_core/beast_core.h
@@ -55,7 +55,6 @@
#include "../../beast/Memory.h"
#include "../../beast/Intrusive.h"
#include "../../beast/Net.h"
-#include "../../beast/SafeBool.h"
#include "../../beast/Strings.h"
#include "../../beast/TypeTraits.h"
#include "../../beast/Threads.h"
@@ -181,8 +180,6 @@ class FileOutputStream;
#include "misc/Uuid.h"
#include "misc/WindowsRegistry.h"
#include "network/MACAddress.h"
-#include "threads/ReadWriteLock.h"
-#include "network/NamedPipe.h"
#include "network/Socket.h"
#include "streams/BufferedInputStream.h"
#include "streams/MemoryInputStream.h"
@@ -198,8 +195,6 @@ class FileOutputStream;
#include "threads/HighResolutionTimer.h"
#include "threads/InterProcessLock.h"
#include "threads/Process.h"
-#include "threads/ScopedReadLock.h"
-#include "threads/ScopedWriteLock.h"
#include "diagnostic/UnitTest.h"
#include "xml/XmlDocument.h"
#include "xml/XmlElement.h"
diff --git a/modules/beast_core/diagnostic/UnitTest.cpp b/modules/beast_core/diagnostic/UnitTest.cpp
index 94d74f5d2..5d94ab60b 100644
--- a/modules/beast_core/diagnostic/UnitTest.cpp
+++ b/modules/beast_core/diagnostic/UnitTest.cpp
@@ -130,7 +130,7 @@ void UnitTest::beginTestCase (String const& name)
m_case = new Case (name, m_className);
}
-bool UnitTest::expect (bool trueCondition, String const& failureMessage)
+bool UnitTest::expect_bool (bool trueCondition, String const& failureMessage)
{
if (trueCondition)
{
@@ -144,7 +144,7 @@ bool UnitTest::expect (bool trueCondition, String const& failureMessage)
return trueCondition;
}
-bool UnitTest::unexpected (bool falseCondition, String const& failureMessage)
+bool UnitTest::unexpected_bool (bool falseCondition, String const& failureMessage)
{
return expect (! falseCondition, failureMessage);
}
diff --git a/modules/beast_core/diagnostic/UnitTest.h b/modules/beast_core/diagnostic/UnitTest.h
index 02dc832b0..71c3091bf 100644
--- a/modules/beast_core/diagnostic/UnitTest.h
+++ b/modules/beast_core/diagnostic/UnitTest.h
@@ -266,17 +266,35 @@ public:
If Suite is true, a pass is logged; if it's false, a failure is logged.
If the failure message is specified, it will be written to the log if the test fails.
+
+ Requirements:
+ Condition must be explicitly convertible to bool
*/
- bool expect (bool trueCondition, String const& failureMessage = String::empty);
+ template
+ bool expect (Condition trueCondition, String const& failureMessage = String::empty)
+ {
+ return expect_bool (!!trueCondition, failureMessage);
+ }
+
+ bool expect_bool (bool trueCondition, String const& failureMessage);
/** Checks that the result of a test is false, and logs this result.
This is basically the opposite of expect().
@see expect
- */
- bool unexpected (bool falseCondition, String const& failureMessage = String::empty);
+ Requirements:
+ Condition must be explicitly convertible to bool
+ */
+ template
+ bool unexpected (Condition falseCondition, String const& failureMessage = String::empty)
+ {
+ return unexpected_bool (!!falseCondition, failureMessage);
+ }
+
+ bool unexpected_bool (bool falseCondition, String const& failureMessage);
+
/** Compares two values, and if they don't match, prints out a message containing the
expected and actual result values.
*/
diff --git a/modules/beast_core/native/posix_NamedPipe.cpp b/modules/beast_core/native/posix_NamedPipe.cpp
deleted file mode 100644
index 227dbc79e..000000000
--- a/modules/beast_core/native/posix_NamedPipe.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Portions of this file are from JUCE.
- Copyright (c) 2013 - Raw Material Software Ltd.
- Please visit http://www.juce.com
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-class NamedPipe::Pimpl : LeakChecked , public Uncopyable
-{
-public:
- Pimpl (const String& pipePath, bool createPipe)
- : pipeInName (pipePath + "_in"),
- pipeOutName (pipePath + "_out"),
- pipeIn (-1), pipeOut (-1),
- createdPipe (createPipe),
- stopReadOperation (false)
- {
- signal (SIGPIPE, signalHandler);
- beast_siginterrupt (SIGPIPE, 1);
- }
-
- ~Pimpl()
- {
- if (pipeIn != -1) ::close (pipeIn);
- if (pipeOut != -1) ::close (pipeOut);
-
- if (createdPipe)
- {
- unlink (pipeInName.toUTF8());
- unlink (pipeOutName.toUTF8());
- }
- }
-
- int read (char* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
- {
- const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
-
- if (pipeIn == -1)
- {
- pipeIn = openPipe (createdPipe ? pipeInName : pipeOutName, O_RDWR | O_NONBLOCK, timeoutEnd);
-
- if (pipeIn == -1)
- return -1;
- }
-
- int bytesRead = 0;
-
- while (bytesRead < maxBytesToRead)
- {
- const int bytesThisTime = maxBytesToRead - bytesRead;
- const int numRead = (int) ::read (pipeIn, destBuffer, (size_t) bytesThisTime);
-
- if (numRead <= 0)
- {
- if (errno != EWOULDBLOCK || stopReadOperation || hasExpired (timeoutEnd))
- return -1;
-
- const int maxWaitingTime = 30;
- waitForInput (pipeIn, timeoutEnd == 0 ? maxWaitingTime
- : bmin (maxWaitingTime,
- (int) (timeoutEnd - Time::getMillisecondCounter())));
- continue;
- }
-
- bytesRead += numRead;
- destBuffer += numRead;
- }
-
- return bytesRead;
- }
-
- int write (const char* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
- {
- const uint32 timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
-
- if (pipeOut == -1)
- {
- pipeOut = openPipe (createdPipe ? pipeOutName : pipeInName, O_WRONLY, timeoutEnd);
-
- if (pipeOut == -1)
- return -1;
- }
-
- int bytesWritten = 0;
-
- while (bytesWritten < numBytesToWrite && ! hasExpired (timeoutEnd))
- {
- const int bytesThisTime = numBytesToWrite - bytesWritten;
- const int numWritten = (int) ::write (pipeOut, sourceBuffer, (size_t) bytesThisTime);
-
- if (numWritten <= 0)
- return -1;
-
- bytesWritten += numWritten;
- sourceBuffer += numWritten;
- }
-
- return bytesWritten;
- }
-
- bool createFifos() const
- {
- return (mkfifo (pipeInName .toUTF8(), 0666) == 0 || errno == EEXIST)
- && (mkfifo (pipeOutName.toUTF8(), 0666) == 0 || errno == EEXIST);
- }
-
- const String pipeInName, pipeOutName;
- int pipeIn, pipeOut;
-
- const bool createdPipe;
- bool stopReadOperation;
-
-private:
- static void signalHandler (int) {}
-
- static uint32 getTimeoutEnd (const int timeOutMilliseconds)
- {
- return timeOutMilliseconds >= 0 ? Time::getMillisecondCounter() + (uint32) timeOutMilliseconds : 0;
- }
-
- static bool hasExpired (const uint32 timeoutEnd)
- {
- return timeoutEnd != 0 && Time::getMillisecondCounter() >= timeoutEnd;
- }
-
- int openPipe (const String& name, int flags, const uint32 timeoutEnd)
- {
- for (;;)
- {
- const int p = ::open (name.toUTF8(), flags);
-
- if (p != -1 || hasExpired (timeoutEnd) || stopReadOperation)
- return p;
-
- Thread::sleep (2);
- }
- }
-
- static void waitForInput (const int handle, const int timeoutMsecs) noexcept
- {
- struct timeval timeout;
- timeout.tv_sec = timeoutMsecs / 1000;
- timeout.tv_usec = (timeoutMsecs % 1000) * 1000;
-
- fd_set rset;
- FD_ZERO (&rset);
- FD_SET (handle, &rset);
-
- select (handle + 1, &rset, nullptr, 0, &timeout);
- }
-};
-
-void NamedPipe::close()
-{
- if (pimpl != nullptr)
- {
- pimpl->stopReadOperation = true;
-
- char buffer[1] = { 0 };
- ssize_t done = ::write (pimpl->pipeIn, buffer, 1);
- (void) done;
-
- ScopedWriteLock sl (lock);
- pimpl = nullptr;
- }
-}
-
-bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
-{
- #if BEAST_IOS
- pimpl = new Pimpl (File::getSpecialLocation (File::tempDirectory)
- .getChildFile (File::createLegalFileName (pipeName)).getFullPathName(), createPipe);
- #else
- pimpl = new Pimpl ("/tmp/" + File::createLegalFileName (pipeName), createPipe);
- #endif
-
- if (createPipe && ! pimpl->createFifos())
- {
- pimpl = nullptr;
- return false;
- }
-
- return true;
-}
-
-int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
-{
- ScopedReadLock sl (lock);
- return pimpl != nullptr ? pimpl->read (static_cast (destBuffer), maxBytesToRead, timeOutMilliseconds) : -1;
-}
-
-int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
-{
- ScopedReadLock sl (lock);
- return pimpl != nullptr ? pimpl->write (static_cast (sourceBuffer), numBytesToWrite, timeOutMilliseconds) : -1;
-}
diff --git a/modules/beast_core/native/win32_Files.cpp b/modules/beast_core/native/win32_Files.cpp
index e3952b82a..5767925b5 100644
--- a/modules/beast_core/native/win32_Files.cpp
+++ b/modules/beast_core/native/win32_Files.cpp
@@ -883,226 +883,3 @@ void File::revealToUser() const
}
}
}
-
-//==============================================================================
-class NamedPipe::Pimpl : LeakChecked , public Uncopyable
-{
-public:
- Pimpl (const String& pipeName, const bool createPipe)
- : filename ("\\\\.\\pipe\\" + File::createLegalFileName (pipeName)),
- pipeH (INVALID_HANDLE_VALUE),
- cancelEvent (CreateEvent (0, FALSE, FALSE, 0)),
- connected (false), ownsPipe (createPipe), shouldStop (false)
- {
- if (createPipe)
- pipeH = CreateNamedPipe (filename.toWideCharPointer(),
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
- PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, 0);
- }
-
- ~Pimpl()
- {
- disconnectPipe();
-
- if (pipeH != INVALID_HANDLE_VALUE)
- CloseHandle (pipeH);
-
- CloseHandle (cancelEvent);
- }
-
- bool connect (const int timeOutMs)
- {
- if (! ownsPipe)
- {
- if (pipeH != INVALID_HANDLE_VALUE)
- return true;
-
- const Time timeOutEnd (Time::getCurrentTime() + RelativeTime::milliseconds (timeOutMs));
-
- for (;;)
- {
- {
- const ScopedLock sl (createFileLock);
-
- if (pipeH == INVALID_HANDLE_VALUE)
- pipeH = CreateFile (filename.toWideCharPointer(),
- GENERIC_READ | GENERIC_WRITE, 0, 0,
- OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
- }
-
- if (pipeH != INVALID_HANDLE_VALUE)
- return true;
-
- if (shouldStop || (timeOutMs >= 0 && Time::getCurrentTime() > timeOutEnd))
- return false;
-
- Thread::sleep (1);
- }
- }
-
- if (! connected)
- {
- OverlappedEvent over;
-
- if (ConnectNamedPipe (pipeH, &over.over) == 0)
- {
- switch (GetLastError())
- {
- case ERROR_PIPE_CONNECTED: connected = true; break;
- case ERROR_IO_PENDING:
- case ERROR_PIPE_LISTENING: connected = waitForIO (over, timeOutMs); break;
- default: break;
- }
- }
- }
-
- return connected;
- }
-
- void disconnectPipe()
- {
- if (ownsPipe && connected)
- {
- DisconnectNamedPipe (pipeH);
- connected = false;
- }
- }
-
- int read (void* destBuffer, const int maxBytesToRead, const int timeOutMilliseconds)
- {
- while (connect (timeOutMilliseconds))
- {
- if (maxBytesToRead <= 0)
- return 0;
-
- OverlappedEvent over;
- unsigned long numRead;
-
- if (ReadFile (pipeH, destBuffer, (DWORD) maxBytesToRead, &numRead, &over.over))
- return (int) numRead;
-
- const DWORD lastError = GetLastError();
-
- if (lastError == ERROR_IO_PENDING)
- {
- if (! waitForIO (over, timeOutMilliseconds))
- return -1;
-
- if (GetOverlappedResult (pipeH, &over.over, &numRead, FALSE))
- return (int) numRead;
- }
-
- if (ownsPipe && (GetLastError() == ERROR_BROKEN_PIPE || GetLastError() == ERROR_PIPE_NOT_CONNECTED))
- disconnectPipe();
- else
- break;
- }
-
- return -1;
- }
-
- int write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
- {
- if (connect (timeOutMilliseconds))
- {
- if (numBytesToWrite <= 0)
- return 0;
-
- OverlappedEvent over;
- unsigned long numWritten;
-
- if (WriteFile (pipeH, sourceBuffer, (DWORD) numBytesToWrite, &numWritten, &over.over))
- return (int) numWritten;
-
- if (GetLastError() == ERROR_IO_PENDING)
- {
- if (! waitForIO (over, timeOutMilliseconds))
- return -1;
-
- if (GetOverlappedResult (pipeH, &over.over, &numWritten, FALSE))
- return (int) numWritten;
-
- if (GetLastError() == ERROR_BROKEN_PIPE && ownsPipe)
- disconnectPipe();
- }
- }
-
- return -1;
- }
-
- const String filename;
- HANDLE pipeH, cancelEvent;
- bool connected, ownsPipe, shouldStop;
- CriticalSection createFileLock;
-
-private:
- struct OverlappedEvent
- {
- OverlappedEvent()
- {
- zerostruct (over);
- over.hEvent = CreateEvent (0, TRUE, FALSE, 0);
- }
-
- ~OverlappedEvent()
- {
- CloseHandle (over.hEvent);
- }
-
- OVERLAPPED over;
- };
-
- bool waitForIO (OverlappedEvent& over, int timeOutMilliseconds)
- {
- if (shouldStop)
- return false;
-
- HANDLE handles[] = { over.over.hEvent, cancelEvent };
- DWORD waitResult = WaitForMultipleObjects (2, handles, FALSE,
- timeOutMilliseconds >= 0 ? timeOutMilliseconds
- : INFINITE);
-
- if (waitResult == WAIT_OBJECT_0)
- return true;
-
- CancelIo (pipeH);
- return false;
- }
-};
-
-void NamedPipe::close()
-{
- if (pimpl != nullptr)
- {
- pimpl->shouldStop = true;
- SetEvent (pimpl->cancelEvent);
-
- ScopedWriteLock sl (lock);
- pimpl = nullptr;
- }
-}
-
-bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
-{
- pimpl = new Pimpl (pipeName, createPipe);
-
- if (createPipe && pimpl->pipeH == INVALID_HANDLE_VALUE)
- {
- pimpl = nullptr;
- return false;
- }
-
- return true;
-}
-
-int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
-{
- ScopedReadLock sl (lock);
- return pimpl != nullptr ? pimpl->read (destBuffer, maxBytesToRead, timeOutMilliseconds) : -1;
-}
-
-int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
-{
- ScopedReadLock sl (lock);
- return pimpl != nullptr ? pimpl->write (sourceBuffer, numBytesToWrite, timeOutMilliseconds) : -1;
-}
diff --git a/modules/beast_core/thread/impl/TrackedMutex.cpp b/modules/beast_core/thread/impl/TrackedMutex.cpp
index 98da8cf0d..0978d402a 100644
--- a/modules/beast_core/thread/impl/TrackedMutex.cpp
+++ b/modules/beast_core/thread/impl/TrackedMutex.cpp
@@ -112,7 +112,7 @@ bool TrackedMutex::Record::isNotNull () const noexcept
return m_mutexName != "";
}
-bool TrackedMutex::Record::asBoolean () const noexcept
+TrackedMutex::Record::operator bool() const noexcept
{
return isNotNull ();
}
@@ -170,7 +170,7 @@ bool TrackedMutex::Agent::isNotNull () const noexcept
return m_thread != nullptr;
}
-bool TrackedMutex::Agent::asBoolean () const noexcept
+TrackedMutex::Agent::operator bool() const noexcept
{
return isNotNull ();
}
diff --git a/modules/beast_core/thread/impl/TrackedMutex.h b/modules/beast_core/thread/impl/TrackedMutex.h
index 783c2014d..30e797f28 100644
--- a/modules/beast_core/thread/impl/TrackedMutex.h
+++ b/modules/beast_core/thread/impl/TrackedMutex.h
@@ -32,7 +32,7 @@ public:
/** A triplet identifying a mutex, a thread, and source code location.
*/
- class Record : public SafeBool
+ class Record
{
public:
Record () noexcept;
@@ -41,7 +41,7 @@ public:
bool isNull () const noexcept;
bool isNotNull () const noexcept;
- bool asBoolean () const noexcept;
+ explicit operator bool() const noexcept;
/** Returns the name of the mutex.
Since the Mutex may not exist after the Record record is
@@ -76,7 +76,7 @@ public:
//--------------------------------------------------------------------------
/** Describes a thread that can acquire mutexes. */
- class Agent : public SafeBool
+ class Agent
{
public:
Agent () noexcept;
@@ -85,7 +85,7 @@ public:
bool isNull () const noexcept;
bool isNotNull () const noexcept;
- bool asBoolean () const noexcept;
+ explicit operator bool() const noexcept;
/** Returns the name of the thread.
The name is generated at the time the Agent record is created,
diff --git a/modules/beast_core/threads/ReadWriteLock.cpp b/modules/beast_core/threads/ReadWriteLock.cpp
deleted file mode 100644
index fbc784a24..000000000
--- a/modules/beast_core/threads/ReadWriteLock.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Portions of this file are from JUCE.
- Copyright (c) 2013 - Raw Material Software Ltd.
- Please visit http://www.juce.com
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-ReadWriteLock::ReadWriteLock() noexcept
- : numWaitingWriters (0),
- numWriters (0),
- writerThreadId (0)
-{
- readerThreads.ensureStorageAllocated (16);
-}
-
-ReadWriteLock::~ReadWriteLock() noexcept
-{
- bassert (readerThreads.size() == 0);
- bassert (numWriters == 0);
-}
-
-//==============================================================================
-void ReadWriteLock::enterRead() const noexcept
-{
- while (! tryEnterRead())
- waitEvent.wait (100);
-}
-
-bool ReadWriteLock::tryEnterRead() const noexcept
-{
- const Thread::ThreadID threadId = Thread::getCurrentThreadId();
-
- const SpinLock::ScopedLockType sl (accessLock);
-
- for (int i = 0; i < readerThreads.size(); ++i)
- {
- ThreadRecursionCount& trc = readerThreads.getReference(i);
-
- if (trc.threadID == threadId)
- {
- trc.count++;
- return true;
- }
- }
-
- if (numWriters + numWaitingWriters == 0
- || (threadId == writerThreadId && numWriters > 0))
- {
- ThreadRecursionCount trc = { threadId, 1 };
- readerThreads.add (trc);
- return true;
- }
-
- return false;
-}
-
-void ReadWriteLock::exitRead() const noexcept
-{
- const Thread::ThreadID threadId = Thread::getCurrentThreadId();
- const SpinLock::ScopedLockType sl (accessLock);
-
- for (int i = 0; i < readerThreads.size(); ++i)
- {
- ThreadRecursionCount& trc = readerThreads.getReference(i);
-
- if (trc.threadID == threadId)
- {
- if (--(trc.count) == 0)
- {
- readerThreads.remove (i);
- waitEvent.signal();
- }
-
- return;
- }
- }
-
- bassertfalse; // unlocking a lock that wasn't locked..
-}
-
-//==============================================================================
-void ReadWriteLock::enterWrite() const noexcept
-{
- const Thread::ThreadID threadId = Thread::getCurrentThreadId();
- const SpinLock::ScopedLockType sl (accessLock);
-
- for (;;)
- {
- if (readerThreads.size() + numWriters == 0
- || threadId == writerThreadId
- || (readerThreads.size() == 1
- && readerThreads.getReference(0).threadID == threadId))
- {
- writerThreadId = threadId;
- ++numWriters;
- break;
- }
-
- ++numWaitingWriters;
- accessLock.exit();
- waitEvent.wait (100);
- accessLock.enter();
- --numWaitingWriters;
- }
-}
-
-bool ReadWriteLock::tryEnterWrite() const noexcept
-{
- const Thread::ThreadID threadId = Thread::getCurrentThreadId();
- const SpinLock::ScopedLockType sl (accessLock);
-
- if (readerThreads.size() + numWriters == 0
- || threadId == writerThreadId
- || (readerThreads.size() == 1
- && readerThreads.getReference(0).threadID == threadId))
- {
- writerThreadId = threadId;
- ++numWriters;
- return true;
- }
-
- return false;
-}
-
-void ReadWriteLock::exitWrite() const noexcept
-{
- const SpinLock::ScopedLockType sl (accessLock);
-
- // check this thread actually had the lock..
- bassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId());
-
- if (--numWriters == 0)
- {
- writerThreadId = 0;
- waitEvent.signal();
- }
-}
diff --git a/modules/beast_core/threads/ReadWriteLock.h b/modules/beast_core/threads/ReadWriteLock.h
deleted file mode 100644
index e1c0442f9..000000000
--- a/modules/beast_core/threads/ReadWriteLock.h
+++ /dev/null
@@ -1,145 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Portions of this file are from JUCE.
- Copyright (c) 2013 - Raw Material Software Ltd.
- Please visit http://www.juce.com
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_READWRITELOCK_H_INCLUDED
-#define BEAST_READWRITELOCK_H_INCLUDED
-
-//==============================================================================
-/**
- A critical section that allows multiple simultaneous readers.
-
- Features of this type of lock are:
-
- - Multiple readers can hold the lock at the same time, but only one writer
- can hold it at once.
- - Writers trying to gain the lock will be blocked until all readers and writers
- have released it
- - Readers trying to gain the lock while a writer is waiting to acquire it will be
- blocked until the writer has obtained and released it
- - If a thread already has a read lock and tries to obtain a write lock, it will succeed if
- there are no other readers
- - If a thread already has the write lock and tries to obtain a read lock, this will succeed.
- - Recursive locking is supported.
-
- @see ScopedReadLock, ScopedWriteLock, CriticalSection
-*/
-class BEAST_API ReadWriteLock : public Uncopyable
-{
-public:
- //==============================================================================
- /**
- Creates a ReadWriteLock object.
- */
- ReadWriteLock() noexcept;
-
- /** Destructor.
-
- If the object is deleted whilst locked, any subsequent behaviour
- is unpredictable.
- */
- ~ReadWriteLock() noexcept;
-
- //==============================================================================
- /** Locks this object for reading.
-
- Multiple threads can simulaneously lock the object for reading, but if another
- thread has it locked for writing, then this will block until it releases the
- lock.
-
- @see exitRead, ScopedReadLock
- */
- void enterRead() const noexcept;
-
- /** Tries to lock this object for reading.
-
- Multiple threads can simulaneously lock the object for reading, but if another
- thread has it locked for writing, then this will fail and return false.
-
- @returns true if the lock is successfully gained.
- @see exitRead, ScopedReadLock
- */
- bool tryEnterRead() const noexcept;
-
- /** Releases the read-lock.
-
- If the caller thread hasn't got the lock, this can have unpredictable results.
-
- If the enterRead() method has been called multiple times by the thread, each
- call must be matched by a call to exitRead() before other threads will be allowed
- to take over the lock.
-
- @see enterRead, ScopedReadLock
- */
- void exitRead() const noexcept;
-
- //==============================================================================
- /** Locks this object for writing.
-
- This will block until any other threads that have it locked for reading or
- writing have released their lock.
-
- @see exitWrite, ScopedWriteLock
- */
- void enterWrite() const noexcept;
-
- /** Tries to lock this object for writing.
-
- This is like enterWrite(), but doesn't block - it returns true if it manages
- to obtain the lock.
-
- @returns true if the lock is successfully gained.
- @see enterWrite
- */
- bool tryEnterWrite() const noexcept;
-
- /** Releases the write-lock.
-
- If the caller thread hasn't got the lock, this can have unpredictable results.
-
- If the enterWrite() method has been called multiple times by the thread, each
- call must be matched by a call to exit() before other threads will be allowed
- to take over the lock.
-
- @see enterWrite, ScopedWriteLock
- */
- void exitWrite() const noexcept;
-
-
-private:
- //==============================================================================
- SpinLock accessLock;
- WaitableEvent waitEvent;
- mutable int numWaitingWriters, numWriters;
- mutable Thread::ThreadID writerThreadId;
-
- struct ThreadRecursionCount
- {
- Thread::ThreadID threadID;
- int count;
- };
-
- mutable Array readerThreads;
-};
-
-
-#endif // BEAST_READWRITELOCK_H_INCLUDED
diff --git a/modules/beast_core/threads/ScopedReadLock.h b/modules/beast_core/threads/ScopedReadLock.h
deleted file mode 100644
index e20b83980..000000000
--- a/modules/beast_core/threads/ScopedReadLock.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Portions of this file are from JUCE.
- Copyright (c) 2013 - Raw Material Software Ltd.
- Please visit http://www.juce.com
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_SCOPEDREADLOCK_H_INCLUDED
-#define BEAST_SCOPEDREADLOCK_H_INCLUDED
-
-//==============================================================================
-/**
- Automatically locks and unlocks a ReadWriteLock object.
-
- Use one of these as a local variable to control access to a ReadWriteLock.
-
- e.g. @code
-
- ReadWriteLock myLock;
-
- for (;;)
- {
- const ScopedReadLock myScopedLock (myLock);
- // myLock is now locked
-
- ...do some stuff...
-
- // myLock gets unlocked here.
- }
- @endcode
-
- @see ReadWriteLock, ScopedWriteLock
-*/
-class BEAST_API ScopedReadLock : public Uncopyable
-{
-public:
- //==============================================================================
- /** Creates a ScopedReadLock.
-
- As soon as it is created, this will call ReadWriteLock::enterRead(), and
- when the ScopedReadLock object is deleted, the ReadWriteLock will
- be unlocked.
-
- Make sure this object is created and deleted by the same thread,
- otherwise there are no guarantees what will happen! Best just to use it
- as a local stack object, rather than creating one with the new() operator.
- */
- inline explicit ScopedReadLock (const ReadWriteLock& lock) noexcept : lock_ (lock) { lock.enterRead(); }
-
- /** Destructor.
-
- The ReadWriteLock's exitRead() method will be called when the destructor is called.
-
- Make sure this object is created and deleted by the same thread,
- otherwise there are no guarantees what will happen!
- */
- inline ~ScopedReadLock() noexcept { lock_.exitRead(); }
-
-
-private:
- //==============================================================================
- const ReadWriteLock& lock_;
-};
-
-
-#endif // BEAST_SCOPEDREADLOCK_H_INCLUDED
diff --git a/modules/beast_core/threads/ScopedWriteLock.h b/modules/beast_core/threads/ScopedWriteLock.h
deleted file mode 100644
index 9d03482f0..000000000
--- a/modules/beast_core/threads/ScopedWriteLock.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Portions of this file are from JUCE.
- Copyright (c) 2013 - Raw Material Software Ltd.
- Please visit http://www.juce.com
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_SCOPEDWRITELOCK_H_INCLUDED
-#define BEAST_SCOPEDWRITELOCK_H_INCLUDED
-
-//==============================================================================
-/**
- Automatically locks and unlocks a ReadWriteLock object.
-
- Use one of these as a local variable to control access to a ReadWriteLock.
-
- e.g. @code
-
- ReadWriteLock myLock;
-
- for (;;)
- {
- const ScopedWriteLock myScopedLock (myLock);
- // myLock is now locked
-
- ...do some stuff...
-
- // myLock gets unlocked here.
- }
- @endcode
-
- @see ReadWriteLock, ScopedReadLock
-*/
-class BEAST_API ScopedWriteLock : public Uncopyable
-{
-public:
- //==============================================================================
- /** Creates a ScopedWriteLock.
-
- As soon as it is created, this will call ReadWriteLock::enterWrite(), and
- when the ScopedWriteLock object is deleted, the ReadWriteLock will
- be unlocked.
-
- Make sure this object is created and deleted by the same thread,
- otherwise there are no guarantees what will happen! Best just to use it
- as a local stack object, rather than creating one with the new() operator.
- */
- inline explicit ScopedWriteLock (const ReadWriteLock& lock) noexcept : lock_ (lock) { lock.enterWrite(); }
-
- /** Destructor.
-
- The ReadWriteLock's exitWrite() method will be called when the destructor is called.
-
- Make sure this object is created and deleted by the same thread,
- otherwise there are no guarantees what will happen!
- */
- inline ~ScopedWriteLock() noexcept { lock_.exitWrite(); }
-
-
-private:
- //==============================================================================
- const ReadWriteLock& lock_;
-};
-
-
-#endif // BEAST_SCOPEDWRITELOCK_H_INCLUDED