75 changes: 75 additions & 0 deletions include/boost/thread/concurrent_queues/queue_adaptor.hpp
@@ -0,0 +1,75 @@
#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
#define BOOST_THREAD_QUEUE_ADAPTOR_HPP

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/queue_base.hpp>

#include <boost/config/abi_prefix.hpp>

namespace boost
{
namespace concurrent
{

template <typename Queue>
class queue_adaptor : public queue_base<typename Queue::value_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
typedef std::size_t size_type;

// Constructors/Assignment/Destructors

queue_adaptor() {}

// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }

// Modifiers
void close() { queue.close(); }

void push_back(const value_type& x) { queue.push_back(x); }
void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::forward<value_type>(x)); }

void pull_front(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull_front() { return queue.pull_front(); }

queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::forward<value_type>(x)); }
queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }

queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::forward<value_type>(x)); }
queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }

queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::forward<value_type>(x)); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }

};

}
using concurrent::queue_adaptor;

}

#include <boost/config/abi_suffix.hpp>

#endif
73 changes: 73 additions & 0 deletions include/boost/thread/concurrent_queues/queue_base.hpp
@@ -0,0 +1,73 @@
#ifndef BOOST_THREAD_QUEUE_BASE_HPP
#define BOOST_THREAD_QUEUE_BASE_HPP

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>

#include <boost/config/abi_prefix.hpp>

namespace boost
{
namespace concurrent
{

template <typename ValueType>
class queue_base
{
public:
typedef ValueType value_type;
typedef std::size_t size_type;

// Constructors/Assignment/Destructors
virtual ~queue_base() {};

// Observers
virtual bool empty() const = 0;
virtual bool full() const = 0;
virtual size_type size() const = 0;
virtual bool closed() const = 0;

// Modifiers
virtual void close() = 0;

virtual void push_back(const value_type& x) = 0;
virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;

virtual void pull_front(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
virtual value_type pull_front() = 0;

virtual queue_op_status try_push_back(const value_type& x) = 0;
virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status try_pull_front(value_type&) = 0;

virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status nonblocking_pull_front(value_type&) = 0;

virtual queue_op_status wait_push_back(const value_type& x) = 0;
virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
virtual queue_op_status wait_pull_front(ValueType& elem) = 0;

};


}
using concurrent::queue_base;

}

#include <boost/config/abi_suffix.hpp>

#endif
40 changes: 40 additions & 0 deletions include/boost/thread/concurrent_queues/queue_op_status.hpp
@@ -0,0 +1,40 @@
#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
#define BOOST_THREAD_QUEUE_OP_STATUS_HPP

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>

#include <boost/config/abi_prefix.hpp>

namespace boost
{
namespace concurrent
{

BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
{ success = 0, empty, full, closed, busy }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
}

#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
struct no_block_tag{};
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
#endif

using concurrent::queue_op_status;

}

#include <boost/config/abi_suffix.hpp>

#endif
157 changes: 157 additions & 0 deletions include/boost/thread/concurrent_queues/queue_views.hpp
@@ -0,0 +1,157 @@
#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
#define BOOST_THREAD_QUEUE_VIEWS_HPP

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/thread/concurrent_queues/queue_base.hpp>

#include <boost/config/abi_prefix.hpp>

namespace boost
{
namespace concurrent
{

template <typename Queue>
class queue_back_view
{
Queue& queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;

// Constructors/Assignment/Destructors
queue_back_view(Queue& q) BOOST_NOEXCEPT : queue(q) {}

// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }

// Modifiers
void close() { queue.close(); }

void push(const value_type& x) { queue.push_back(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(forward<value_type>(x)); }

void pull(value_type& x) { queue.pull_back(x); }
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue.pull_back(); }

queue_op_status try_push(const value_type& x) { return queue.try_push_back(x); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(forward<value_type>(x)); }

queue_op_status try_pull(value_type& x) { return queue.try_pull_back(x); }

queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push_back(x); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(forward<value_type>(x)); }

queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull_back(x); }

queue_op_status wait_push(const value_type& x) { return queue.wait_push_back(x); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(forward<value_type>(x)); }
queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_back(x); }

};

template <typename Queue>
class queue_front_view
{
Queue& queue;
public:
typedef typename Queue::value_type value_type;
typedef typename Queue::size_type size_type;

// Constructors/Assignment/Destructors
queue_front_view(Queue& q) BOOST_NOEXCEPT : queue(q) {}

// Observers
bool empty() const { return queue.empty(); }
bool full() const { return queue.full(); }
size_type size() const { return queue.size(); }
bool closed() const { return queue.closed(); }

// Modifiers
void close() { queue.close(); }

void push(const value_type& x) { queue.push_front(x); }
void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push_front(forward<value_type>(x)); }

void pull(value_type& x) { queue.pull_front(x); };
// enable_if is_nothrow_copy_movable<value_type>
value_type pull() { return queue.pull_front(); }

queue_op_status try_push(const value_type& x) { return queue.try_push_front(x); }
queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_front(forward<value_type>(x)); }

queue_op_status try_pull(value_type& x) { return queue.try_pull_front(x); }

queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push_front(x); }
queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_front(forward<value_type>(x)); }

queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull_front(x); }

queue_op_status wait_push(const value_type& x) { return queue.wait_push_front(x); }
queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_front(forward<value_type>(x)); }
queue_op_status wait_pull(value_type& x) { return queue.wait_pull_front(x); }

};

#if 0
template <class T>
using queue_back = queue_back_view<queue_base<T> > ;
template <class T>
using queue_front = queue_front_view<queue_base<T> > ;
#else
template <class T>
struct queue_back {
typedef queue_back_view<queue_base<T> > type;
};
template <class T>
struct queue_front {
typedef queue_front_view<queue_base<T> > type;
};

#endif

// template <class Queue>
// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
// template <class Queue>
// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
//#if 0
// template <class T>
// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
// template <class T>
// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
//#else
// template <class T>
// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
// template <class T>
// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
//#endif
}

using concurrent::queue_back_view;
using concurrent::queue_front_view;
using concurrent::queue_back;
using concurrent::queue_front;
//using concurrent::back;
//using concurrent::front;

}

#include <boost/config/abi_suffix.hpp>

#endif
19 changes: 3 additions & 16 deletions include/boost/thread/executors/basic_thread_pool.hpp
Expand Up @@ -264,33 +264,20 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
//work w ((closure));
//work_queue.push_back(boost::move(w));
work_queue.push_back(work(closure)); // todo check why this doesn't work
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
//work w ((closure));
//work_queue.push_back(boost::move(w));
work_queue.push_back(work(closure)); // todo check why this doesn't work
work_queue.push_back(work(closure));
}

#if 0
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w = boost::move(closure);
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
}
#else
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work_queue.push_back(work(boost::forward<Closure>(closure)));
}
#endif

/**
* \b Requires: This must be called from an scheduled task.
*
Expand Down
51 changes: 34 additions & 17 deletions include/boost/thread/executors/executor.hpp
Expand Up @@ -32,43 +32,54 @@ namespace boost
executor() {}

/**
* \b Effects: Destroys the executor.
* \par Effects
* Destroys the executor.
*
* \b Synchronization: The completion of all the closures happen before the completion of the executor destructor.
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
virtual ~executor() {};

/**
* \b Effects: close the \c executor for submissions.
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
virtual void close() = 0;

/**
* \b Returns: whether the pool is closed for submissions.
* \par Returns
* Whether the pool is closed for submissions.
*/
virtual bool closed() = 0;

/**
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;

/**
* \b Requires: \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/

Expand All @@ -94,16 +105,23 @@ namespace boost
}

/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
virtual bool try_executing_one() = 0;

/**
* \b Requires: This must be called from an scheduled task.
* \par Requires
* This must be called from an scheduled task.
*
* \b Effects: reschedule functions until pred()
* \par Effects
* Reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
Expand All @@ -119,7 +137,6 @@ namespace boost
}
};


}
using executors::executor;
}
Expand Down
19 changes: 3 additions & 16 deletions include/boost/thread/executors/executor_adaptor.hpp
Expand Up @@ -97,39 +97,26 @@ namespace executors
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
return ex.submit(boost::move(closure));
//return ex.submit(boost::forward<work>(closure));
//return ex.submit(boost::forward<work>(closure)); // todo check why this doesn't work
}

#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
submit(work(closure));
}

#if 0
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w =boost::move(closure);
submit(boost::move(w));
}
#else
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
submit(work(boost::forward<Closure>(closure)));
}
#endif

/**
* Effects: try to execute one task.
Expand Down
209 changes: 209 additions & 0 deletions include/boost/thread/executors/generic_executor_ref.hpp
@@ -0,0 +1,209 @@
// Copyright (C) 2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP

#include <boost/thread/detail/config.hpp>

#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/executor.hpp>

#include <boost/shared_ptr.hpp>

#include <boost/config/abi_prefix.hpp>

namespace boost
{
namespace executors
{

template <class Executor>
class executor_ref : public executor
{
Executor& ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;

/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_ref)
executor_ref(Executor& ex) : ex(ex) {}

/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
~executor_ref() {};

/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }

/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }

/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
//ex.submit(boost::forward<work>(closure)); // todo check why this doesn't work
ex.submit(boost::move(closure));
}


/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }

};

class generic_executor_ref
{
shared_ptr<executor> ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;

template<typename Executor>
generic_executor_ref(Executor& ex)
//: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
: ex( new executor_ref<Executor>(ex) )
{
}

//generic_executor_ref(generic_executor_ref const& other) noexcept {}
//generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}


/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex->close(); }

/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex->closed(); }

void submit(BOOST_THREAD_RV_REF(work) closure)
{
ex->submit(boost::forward<work>(closure));
}

/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/

#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
}

template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w = boost::move(closure);
submit(boost::move(w));
}

// size_t num_pending_closures() const
// {
// return ex->num_pending_closures();
// }

/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex->try_executing_one(); }

/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}

};
}
using executors::executor_ref;
using executors::generic_executor_ref;
}

#include <boost/config/abi_suffix.hpp>

#endif
12 changes: 3 additions & 9 deletions include/boost/thread/executors/loop_executor.hpp
Expand Up @@ -148,24 +148,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
work_queue.push_back(boost::move(w));
//work_queue.push(work(closure)); // todo check why this doesn't work
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(closure)); // todo check why this doesn't work
work_queue.push_back(work(closure));
}

template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w =boost::move(closure);
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
work_queue.push_back(work(boost::forward<Closure>(closure)));
}

/**
Expand Down
25 changes: 13 additions & 12 deletions include/boost/thread/executors/serial_executor.hpp
Expand Up @@ -14,7 +14,7 @@
#include <boost/thread/detail/move.hpp>
#include <boost/thread/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/scoped_thread.hpp>

Expand All @@ -34,7 +34,7 @@ namespace executors

/// the thread safe work queue
sync_queue<work > work_queue;
executor& ex;
generic_executor_ref ex;
thread_t thr;

struct try_executing_one_task {
Expand All @@ -48,6 +48,12 @@ namespace executors
}
};
public:
/**
* \par Returns
* The underlying executor wrapped on a generic executor reference.
*/
generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex; }

/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
Expand Down Expand Up @@ -118,7 +124,8 @@ namespace executors
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
serial_executor(executor& ex)
template <class Executor>
serial_executor(Executor& ex)
: ex(ex), thr(&serial_executor::worker_thread, this)
{
}
Expand Down Expand Up @@ -166,24 +173,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
work_queue.push_back(boost::move(w));
//work_queue.push(work(closure)); // todo check why this doesn't work
work_queue.push_back(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(closure)); // todo check why this doesn't work
work_queue.push_back(work(closure));
}

template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
work w =boost::move(closure);
work_queue.push_back(boost::move(w));
//work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
work_queue.push_back(work(boost::forward<Closure>(closure)));
}

/**
Expand Down
12 changes: 3 additions & 9 deletions include/boost/thread/sync_bounded_queue.hpp
Expand Up @@ -3,7 +3,7 @@

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013. Distributed under the Boost
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
Expand All @@ -16,6 +16,8 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>

#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
Expand All @@ -25,14 +27,6 @@
namespace boost
{

BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
{ success = 0, empty, full, closed, busy }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)

#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
struct no_block_tag{};
BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
#endif

struct sync_queue_is_closed : std::exception
{
Expand Down
4 changes: 3 additions & 1 deletion include/boost/thread/sync_queue.hpp
Expand Up @@ -3,7 +3,7 @@

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013. Distributed under the Boost
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
Expand All @@ -15,6 +15,8 @@
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>

#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
Expand Down
2 changes: 2 additions & 0 deletions test/Jamfile.v2
Expand Up @@ -849,6 +849,8 @@ rule thread-compile ( sources : reqs * : name )
#[ thread-run test_9720.cpp ]
#[ thread-run test_10125.cpp ]
#[ thread-run test_10128.cpp ]
#[ thread-run2 ../example/producer_consumer2.cpp : ex_producer_consumer2 ]
[ thread-run2 ../example/generic_executor_ref.cpp : generic_executor_ref ]
;

}