just some more thoughts
This commit is contained in:
parent
ec63dc655b
commit
02df7de0c3
@ -1,15 +1,15 @@
|
|||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
component.cpp
|
||||||
collection.cpp
|
collection.cpp
|
||||||
loggable.cpp
|
loggable.cpp
|
||||||
taskmanager.cpp
|
taskmanager.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
component.h
|
||||||
collection.h
|
collection.h
|
||||||
loggable.h
|
loggable.h
|
||||||
taskmanager.h
|
taskmanager.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
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
|
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:
|
public:
|
||||||
UnknownSource(const std::string& source);
|
explicit UnknownSource(const std::string& source);
|
||||||
|
|
||||||
const char* what() const noexcept( true ) override;
|
|
||||||
private:
|
|
||||||
std::string source;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Collection::DuplicateSource : public std::exception {
|
class Collection::DuplicateSource : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
DuplicateSource(const std::string& source);
|
explicit DuplicateSource(const std::string& source);
|
||||||
|
|
||||||
const char* what() const noexcept( true ) override;
|
|
||||||
private:
|
|
||||||
std::string source;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Collection::DuplicatePath : public std::exception {
|
class Collection::DuplicatePath : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
DuplicatePath(const std::string& source, const std::filesystem::path& path);
|
explicit 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;
|
|
||||||
};
|
};
|
||||||
|
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),
|
stopping(false),
|
||||||
maxThreads(std::thread::hardware_concurrency()),
|
maxThreads(std::thread::hardware_concurrency()),
|
||||||
activeThreads(0),
|
activeThreads(0),
|
||||||
queue(),
|
jobs(),
|
||||||
queueMutex(),
|
mutex(),
|
||||||
loopConditional(),
|
loopConditional(),
|
||||||
waitConditional(),
|
waitConditional(),
|
||||||
threads()
|
threads()
|
||||||
@ -18,8 +18,15 @@ TaskManager::~TaskManager() {
|
|||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TaskManager::queue(const Job& job) {
|
||||||
|
std::unique_lock lock(mutex);
|
||||||
|
jobs.emplace(job);
|
||||||
|
lock.unlock();
|
||||||
|
loopConditional.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
void TaskManager::start() {
|
void TaskManager::start() {
|
||||||
std::lock_guard lock(queueMutex);
|
std::lock_guard lock(mutex);
|
||||||
if (running)
|
if (running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -30,7 +37,7 @@ void TaskManager::start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TaskManager::stop() {
|
void TaskManager::stop() {
|
||||||
std::unique_lock lock(queueMutex);
|
std::unique_lock lock(mutex);
|
||||||
if (!running)
|
if (!running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -47,19 +54,19 @@ void TaskManager::stop() {
|
|||||||
void TaskManager::loop() {
|
void TaskManager::loop() {
|
||||||
while (true) {
|
while (true) {
|
||||||
Job job;
|
Job job;
|
||||||
std::unique_lock lock(queueMutex);
|
std::unique_lock lock(mutex);
|
||||||
while (!stopping && queue.empty())
|
while (!stopping && jobs.empty())
|
||||||
loopConditional.wait(lock);
|
loopConditional.wait(lock);
|
||||||
|
|
||||||
if (stopping)
|
if (stopping)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++activeThreads;
|
++activeThreads;
|
||||||
job = queue.front();
|
job = jobs.front();
|
||||||
queue.pop();
|
jobs.pop();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
//do the job
|
job();
|
||||||
lock.lock();
|
lock.lock();
|
||||||
--activeThreads;
|
--activeThreads;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@ -68,13 +75,13 @@ void TaskManager::loop() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaskManager::busy() {
|
bool TaskManager::busy() const {
|
||||||
std::lock_guard lock(queueMutex);
|
std::lock_guard lock(mutex);
|
||||||
return activeThreads == 0;
|
return activeThreads == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskManager::wait() {
|
void TaskManager::wait() const {
|
||||||
std::unique_lock lock(queueMutex);
|
std::unique_lock lock(mutex);
|
||||||
while (activeThreads != 0)
|
while (activeThreads != 0)
|
||||||
waitConditional.wait(lock);
|
waitConditional.wait(lock);
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,19 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class TaskManager {
|
class TaskManager {
|
||||||
public:
|
public:
|
||||||
typedef std::string Job;
|
using Job = std::function<void ()>;
|
||||||
TaskManager();
|
TaskManager();
|
||||||
~TaskManager();
|
~TaskManager();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void wait();
|
void wait() const;
|
||||||
bool busy();
|
void queue(const Job& job);
|
||||||
|
bool busy() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loop();
|
void loop();
|
||||||
@ -26,9 +28,9 @@ private:
|
|||||||
bool stopping;
|
bool stopping;
|
||||||
uint32_t maxThreads;
|
uint32_t maxThreads;
|
||||||
uint32_t activeThreads;
|
uint32_t activeThreads;
|
||||||
std::queue<Job> queue;
|
std::queue<Job> jobs;
|
||||||
std::mutex queueMutex;
|
mutable std::mutex mutex;
|
||||||
std::condition_variable loopConditional;
|
mutable std::condition_variable loopConditional;
|
||||||
std::condition_variable waitConditional;
|
mutable std::condition_variable waitConditional;
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user