just some more thoughts
This commit is contained in:
parent
ec63dc655b
commit
02df7de0c3
@ -1,15 +1,15 @@
|
||||
set(SOURCES
|
||||
component.cpp
|
||||
collection.cpp
|
||||
loggable.cpp
|
||||
taskmanager.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
component.h
|
||||
collection.h
|
||||
loggable.h
|
||||
taskmanager.h
|
||||
)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
||||
|
||||
add_subdirectory(components)
|
||||
|
@ -30,30 +30,17 @@ private:
|
||||
std::map<std::string, std::filesystem::path> successSources; //would be nice to have a bimap here
|
||||
};
|
||||
|
||||
class Collection::UnknownSource : public std::exception {
|
||||
class Collection::UnknownSource : public std::runtime_error {
|
||||
public:
|
||||
UnknownSource(const std::string& source);
|
||||
|
||||
const char* what() const noexcept( true ) override;
|
||||
private:
|
||||
std::string source;
|
||||
explicit UnknownSource(const std::string& source);
|
||||
};
|
||||
|
||||
class Collection::DuplicateSource : public std::exception {
|
||||
class Collection::DuplicateSource : public std::runtime_error {
|
||||
public:
|
||||
DuplicateSource(const std::string& source);
|
||||
|
||||
const char* what() const noexcept( true ) override;
|
||||
private:
|
||||
std::string source;
|
||||
explicit DuplicateSource(const std::string& source);
|
||||
};
|
||||
|
||||
class Collection::DuplicatePath : public std::exception {
|
||||
class Collection::DuplicatePath : public std::runtime_error {
|
||||
public:
|
||||
DuplicatePath(const std::string& source, const std::filesystem::path& path);
|
||||
|
||||
const char* what() const noexcept( true ) override;
|
||||
private:
|
||||
std::string source;
|
||||
std::filesystem::path path;
|
||||
explicit DuplicatePath(const std::string& source, const std::filesystem::path& path);
|
||||
};
|
||||
|
65
src2/component.cpp
Normal file
65
src2/component.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "component.h"
|
||||
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
|
||||
constexpr std::array<std::string_view, Component::done + 1> stringStates {
|
||||
"initial",
|
||||
"reading",
|
||||
"ready",
|
||||
"building",
|
||||
"done"
|
||||
};
|
||||
|
||||
Component::Component(
|
||||
const std::filesystem::path& path,
|
||||
const std::shared_ptr<Collection>& collection,
|
||||
const std::shared_ptr<TaskManager>& taskManager,
|
||||
const std::shared_ptr<Logger>& logger
|
||||
):
|
||||
Loggable(logger),
|
||||
collection(collection),
|
||||
taskManager(taskManager),
|
||||
location(path)
|
||||
{}
|
||||
|
||||
void Component::read() {
|
||||
if (state != initial)
|
||||
throw WrongState(state, "read");
|
||||
|
||||
try {
|
||||
collection->addSource(location);
|
||||
} catch (const Collection::DuplicateSource e) {
|
||||
state = error;
|
||||
throw e;
|
||||
}
|
||||
state = reading;
|
||||
taskManager->queue(std::bind(&Component::performRead, this));
|
||||
}
|
||||
|
||||
void Component::build(const std::filesystem::path& destination, const std::string& target) {
|
||||
if (state != ready)
|
||||
throw WrongState(state, "build");
|
||||
|
||||
state = building;
|
||||
taskManager->queue(std::bind(&Component::performBuild, this, destination, target));
|
||||
}
|
||||
|
||||
void Component::performRead() {
|
||||
}
|
||||
|
||||
void Component::performBuild(std::filesystem::path destination, std::string target) {
|
||||
}
|
||||
|
||||
Component::State Component::getState() const {
|
||||
return state;
|
||||
}
|
||||
|
||||
Component::Type Component::getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
Component::WrongState::WrongState(State state, const std::string& action):
|
||||
std::runtime_error("An attempt to perform action \"" + action
|
||||
+ "\" on a wrong state \"" + stringStates[state].data() + '\"')
|
||||
{}
|
61
src2/component.h
Normal file
61
src2/component.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
|
||||
#include "loggable.h"
|
||||
#include "loggger.h"
|
||||
#include "collection.h"
|
||||
#include "taskmanager.h"
|
||||
|
||||
class Component : protected Loggable {
|
||||
public:
|
||||
class WrongState;
|
||||
enum State {
|
||||
initial,
|
||||
reading,
|
||||
ready,
|
||||
building,
|
||||
error,
|
||||
done
|
||||
};
|
||||
|
||||
enum Type {
|
||||
unknown,
|
||||
file,
|
||||
directory,
|
||||
mason
|
||||
};
|
||||
|
||||
Component(
|
||||
const std::filesystem::path& path,
|
||||
const std::shared_ptr<Collection>& collection,
|
||||
const std::shared_ptr<TaskManager>& taskManager,
|
||||
const std::shared_ptr<Logger>& logger
|
||||
);
|
||||
|
||||
Type getType() const;
|
||||
State getState() const;
|
||||
|
||||
void read();
|
||||
void build(const std::filesystem::path& destination, const std::string& target);
|
||||
|
||||
private:
|
||||
void performRead();
|
||||
void performBuild(std::filesystem::path destination, std::string target);
|
||||
|
||||
private:
|
||||
State state;
|
||||
Type type;
|
||||
std::shared_ptr<Collection> collection;
|
||||
std::shared_ptr<TaskManager> taskManager;
|
||||
std::filesystem::path location;
|
||||
};
|
||||
|
||||
class Component::WrongState : public std::runtime_error {
|
||||
public:
|
||||
explicit WrongState(State state, const std::string& action);
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
set(SOURCES
|
||||
component.cpp
|
||||
file.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
component.h
|
||||
file.h
|
||||
)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
@ -1,23 +0,0 @@
|
||||
#include "component.h"
|
||||
|
||||
Component::Component(const std::shared_ptr<Collection>& collection, const std::shared_ptr<Logger>& logger):
|
||||
Loggable(logger),
|
||||
collection(collection)
|
||||
{}
|
||||
|
||||
void Component::read(const std::filesystem::path& path) {
|
||||
if (state != initial)
|
||||
throw WrongState(state, "read");
|
||||
|
||||
location = path;
|
||||
state = reading;
|
||||
}
|
||||
|
||||
|
||||
Component::State Component::getState() const {
|
||||
return state;
|
||||
}
|
||||
|
||||
Component::Type Component::getType() const {
|
||||
return type;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
|
||||
#include "loggable.h"
|
||||
#include "loggger.h"
|
||||
#include "collection.h"
|
||||
|
||||
class Component : protected Loggable {
|
||||
public:
|
||||
class WrongState;
|
||||
enum State {
|
||||
initial,
|
||||
reading,
|
||||
building,
|
||||
ready
|
||||
};
|
||||
|
||||
enum Type {
|
||||
unknown,
|
||||
file,
|
||||
directory,
|
||||
mason
|
||||
};
|
||||
|
||||
Component(const std::shared_ptr<Collection>& collection, const std::shared_ptr<Logger>& logger);
|
||||
virtual ~Component() override = default;
|
||||
|
||||
Type getType() const;
|
||||
State getState() const;
|
||||
|
||||
virtual void read(const std::filesystem::path& path);
|
||||
virtual void build(const std::filesystem::path& destination, const std::string& target) = 0;
|
||||
|
||||
protected:
|
||||
State state;
|
||||
Type type;
|
||||
std::shared_ptr<Collection> collection;
|
||||
std::filesystem::path location;
|
||||
};
|
||||
|
||||
class Component::WrongState : public std::exception {
|
||||
public:
|
||||
WrongState(State state, const std::string& action);
|
||||
|
||||
const char* what() const noexcept( true ) override;
|
||||
private:
|
||||
State state;
|
||||
std::string action;
|
||||
};
|
@ -1 +0,0 @@
|
||||
#include "file.h"
|
@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
#include "component.h"
|
||||
|
||||
class File : public Component {
|
||||
public:
|
||||
File(const std::shared_ptr<Collection>& collection, const std::shared_ptr<Logger>& logger);
|
||||
|
||||
protected:
|
||||
|
||||
};
|
@ -5,8 +5,8 @@ TaskManager::TaskManager() :
|
||||
stopping(false),
|
||||
maxThreads(std::thread::hardware_concurrency()),
|
||||
activeThreads(0),
|
||||
queue(),
|
||||
queueMutex(),
|
||||
jobs(),
|
||||
mutex(),
|
||||
loopConditional(),
|
||||
waitConditional(),
|
||||
threads()
|
||||
@ -18,8 +18,15 @@ TaskManager::~TaskManager() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void TaskManager::queue(const Job& job) {
|
||||
std::unique_lock lock(mutex);
|
||||
jobs.emplace(job);
|
||||
lock.unlock();
|
||||
loopConditional.notify_one();
|
||||
}
|
||||
|
||||
void TaskManager::start() {
|
||||
std::lock_guard lock(queueMutex);
|
||||
std::lock_guard lock(mutex);
|
||||
if (running)
|
||||
return;
|
||||
|
||||
@ -30,7 +37,7 @@ void TaskManager::start() {
|
||||
}
|
||||
|
||||
void TaskManager::stop() {
|
||||
std::unique_lock lock(queueMutex);
|
||||
std::unique_lock lock(mutex);
|
||||
if (!running)
|
||||
return;
|
||||
|
||||
@ -47,19 +54,19 @@ void TaskManager::stop() {
|
||||
void TaskManager::loop() {
|
||||
while (true) {
|
||||
Job job;
|
||||
std::unique_lock lock(queueMutex);
|
||||
while (!stopping && queue.empty())
|
||||
std::unique_lock lock(mutex);
|
||||
while (!stopping && jobs.empty())
|
||||
loopConditional.wait(lock);
|
||||
|
||||
if (stopping)
|
||||
return;
|
||||
|
||||
++activeThreads;
|
||||
job = queue.front();
|
||||
queue.pop();
|
||||
job = jobs.front();
|
||||
jobs.pop();
|
||||
lock.unlock();
|
||||
|
||||
//do the job
|
||||
job();
|
||||
lock.lock();
|
||||
--activeThreads;
|
||||
lock.unlock();
|
||||
@ -68,13 +75,13 @@ void TaskManager::loop() {
|
||||
|
||||
}
|
||||
|
||||
bool TaskManager::busy() {
|
||||
std::lock_guard lock(queueMutex);
|
||||
bool TaskManager::busy() const {
|
||||
std::lock_guard lock(mutex);
|
||||
return activeThreads == 0;
|
||||
}
|
||||
|
||||
void TaskManager::wait() {
|
||||
std::unique_lock lock(queueMutex);
|
||||
void TaskManager::wait() const {
|
||||
std::unique_lock lock(mutex);
|
||||
while (activeThreads != 0)
|
||||
waitConditional.wait(lock);
|
||||
}
|
||||
|
@ -6,17 +6,19 @@
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
|
||||
class TaskManager {
|
||||
public:
|
||||
typedef std::string Job;
|
||||
using Job = std::function<void ()>;
|
||||
TaskManager();
|
||||
~TaskManager();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void wait();
|
||||
bool busy();
|
||||
void wait() const;
|
||||
void queue(const Job& job);
|
||||
bool busy() const;
|
||||
|
||||
private:
|
||||
void loop();
|
||||
@ -26,9 +28,9 @@ private:
|
||||
bool stopping;
|
||||
uint32_t maxThreads;
|
||||
uint32_t activeThreads;
|
||||
std::queue<Job> queue;
|
||||
std::mutex queueMutex;
|
||||
std::condition_variable loopConditional;
|
||||
std::condition_variable waitConditional;
|
||||
std::queue<Job> jobs;
|
||||
mutable std::mutex mutex;
|
||||
mutable std::condition_variable loopConditional;
|
||||
mutable std::condition_variable waitConditional;
|
||||
std::vector<std::thread> threads;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user