init
This commit is contained in:
commit
b4fc91f41b
14
README.md
Normal file
14
README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
![actfm's logo](./logo.png)
|
||||||
|
*The actor model is well described and if you don’t 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*.
|
||||||
|
|
||||||
|
**Here’s 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 don’t 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
43
bin/main.cpp
Normal 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
10
bin/meson.build
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
src = [ 'main.cpp' ]
|
||||||
|
|
||||||
|
deps += actfm_dep
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'actorfm',
|
||||||
|
src,
|
||||||
|
dependencies : deps,
|
||||||
|
cpp_args: args
|
||||||
|
)
|
37
meson.build
Normal file
37
meson.build
Normal 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
15
run
Executable 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
3
src/actfm.hpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "actor.hpp"
|
||||||
|
#include "actor_controller.hpp"
|
||||||
|
|
24
src/actor.hpp
Normal file
24
src/actor.hpp
Normal 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
25
src/actor_controller.hpp
Normal 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
16
src/meson.build
Normal 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
36
src/scheduler.hpp
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
15
src/thread_pool/meson.build
Normal file
15
src/thread_pool/meson.build
Normal 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,
|
||||||
|
)
|
33
src/thread_pool/thread_pool.cpp
Normal file
33
src/thread_pool/thread_pool.cpp
Normal 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");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
25
src/thread_pool/thread_pool.hpp
Normal file
25
src/thread_pool/thread_pool.hpp
Normal 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
15
src/threadsafe_queue.hpp
Normal 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
15
subprojects/gtest.wrap
Normal 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
6
subprojects/hack.wrap
Normal 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
0
tests/meson.build
Normal file
Loading…
Reference in New Issue
Block a user