Skip to content

Commit

Permalink
chore: Config uses ThreadPool
Browse files Browse the repository at this point in the history
vinniefalco committed Jun 10, 2023
1 parent 9121bef commit c740a9a
Showing 11 changed files with 85 additions and 241 deletions.
107 changes: 6 additions & 101 deletions include/mrdox/Config.hpp
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@

#include <mrdox/Platform.hpp>
#include <mrdox/Support/Error.hpp>
#include <mrdox/Support/Thread.hpp>
#include <functional>
#include <memory>
#include <string>
@@ -42,30 +43,18 @@ class MRDOX_VISIBLE
Config() noexcept;

public:
/** A resource for running submitted work, possibly concurrent.
*/
class WorkGroup;

/** Destructor.
*/
MRDOX_DECL
virtual
~Config() noexcept = 0;

/** Call a function for each element of a range.
The function is invoked with a reference
to each element of the container using the
concurrency specified in the configuration.
This function must not be called concurrently,
despite being marked `const`.
/** Return a pool of threads for executing work.
*/
template<class Range, class UnaryFunction>
void
parallelForEach(
Range&& range,
UnaryFunction const& f) const;
MRDOX_DECL
virtual
ThreadPool&
threadPool() const noexcept = 0;

//--------------------------------------------
//
@@ -147,90 +136,6 @@ class MRDOX_VISIBLE
std::string extraYaml;
};

//------------------------------------------------

/** A group representing possibly concurrent related tasks.
*/
class MRDOX_VISIBLE
Config::WorkGroup
{
public:
/** Destructor.
*/
MRDOX_DECL
~WorkGroup();

/** Constructor.
Default constructed workgroups have no
concurrency level. Calls to post and wait
are blocking.
*/
MRDOX_DECL
WorkGroup() noexcept;

/** Constructor.
*/
MRDOX_DECL
explicit
WorkGroup(
Config const* config);

/** Constructor.
*/
MRDOX_DECL
WorkGroup(
WorkGroup const& other);

/** Assignment.
*/
MRDOX_DECL
WorkGroup&
operator=(
WorkGroup const& other);

/** Post work to the work group.
*/
MRDOX_DECL
void
post(std::function<void(void)>);

/** Wait for all posted work in the work group to complete.
*/
MRDOX_DECL
void
wait();

private:
friend class ConfigImpl;

struct Base
{
MRDOX_DECL virtual ~Base() noexcept;
};

class Impl;

std::shared_ptr<ConfigImpl const> config_;
std::unique_ptr<Base> impl_;
};

template<class Range, class UnaryFunction>
void
Config::
parallelForEach(
Range&& range,
UnaryFunction const& f) const
{
WorkGroup wg(this);
for(auto&& element : range)
wg.post([&f, &element]
{
f(element);
});
wg.wait();
}

} // mrdox
} // clang

57 changes: 54 additions & 3 deletions include/mrdox/Support/Thread.hpp
Original file line number Diff line number Diff line change
@@ -55,6 +55,12 @@ class MRDOX_VISIBLE
ThreadPool(
unsigned concurrency);

/** Return the number of threads in the pool.
*/
MRDOX_DECL
unsigned
getThreadCount() const noexcept;

/** Submit work to be executed.
The signature of the submitted function
@@ -119,16 +125,61 @@ forEach(
Range&& range,
F const& f)
{
TaskGroup tg(*this);
TaskGroup taskGroup(*this);
for(auto&& value : range)
tg.async(
taskGroup.async(
[&f, &value]
{
f(value);
});
tg.wait();
taskGroup.wait();
}

//------------------------------------------------

#if 0
/** A set of execution agents for performing concurrent work.
*/
template<class... Args>
class ExecutionGroup
{
std::vector<Agent*> agents_;
std::vector<std::function<void(Agent&)>> work_;
ThreadPool threadPool_;
TaskGroup taskGroup_;

public:
template<class Agents>
explicit
Executors(
Agents&& agents,
ThreadPool &threadPool)
: threadPool_(threadPool)
{
agents_.reserve(std::distance(
std::begin(agents), std::end(agents)));
for(auto& agent : agents)
agents_.push_back(&agent);
}

/** Submit work to be executed.

The signature of the submitted function
object should be `void(Agent&)`.
*/
void
async(std::function<void(void)> f);

/** Block until all work has completed.
*/
void
wait()
{
taskGroup_.wait();
}
};
#endif

} // mrdox
} // clang

4 changes: 2 additions & 2 deletions source/-adoc/AdocPagesBuilder.cpp
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ AdocPagesBuilder::
build()
{
corpus_.traverse(*this, SymbolID::zero);
wg_.wait();
taskGroup_.wait();
return {};
}

@@ -40,7 +40,7 @@ build(
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;

wg_.post(
taskGroup_.async(
[&]
{
llvm::SmallString<512> filePath = outputPath_;
4 changes: 2 additions & 2 deletions source/-adoc/AdocPagesBuilder.hpp
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ class AdocPagesBuilder
Corpus const& corpus_;
SafeNames names_;
llvm::StringRef outputPath_;
Config::WorkGroup wg_;
TaskGroup taskGroup_;

public:
AdocPagesBuilder(
@@ -36,7 +36,7 @@ class AdocPagesBuilder
: corpus_(corpus)
, names_(corpus_)
, outputPath_(outputPath)
, wg_(&corpus.config)
, taskGroup_(corpus.config.threadPool())
{
}

8 changes: 4 additions & 4 deletions source/-bitcode/BitcodeGenerator.cpp
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ class MultiFileBuilder : public Corpus::Visitor
Corpus const& corpus_;
std::string_view outputPath_;
SafeNames names_;
Config::WorkGroup wg_;
TaskGroup taskGroup_;

public:
MultiFileBuilder(
@@ -34,15 +34,15 @@ class MultiFileBuilder : public Corpus::Visitor
: corpus_(corpus)
, outputPath_(outputPath)
, names_(corpus_)
, wg_(&corpus.config)
, taskGroup_(corpus.config.threadPool())
{
}

Error
build()
{
corpus_.traverse(*this, SymbolID::zero);
wg_.wait();
taskGroup_.wait();
return Error();
}

@@ -52,7 +52,7 @@ class MultiFileBuilder : public Corpus::Visitor
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;

wg_.post(
taskGroup_.async(
[&]
{
llvm::SmallString<512> filePath(outputPath_);
120 changes: 0 additions & 120 deletions source/Config.cpp
Original file line number Diff line number Diff line change
@@ -32,131 +32,11 @@ static_assert(
#endif

#include <ranges>

#include <fmt/format.h>

namespace clang {
namespace mrdox {

//------------------------------------------------
//
// Config::WorkGroup
//
//------------------------------------------------

class Config::WorkGroup::
Impl : public Base
{
public:
explicit
Impl(
llvm::ThreadPool& threadPool) noexcept
: group_(threadPool)
{
}

llvm::ThreadPoolTaskGroup group_;
};

Config::
WorkGroup::
Base::~Base() noexcept = default;

Config::
WorkGroup::
~WorkGroup()
{
impl_ = nullptr;
config_ = nullptr;
}

Config::
WorkGroup::
WorkGroup(
Config const* config)
: config_(config
? dynamic_cast<ConfigImpl const*>(
config)->shared_from_this()
: nullptr)
, impl_(config_
? std::make_unique<Impl>(const_cast<
llvm::ThreadPool&>(config_->threadPool_))
: nullptr)
{
}

Config::
WorkGroup::
WorkGroup(
WorkGroup const& other)
: config_(other.config_)
, impl_(other.config_
? std::make_unique<Impl>(const_cast<
llvm::ThreadPool&>(config_->threadPool_))
: nullptr)
{
}

auto
Config::
WorkGroup::
operator=(
WorkGroup const& other) ->
WorkGroup&
{
if(this == &other)
return *this;

if(! other.config_)
{
config_ = nullptr;
impl_ = nullptr;
return *this;
}

auto impl = std::make_unique<Impl>(
const_cast<llvm::ThreadPool&>(
other.config_->threadPool_));
impl_ = std::move(impl);
config_ = other.config_;
return *this;
}

void
Config::
WorkGroup::
post(
std::function<void(void)> f)
{
if(config_ && config_->concurrency > 1)
{
auto& impl = static_cast<Impl&>(*impl_);
impl.group_.async(std::move(f));
}
else
{
f();
}
}

void
Config::
WorkGroup::
wait()
{
if(config_ && config_->concurrency > 1)
{
auto& impl = static_cast<Impl&>(*impl_);
impl.group_.wait();
}
}

//------------------------------------------------
//
// Config
//
//------------------------------------------------

Config::
Config() noexcept
{
4 changes: 1 addition & 3 deletions source/ConfigImpl.cpp
Original file line number Diff line number Diff line change
@@ -117,9 +117,7 @@ construct(

ConfigImpl::
ConfigImpl()
: threadPool_(
llvm::hardware_concurrency(
tooling::ExecutorConcurrency))
: threadPool_(0)
{
}

10 changes: 8 additions & 2 deletions source/ConfigImpl.hpp
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#include "Support/YamlFwd.hpp"
#include <mrdox/Config.hpp>
#include <mrdox/Support/Expected.hpp>
#include <mrdox/Support/Thread.hpp>
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/ThreadPool.h>
#include <memory>
@@ -25,7 +26,6 @@ namespace mrdox {
class ConfigImpl
: public Config
, public std::enable_shared_from_this<ConfigImpl>

{
public:
//--------------------------------------------
@@ -47,7 +47,7 @@ class ConfigImpl
//--------------------------------------------

private:
llvm::ThreadPool mutable threadPool_;
ThreadPool mutable threadPool_;
llvm::SmallString<0> outputPath_;
std::vector<std::string> inputFileIncludes_;

@@ -66,6 +66,12 @@ class ConfigImpl
public:
ConfigImpl();

ThreadPool&
threadPool() const noexcept override
{
return threadPool_;
}

/** Return the full path to the source root directory.
The returned path will always be POSIX
2 changes: 1 addition & 1 deletion source/CorpusImpl.cpp
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ build(
reportInfo("Reducing {} declarations", bitcodes.size());
std::atomic<bool> GotFailure;
GotFailure = false;
corpus->config.parallelForEach(
corpus->config.threadPool().forEach(
bitcodes,
[&](auto& Group)
{
7 changes: 7 additions & 0 deletions source/Support/Thread.cpp
Original file line number Diff line number Diff line change
@@ -37,6 +37,13 @@ ThreadPool(
impl_ = std::make_unique<llvm::ThreadPool>(S);
}

unsigned
ThreadPool::
getThreadCount() const noexcept
{
return impl_->getThreadCount();
}

void
ThreadPool::
async(
3 changes: 0 additions & 3 deletions source/TestAction.cpp
Original file line number Diff line number Diff line change
@@ -78,7 +78,6 @@ class TestRunner
std::string extraYaml_;
llvm::ErrorOr<std::string> diff_;
Generator const* xmlGen_;
Generator const* adocGen_;

std::shared_ptr<Config const>
makeConfig(
@@ -124,10 +123,8 @@ TestRunner(
, extraYaml_(extraYaml)
, diff_(llvm::sys::findProgramByName("diff"))
, xmlGen_(getGenerators().find("xml"))
, adocGen_(getGenerators().find("adoc"))
{
Assert(xmlGen_ != nullptr);
Assert(adocGen_ != nullptr);
}

std::shared_ptr<Config const>

0 comments on commit c740a9a

Please sign in to comment.