just some more thoughts

This commit is contained in:
Blue 2023-09-20 16:45:22 -03:00
parent ec63dc655b
commit 02df7de0c3
Signed by: blue
GPG Key ID: 9B203B252A63EE38
11 changed files with 163 additions and 143 deletions

View File

@ -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)

View File

@ -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
View 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
View 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);
};

View File

@ -1,11 +0,0 @@
set(SOURCES
component.cpp
file.cpp
)
set(HEADERS
component.h
file.h
)
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})

View File

@ -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;
}

View File

@ -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;
};

View File

@ -1 +0,0 @@
#include "file.h"

View File

@ -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:
};

View File

@ -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);
}

View File

@ -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;
};