This commit is contained in:
chatlanin 2022-04-11 10:23:05 +03:00
commit b4fc91f41b
18 changed files with 332 additions and 0 deletions

14
README.md Normal file
View File

@ -0,0 +1,14 @@
![actfm's logo](./logo.png)
*The actor model is well described and if you dont know anything about it, you can read about it elsewhere.*
**This Actor Model behaves as follows:**
- An Actor is a unit of computation. It can accept a message and asynchronously perform some action based on user-specified behaviour.
- Actors have a “sendbox”, usually an in-memory queue that stores messages sent to that actor.
- Actors do not access shared state.
- Actors “own” any state they operate on, so the need for locking mechanisms is reduced*.
**Heres how it work:**
- Client code define the type of the message an actor can handle, and the type of the result produced by that actor using template parameters. In other words, the actors are statically typed.
- There have a simple actor interface. Clients send a message to an actor in two ways: actor.send if they dont expect a response, or actor.expect if a response is required.
- Actor systems are instantiated with a thread pool onto which work dispatched.
- Actor systems are instantiated with a scheduler which handle the dispatching of tasks onto the thread pool in a fair manner.

43
bin/main.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "actfm.hpp"
#include "logger/logger.hpp"
using result_t = std::vector<int>;
struct message
{
result_t data;
};
class sorting : public actfm::actor<message, result_t>
{
public:
result_t set_message(message ms, actfm::actor<message, result_t>* ac = nullptr) override
{
result_t res;
if (ac)
{}
else
{
std::sort(ms.data.begin(), ms.data.end());
}
return res;
}
};
int main(int argc, char *argv[])
{
hack::log()("run example");
message ms;
ms.data = { 1, 5, 7, 9, 2, 4, 6, 8 };
sorting sort;
sort.set_message(ms);
actfm::actor_controller::instance().set_actro(sort);
hack::log()("completed");
}

10
bin/meson.build Normal file
View File

@ -0,0 +1,10 @@
src = [ 'main.cpp' ]
deps += actfm_dep
executable(
'actorfm',
src,
dependencies : deps,
cpp_args: args
)

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

37
meson.build Normal file
View File

@ -0,0 +1,37 @@
# https://pixorblog.wordpress.com/2019/07/27/a-meson-starter-script-for-c-projects
project(
'actorfm',
'cpp',
version : '0.0.1',
default_options : ['cpp_std=c++2a']
)
add_project_arguments (
'-Wpedantic',
'-Wshadow',
'-Wno-comment',
'-Wunused-but-set-variable',
language: 'cpp'
)
compiler = meson.get_compiler('cpp')
if compiler.get_id() == 'gcc'
message('Compiler: GCC')
elif compiler.get_id() == 'clang'
message('Compiler: LLVM/clang')
endif
deps = [
dependency('threads'),
]
inc = []
inc += include_directories('.', join_paths('.', 'subprojects'))
args = []
hack = subproject('hack')
deps += hack.get_variable('logger_dep')
subdir('src')
subdir('bin')
#subdir('tests')

15
run Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
PROJECT_NAME="actorfm"
TEST="meson test -C build"
RUN="./build/bin/$PROJECT_NAME"
command meson compile -C build
if [[ $1 == "test" ]]; then
command $TEST
else
command $RUN
fi
return 0

3
src/actfm.hpp Normal file
View File

@ -0,0 +1,3 @@
#include "actor.hpp"
#include "actor_controller.hpp"

24
src/actor.hpp Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include <vector>
#include <thread>
namespace actfm
{
template<typename message_t, typename result_t>
class actor
{
public:
virtual ~actor() {}
public:
virtual result_t set_message(message_t ms, actor* ac = nullptr) = 0;
void send(message_t ms, actor* ac = nullptr)
{}
result_t expect(message_t ms, actor* ac = nullptr)
{}
};
}

25
src/actor_controller.hpp Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <memory>
#include "scheduler.hpp"
namespace actfm
{
class actor_controller
{
public:
actor_controller() : sch { std::make_unique<scheduler>() } {}
static actor_controller& instance() { static actor_controller ac; return ac; }
template<typename actor_t>
void set_actro(actor_t& actor)
{
sch->set_actor(actor);
}
private:
std::unique_ptr<scheduler> sch;
};
}

16
src/meson.build Normal file
View File

@ -0,0 +1,16 @@
inc += include_directories('.')
subdir('thread_pool')
deps += thread_pool_dep
lib = library(
'actfm',
include_directories : inc,
dependencies : deps,
cpp_args: args
)
actfm_dep = declare_dependency(
include_directories: inc,
link_with: lib,
)

36
src/scheduler.hpp Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <memory>
#include "thread_pool/thread_pool.hpp"
#include "logger/logger.hpp"
namespace actfm
{
class scheduler
{
public:
scheduler() : th_pool { std::make_unique<thread_pool>() }
{
}
template<typename actor_t>
void set_actor(actor_t& actor)
{
hack::log()("ref semantic");
}
template<typename actor_t>
void set_actor(actor_t&& actor)
{
hack::log()("move semantic");
}
private:
std::unique_ptr<thread_pool> th_pool;
};
}

View File

@ -0,0 +1,15 @@
headers = ['thread_pool.hpp']
sources = ['thread_pool.cpp']
lib = library(
'thread_pool',
include_directories : inc,
sources: [headers, sources],
dependencies : deps,
cpp_args: args
)
thread_pool_dep = declare_dependency(
include_directories: inc,
link_with: lib,
)

View File

@ -0,0 +1,33 @@
#include "thread_pool.hpp"
namespace actfm
{
thread_pool::thread_pool()
{
const auto thread_count = std::thread::hardware_concurrency();
try
{
for (auto i = 0u; i < thread_count; ++i)
pool.emplace_back(std::thread(&thread_pool::worker, this));
}
catch (std::exception& e)
{
hack::log()(e.what());
}
}
thread_pool::~thread_pool()
{
done = true;
hack::log()("thread_pool completed");
}
void thread_pool::worker()
{
while (!done)
{
hack::log()("run thread");
}
};
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <vector>
#include <thread>
#include "logger/logger.hpp"
namespace actfm
{
class thread_pool
{
using Pool = std::vector<std::thread>;
public:
thread_pool();
~thread_pool();
private:
void worker();
private:
Pool pool;
bool done { false };
};
}

15
src/threadsafe_queue.hpp Normal file
View File

@ -0,0 +1,15 @@
#pragma once
namespace actfm
{
template<typename data_t>
class threadsafe_queue
{
private:
struct node
{
};
};
}

15
subprojects/gtest.wrap Normal file
View File

@ -0,0 +1,15 @@
[wrap-file]
directory = googletest-release-1.11.0
source_url = https://github.com/google/googletest/archive/release-1.11.0.tar.gz
source_filename = gtest-1.11.0.tar.gz
source_hash = b4870bf121ff7795ba20d20bcdd8627b8e088f2d1dab299a031c1034eddc93d5
patch_filename = gtest_1.11.0-2_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/gtest_1.11.0-2/get_patch
patch_hash = 764530d812ac161c9eab02a8cfaec67c871fcfc5548e29fd3d488070913d4e94
[provide]
gtest = gtest_dep
gtest_main = gtest_main_dep
gmock = gmock_dep
gmock_main = gmock_main_dep

6
subprojects/hack.wrap Normal file
View File

@ -0,0 +1,6 @@
[wrap-git]
url = https://github.com/azchatlanin/hack.git
revision = master
[provide]
hack = hack_dep

0
tests/meson.build Normal file
View File