diff options
author | Frederico Linhares <fred@linhares.blue> | 2024-12-31 12:32:36 -0300 |
---|---|---|
committer | Frederico Linhares <fred@linhares.blue> | 2024-12-31 19:03:51 -0300 |
commit | 736637680ac7b2cd0d0b878401a7e044fde0ee6a (patch) | |
tree | bf4feaf3f3f0e48207bf7a31ad8bcbff0f244091 /src/blu_cat/com | |
parent | 083e64da1d4b5b68579288bc1690ca90d3f0a2c0 (diff) |
Diffstat (limited to 'src/blu_cat/com')
-rw-r--r-- | src/blu_cat/com/command.cpp | 78 | ||||
-rw-r--r-- | src/blu_cat/com/command.hpp | 92 | ||||
-rw-r--r-- | src/blu_cat/com/job_queue.cpp | 66 | ||||
-rw-r--r-- | src/blu_cat/com/job_queue.hpp | 57 | ||||
-rw-r--r-- | src/blu_cat/com/worker.cpp | 39 | ||||
-rw-r--r-- | src/blu_cat/com/worker.hpp | 38 |
6 files changed, 370 insertions, 0 deletions
diff --git a/src/blu_cat/com/command.cpp b/src/blu_cat/com/command.cpp new file mode 100644 index 0000000..a1d3240 --- /dev/null +++ b/src/blu_cat/com/command.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include "command.hpp" + +CommandError::CommandError(const std::string &m): + error(m) +{ +} + +CommandError::CommandError(const char &m): + CommandError{std::string{m}} +{ +} + +const char* CommandError::what() const noexcept +{ + return this->error.c_str(); +} + +CommandChain::CommandChain(std::initializer_list<Command> commands) +{ + for(auto c: commands) this->add(c); +} + +void +CommandChain::partial_revert(void *obj, int32_t step) const +{ + // Already unloaded, nothing to do. + if(step <= 0) return; + + for(; step > 0; step--) + { + auto command = this->_commands[step -1].undo_command; + if(command != nullptr) command(obj); + } +} + +void +CommandChain::add(const Command &c) +{ + this->_commands.push_back(c); +} + +void +CommandChain::execute(void *obj) const +{ + for(auto i{0}; i < this->_commands.size(); i++) + { + try { this->_commands[i].do_command(obj); } + catch(const CommandError &error) + { + this->partial_revert(obj, i); + throw; + } + } +} + +void +CommandChain::revert(void *obj) const +{ + this->partial_revert(obj, this->_commands.size()); +} diff --git a/src/blu_cat/com/command.hpp b/src/blu_cat/com/command.hpp new file mode 100644 index 0000000..5079c58 --- /dev/null +++ b/src/blu_cat/com/command.hpp @@ -0,0 +1,92 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLU_CAT_COM_COMMAND_CHAIN_H +#define BLU_CAT_COM_COMMAND_CHAIN_H 1 + +#include <cstdint> +#include <initializer_list> +#include <stdexcept> +#include <string> +#include <vector> + +class CommandChain; + +struct CommandError: public std::exception +{ + CommandError(const std::string &m); + CommandError(const char &m); + + const char* what() const noexcept; + +private: + std::string error; +}; + +/** + * Stores a reversible action. + */ +struct Command +{ + void (*do_command)(void *obj); + void (*undo_command)(void *obj); +}; + +/** + * Stores a sequence of functions that must be executed and rolled back in + * order. + * + * For example, if the variable _commands contain A→B→C→D→E, it will load A, + * then B, then C, etc. If D fails, it unloads C, then B, then A. + */ +class CommandChain +{ + std::vector<Command> _commands; + + void + partial_revert(void *obj, int32_t step) const; + +public: + CommandChain(std::initializer_list<Command> commands); + +/** + * Adds a reversible action to the command. The first action added is the first + * to de executed the last rolled back, and so on. Those functions are stored + * inside _commands. + * + * @param[unload] the undo/rollback action, if the action do not need a + * rollback, this pointer can be set to null. + */ + void + add(const Command &c); + +/** + * Execute all of the load functions in the _commands. If one of them fails, + * roll back everything inside _commands. + * @return true on success and false on fail. + */ + void + execute(void *obj) const; + +/** + * Roll back all loaded function inside commands, if there are any. + */ + void + revert(void *obj) const; + +}; + +#endif /* BLU_CAT_COM_COMMAND_CHAIN_H */ diff --git a/src/blu_cat/com/job_queue.cpp b/src/blu_cat/com/job_queue.cpp new file mode 100644 index 0000000..beaf989 --- /dev/null +++ b/src/blu_cat/com/job_queue.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "job_queue.hpp" + +#include <chrono> + +namespace BluCat::COM +{ + +JobQueue::JobQueue(): + jobs{}, + _stop{false} +{ +} + +void +JobQueue::stop() +{ + using namespace std::chrono_literals; + + while(!this->jobs.empty()) std::this_thread::sleep_for(1000ms); + this->_stop = true; + this->condition.notify_all(); +} + +void +JobQueue::push(Job job) +{ + std::unique_lock<std::mutex> lock{this->access}; + this->jobs.push_back(job); + this->condition.notify_one(); +} + +Job +JobQueue::pop() +{ + std::unique_lock<std::mutex> lock{this->access}; + this->condition.wait(lock, [this]{ + return !this->jobs.empty() || this->_stop;}); + if(!this->jobs.empty()) + { + auto job{std::move(this->jobs.front())}; + this->jobs.pop_front(); + return job; + } + else + { + return Job{nullptr}; + } +} + +} diff --git a/src/blu_cat/com/job_queue.hpp b/src/blu_cat/com/job_queue.hpp new file mode 100644 index 0000000..856946d --- /dev/null +++ b/src/blu_cat/com/job_queue.hpp @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLU_CAT_COM_JOB_QUEUE_H +#define BLU_CAT_COM_JOB_QUEUE_H 1 + +#include <atomic> +#include <condition_variable> +#include <deque> +#include <functional> +#include <mutex> + +namespace BluCat::COM +{ + +class Worker; + +typedef std::function<void(void)> Job; + +class JobQueue +{ + friend Worker; + + std::mutex access; + std::condition_variable condition; + std::atomic<bool> _stop; + std::deque<Job> jobs; + + Job + pop(); + +public: + JobQueue(); + + void + stop(); + + void + push(Job job); +}; + +} + +#endif /* BLU_CAT_COM_JOB_QUEUE_H */ diff --git a/src/blu_cat/com/worker.cpp b/src/blu_cat/com/worker.cpp new file mode 100644 index 0000000..847b571 --- /dev/null +++ b/src/blu_cat/com/worker.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "worker.hpp" + +#include <thread> + +namespace BluCat::COM +{ + +Worker::Worker(JobQueue *job_queue): + job_queue{job_queue} +{ +} + +void +Worker::operator()() +{ + while(!this->job_queue->_stop) + { + auto job{this->job_queue->pop()}; + if(job) job(); + } +} + +} diff --git a/src/blu_cat/com/worker.hpp b/src/blu_cat/com/worker.hpp new file mode 100644 index 0000000..d74aa24 --- /dev/null +++ b/src/blu_cat/com/worker.hpp @@ -0,0 +1,38 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLU_CAT_COM_WORKER_H +#define BLU_CAT_COM_WORKER_H 1 + +#include "job_queue.hpp" + +namespace BluCat::COM +{ + +class Worker +{ + JobQueue *job_queue; + +public: + Worker(JobQueue *job_queue); + + void + operator()(); +}; + +} + +#endif /* BLU_CAT_COM_WORKER_H */ |