summaryrefslogtreecommitdiff
path: root/src/blu_cat/com
diff options
context:
space:
mode:
authorFrederico Linhares <fred@linhares.blue>2024-12-31 12:32:36 -0300
committerFrederico Linhares <fred@linhares.blue>2024-12-31 19:03:51 -0300
commit736637680ac7b2cd0d0b878401a7e044fde0ee6a (patch)
treebf4feaf3f3f0e48207bf7a31ad8bcbff0f244091 /src/blu_cat/com
parent083e64da1d4b5b68579288bc1690ca90d3f0a2c0 (diff)
refa Split BluCat into several namespacesHEADmaster
Diffstat (limited to 'src/blu_cat/com')
-rw-r--r--src/blu_cat/com/command.cpp78
-rw-r--r--src/blu_cat/com/command.hpp92
-rw-r--r--src/blu_cat/com/job_queue.cpp66
-rw-r--r--src/blu_cat/com/job_queue.hpp57
-rw-r--r--src/blu_cat/com/worker.cpp39
-rw-r--r--src/blu_cat/com/worker.hpp38
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 */