mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-17 07:24:34 +00:00
1d85cc4546
While making abipkgdiff to use the abigail::workers API to do away with using pthreads directory, it appeared that the abigail::workers API needs fixes and enhancements. Fixes ===== * Don't try to schedule a task if the pointer to the task is nil * Fix a data race when bringing workers (of a queue) down * Always try to wake up all waiting threads when bringing down queue workers. * Fix a data race when accessing the queue condition variable * Fix a data race when notifying listeners about the end of the job performed by the task. Enhancements ============ * Pass the "task done" notifier by reference, to the worker queue. Without this, the worker queue needs to copy the "task done" notifier by value. This implies that user code needs to provide task done notifier instances that come with potentially complicated copy constructors. By passing it by reference and by just re-using the notifier from the user code, we do away with the need for copying altogether. This also fixes some latent copying bugs. * Add a workers::queue::schedule_tasks() method This allows user code to schedule a vector of tasks at once. * make workers::queue::get_completed_tasks() return a non-const vector This enables user code to sort the completed tasks as they wish. * include/abg-workers.h (queue::tasks_type): New typedef. (queue::queue): Pass task_done_notify by reference. (queue::schedule_tasks): Declare new member function. (queue::get_completed_tasks): Return non-const vector. * src/abg-workers.cc (queue::priv::default_notify): New data member. (queue::priv::notify): Make this data member be a reference. (queue::priv::priv): Initialize the notify data member to either the new default_notify (if no notifier is provided by the constructor) or to the notifier provided by the constructor. (queue::priv::schedule_task): Do not schedule a nil task. Update comment. (queue::priv::schedule_tasks): Add a new member function. (queue::priv::do_bring_workers_down): Update comment. Protect access to "bring_workers_down" with tasks_todo_mutex to prevent a data race. Call pthread_cond_broadcast on the queue_cond unconditionaly to prevent some worker threads to keep waiting for ever. Also, protect the access to the queue_cond by the queue_cond_mutex to precent a data race. (queue::queue): Pass the notifier by reference. Update comment. (queue::schedule_task): Update comment. (queue::schedule_tasks): Define new member function. (queue::wait_for_workers_to_complete): Update comment. (queue::get_completed_tasks): Return a non-const vector. Update comment. (worker::wait_to_execute_a_task): Update several comments. Make the execution of the notification code to be synchronized (on the tasks_done_mutex). Signed-off-by: Dodji Seketeli <dodji@redhat.com>
120 lines
3.4 KiB
C++
120 lines
3.4 KiB
C++
// -*- Mode: C++ -*-
|
|
//
|
|
// Copyright (C) 2013-2016 Red Hat, Inc.
|
|
//
|
|
// This file is part of the GNU Application Binary Interface Generic
|
|
// Analysis and Instrumentation Library (libabigail). This library is
|
|
// free software; you can redistribute it and/or modify it under the
|
|
// terms of the GNU Lesser General Public License as published by the
|
|
// Free Software Foundation; either version 3, or (at your option) any
|
|
// later version.
|
|
|
|
// This library is distributed in the hope that it will be useful, but
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Lesser Public License for more details.
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this program; see the file COPYING-LGPLV3. If
|
|
// not, see <http://www.gnu.org/licenses/>.
|
|
|
|
// Author: Dodji Seketeli
|
|
|
|
/// @file
|
|
///
|
|
/// This file declares an interface for the worker threads (or thread
|
|
/// pool) design pattern. It aims at performing a set of tasks in
|
|
/// parallel, using the multi-threading capabilities of the underlying
|
|
/// processor(s).
|
|
///
|
|
|
|
#ifndef __ABG_WORKERS_H__
|
|
#define __ABG_WORKERS_H__
|
|
|
|
#include <tr1/memory>
|
|
#include <vector>
|
|
|
|
using std::tr1::shared_ptr;
|
|
|
|
namespace abigail
|
|
{
|
|
|
|
/// The namespace of the worker threads (or thread pool)
|
|
/// implementation of libabigail. This was modelled after the article
|
|
/// https://en.wikipedia.org/wiki/Thread_pool.
|
|
namespace workers
|
|
{
|
|
|
|
class task;
|
|
typedef shared_ptr<task> task_sptr;
|
|
|
|
size_t get_number_of_threads();
|
|
|
|
/// This represents a task to be performed.
|
|
///
|
|
/// Each instance of this type represents a task that can be performed
|
|
/// concurrently to other instance of the same type.
|
|
///
|
|
/// An instance of @ref task is meant to be performed by a worker
|
|
/// (thread). A set of tasks can be stored in a @ref queue.
|
|
class task
|
|
{
|
|
public:
|
|
task();
|
|
virtual void
|
|
perform() = 0;
|
|
|
|
virtual ~task();
|
|
}; // end class task.
|
|
|
|
/// This represents a queue of tasks to be performed.
|
|
///
|
|
/// Tasks are performed by a number of worker threads.
|
|
///
|
|
/// When a task is inserted into a @ref queue, the task is said to be
|
|
/// "scheduled for execution".
|
|
///
|
|
/// This is because there are worker threads waiting for tasks to be
|
|
/// added to the queue. When a task is added to the queue, a worker
|
|
/// thread picks it up, executes it, notifies interested listeners
|
|
/// when the @ref task's execution is completed, and waits for another
|
|
/// task to be added to the queue.
|
|
///
|
|
/// Of course, several worker threads can execute tasks concurrently.
|
|
class queue
|
|
{
|
|
public:
|
|
struct priv;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
/// A convenience typedef for a vector of @ref task_sptr
|
|
typedef std::vector<task_sptr> tasks_type;
|
|
|
|
private:
|
|
priv_sptr p_;
|
|
|
|
public:
|
|
struct task_done_notify;
|
|
queue();
|
|
queue(unsigned number_of_workers);
|
|
queue(unsigned number_of_workers,
|
|
task_done_notify& notifier);
|
|
size_t get_size() const;
|
|
bool schedule_task(const task_sptr&);
|
|
bool schedule_tasks(const tasks_type&);
|
|
void wait_for_workers_to_complete();
|
|
tasks_type& get_completed_tasks() const;
|
|
~queue();
|
|
}; // end class queue
|
|
|
|
/// This functor is to notify listeners that a given task scheduled
|
|
/// for execution has been fully executed.
|
|
struct queue::task_done_notify
|
|
{
|
|
virtual void
|
|
operator()(const task_sptr& task_done);
|
|
};
|
|
} // end namespace workers
|
|
} // end namespace abigail
|
|
#endif // __ABG_WORKERS_H__
|