Skip to content

Add Async Implementation Reference Module #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8472ca4
Initial commit, adding entt stuff
Kelwan Nov 21, 2022
f41cb1f
Set up testing and now working on ref test implementation
Kelwan Nov 21, 2022
30dd125
Added cpp execution, moving into more testing
Kelwan Nov 22, 2022
40f6c06
File restructure, separating code, testing use cases. Going to do a w…
Kelwan Dec 1, 2022
45b2da7
Changed tests, more fail safes and made entity creation asynchronous
Kelwan Dec 2, 2022
96a21d2
Separate functionality, make actually async, and consider more cases
Kelwan Dec 7, 2022
9e40e2b
Moving somewhere else, totally broken
Kelwan Dec 8, 2022
0857417
Lots of thread safety
Kelwan Dec 15, 2022
f52720d
Removed pending registry, opted for serialization instead. Data probl…
Kelwan Dec 16, 2022
7660f9c
Everything working again, added tick rate options and fixed some bugs
Kelwan Dec 20, 2022
54e0c9a
Split off entity code and ready for review
Kelwan Dec 21, 2022
cf21766
Code review, removing older styles of coding
Kelwan Dec 21, 2022
9d4423b
More code revision
Kelwan Dec 21, 2022
8fbdd85
Done code review
Kelwan Dec 21, 2022
7c76a64
Updated tests, rewrote code to fix lifetime issues
Kelwan Jan 4, 2023
2acd5ad
Fixed tick merging issues
Kelwan Jan 5, 2023
ff65046
Fixed tests, ready for review
Kelwan Jan 10, 2023
50f8c9d
Add disconnect
Kelwan Jan 10, 2023
a39ff7e
Specify unused variables
Kelwan Jan 10, 2023
b0453bd
Update to Clang 15.0.6
Kelwan Jan 10, 2023
b5f8cd3
Trying it again
Kelwan Jan 10, 2023
fc3e696
Trying more attribs
Kelwan Jan 10, 2023
8caac0c
More attempts to clang
Kelwan Jan 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ hedron_compile_commands_setup()

http_archive(
name = "com_grail_bazel_toolchain",
sha256 = "7fa5a8624b1148c36e09c7fa29ef6ee8b83f865219c9c219c9125aac78924758",
strip_prefix = "bazel-toolchain-c3131a6894804ee586d059c57ffe8e88d44172e1",
url = "https://github.com/grailbio/bazel-toolchain/archive/c3131a6894804ee586d059c57ffe8e88d44172e1.zip",
sha256 = "3cf5ac4bb7dae3776da586fe85685274f5d89cbb59436f50f572928354e72198",
strip_prefix = "bazel-toolchain-70a0fb556662fe3cadb07da32c91e232eb0d883d",
url = "https://github.com/grailbio/bazel-toolchain/archive/70a0fb556662fe3cadb07da32c91e232eb0d883d.zip",
)

load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies")
Expand All @@ -74,7 +74,8 @@ load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
llvm_toolchain(
name = "llvm_toolchain",
cxx_standard = {"linux": "c++20"},
llvm_version = "14.0.0",
distribution = "clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz",
llvm_version = "15.0.6",
)

load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains")
Expand Down
2 changes: 1 addition & 1 deletion bazel/copts.bzl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
copts = select({
"@bazel_tools//tools/cpp:msvc": ["/std:c++20", "/Zc:preprocessor", "/permissive-"],
"//conditions:default": ["-std=c++20"],
"//conditions:default": ["-std=c++20", "-fexperimental-library"],
})
121 changes: 79 additions & 42 deletions ecsact/runtime/async.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,51 +53,107 @@ typedef enum {
*/
ECSACT_ASYNC_ERR_PERMISSION_DENIED,

/**
* Client sent invalid connection options
*/
ECSACT_ASYNC_INVALID_CONNECTION_STRING,

/**
* Connection to the client is closed
*/
ECSACT_ASYNC_ERR_CONNECTION_CLOSED,

/**
* ExecutionOptions failed to merge
* ExecutionOptions failed to merge, and upon failure the connection is closed
*/
ECSACT_ASYNC_ERR_EXECUTION_MERGE_FAILURE,
} ecsact_async_error;

/**
* When an error occurs due to an async request this callback is invoked, only
* either @p async_err or @p execute_err will have a non-ok value.
* When an error occurs due to an async request this callback is invoked.
*
* @param async_err when there is no async error this will be @ref
* ECSACT_ASYNC_OK otherwise @see ecsact_async_error
* @param execute_err when there is no system execution error, this will be @ref
* ECSACT_EXEC_SYS_OK other @see ecsact_execute_systems_error
* @param request_id the request ID returned by an async request function that

* @param request_ids A list of request IDs returned by an async request
function that
* was responsible for this error
* @param callback_user_data the @ref
* ecsact_async_events_collector::error_callback_user_data
*/
typedef void (*ecsact_async_error_callback)(
//
ecsact_async_error async_err,
ecsact_async_error async_err,
int request_ids_length,
ecsact_async_request_id* request_ids,
void* callback_user_data
);

/**
* When an occurs from the system execution this callback is invoked.
*
* @param execute_err when there is no system execution error, this will be
* @ref ECSACT_EXEC_SYS_OK other @see ecsact_execute_systems_error
*/
typedef void (*ecsact_execute_sys_error_callback)(
//
ecsact_execute_systems_error execute_err,
ecsact_async_request_id request_id,
void* callback_user_data
);

/**
* When an entity is sucessfully created this callback is
* invoked.
*
* @param entity_id the entity id of the created entity
* @param request_id the request ID returned by the create entity callback
* @param callback_user_data the @ref
* ecsact_async_events_collector::error_callback_user_data
*/
typedef void (*ecsact_async_create_entity_callback)(
//
ecsact_entity_id entity_id,
ecsact_async_request_id request_id,
void* callback_user_data
);

typedef struct ecsact_async_events_collector {
/**
* invoked when an async request failed.
* @see ecsact_async_error_callback
* @see ecsact_async_error
*/
ecsact_async_error_callback async_error_callback;

/**
* `callback_user_data` passed to `async_error_callback`
*/
void* async_error_callback_user_data;

/**
* Invoked when a create entity request succeeds.
* @see ecsact_async_create_entity_callback
* @see ecsact_entity_id
* @see ecsact_async_error
*/
ecsact_async_create_entity_callback async_entity_callback;

/**
* `callback_user_data` passed to `async_entity_callback`
*/
void* async_entity_callback_user_data;

/**
* invoked when a system execution error occurred.
* @see ecsact_execute_sys_error_callback
* @see ecsact_execute_systems_error
*/
ecsact_async_error_callback error_callback;
ecsact_execute_sys_error_callback system_error_callback;

/**
* `callback_user_data` passed to `error_callback`
*/
void* error_callback_user_data;
void* system_error_callback_user_data;
} ecsact_async_events_collector;

/**
Expand All @@ -116,34 +172,10 @@ ECSACT_ASYNC_API_FN(
const ecsact_execution_options options
);

/**
* Enqueues system execution options at the specified ticks. If multiple
* invocations of `ecsact_async_enqueue_execution_options_at` happen for the
* same tick(s) the execution options will be _merged_.
*
* @param list_length the length of @p tick_list and @p options_list
* @param tick_list a sequential list of ticks the execution options in @p
* options_list will be used during system exeuction. Length is determined by @p
* list_length
* @param options_list a sequential list of execution options. Length is
* determined by @p list_length
* @returns a request ID representing this async request. Later used in @ref
* ecsact_async_error_callback if an error occurs
*/

ECSACT_ASYNC_API_FN(
ecsact_async_request_id,
ecsact_async_enqueue_execution_options_at
)
( //
int list_length,
const int* tick_list,
const ecsact_execution_options* options_list
);

/**
* Invokes the various callbacks in `execution_events` and `async_events` that
* have been pending.
* have been pending. If either a system or async error occurs it's treated
* as a call to ecscact_async_disconnect
*/
ECSACT_ASYNC_API_FN(void, ecsact_async_flush_events)
( //
Expand Down Expand Up @@ -171,12 +203,17 @@ ECSACT_ASYNC_API_FN(ecsact_async_request_id, ecsact_async_connect)
*/
ECSACT_ASYNC_API_FN(void, ecsact_async_disconnect)(void);

#define FOR_EACH_ECSACT_ASYNC_API_FN(fn, ...) \
fn(ecsact_async_enqueue_execution_options, __VA_ARGS__); \
fn(ecsact_async_enqueue_execution_options_at, __VA_ARGS__); \
fn(ecsact_async_flush_events, __VA_ARGS__); \
fn(ecsact_async_connect, __VA_ARGS__); \
fn(ecsact_async_disconnect, __VA_ARGS__);
/**
* Returns an entity
*/
ECSACT_ASYNC_API_FN(ecsact_async_request_id, ecsact_async_create_entity)(void);

#define FOR_EACH_ECSACT_ASYNC_API_FN(fn, ...) \
fn(ecsact_async_enqueue_execution_options, __VA_ARGS__); \
fn(ecsact_async_flush_events, __VA_ARGS__); \
fn(ecsact_async_connect, __VA_ARGS__); \
fn(ecsact_async_disconnect, __VA_ARGS__); \
fn(ecsact_async_create_entity, __VA_ARGS__);

#undef ECSACT_ASYNC_API
#undef ECSACT_ASYNC_API_FN
Expand Down
71 changes: 71 additions & 0 deletions ecsact/runtime/serialize.hh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,38 @@ std::vector<std::byte> serialize(const T& component_or_action) {
return bytes;
}

/**
* Serializes an ecsact_component when the type is unknown.
* @returns serialized action bytes
*/
inline std::vector<std::byte> serialize(const ecsact_component& component) {
std::vector<std::byte> out_component;
out_component.resize(ecsact_serialize_component_size(component.component_id));

ecsact_serialize_component(
component.component_id,
component.component_data,
reinterpret_cast<uint8_t*>(out_component.data())
);
return out_component;
}

/**
* Serializes an ecsact_action when the type is unknown.
* @returns serialized component bytes
*/
inline std::vector<std::byte> serialize(const ecsact_action& action) {
std::vector<std::byte> out_action;
out_action.resize(ecsact_serialize_action_size(action.action_id));

ecsact_serialize_action(
action.action_id,
action.action_data,
reinterpret_cast<uint8_t*>(out_action.data())
);
return out_action;
}

/**
* Calls `ecsact_deserialize_action` or `ecsact_deserialize_component` based on
* the type of @tp T.
Expand Down Expand Up @@ -115,4 +147,43 @@ int deserialize(
::ecsact::deserialize<T>(serialized_component_or_action, read_amount);
return read_amount;
}

/**
* Deserializes an ecsact_component when the type is unknown.
* @returns an ecsact_action
*/
inline std::vector<std::byte> deserialize(
const ecsact_action_id& id,
std::vector<std::byte>& serialized_action
) {
std::vector<std::byte> action_data;
action_data.resize(serialized_action.size());

ecsact_deserialize_action(
id,
reinterpret_cast<uint8_t*>(serialized_action.data()),
action_data.data()
);
return action_data;
}

/**
* Deserializes an ecsact_component when the type is unknown.
* @returns an ecsact_component_id
*/
inline std::vector<std::byte> deserialize(
const ecsact_component_id& id,
std::vector<std::byte>& serialized_component
) {
std::vector<std::byte> component_data;
component_data.resize(serialized_component.size());

ecsact_deserialize_component(
id,
reinterpret_cast<uint8_t*>(serialized_component.data()),
component_data.data()
);
return component_data;
}

} // namespace ecsact
41 changes: 41 additions & 0 deletions reference/async_reference/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
load("//bazel:copts.bzl", "copts")

package(default_visibility = ["//visiblity:public"])

exports_files([
"async_reference.hh",
"async_reference.cc",
"async.cc",
])

cc_library(
name = "async_reference",
srcs = ["async_reference.cc"],
hdrs = ["async_reference.hh"],
copts = copts,
visibility = ["//visibility:public"],
deps = [
"//:async",
"//:core",
"//reference/async_reference/callbacks:async_callbacks",
"//reference/async_reference/callbacks:execution_callbacks",
"//reference/async_reference/detail/c_execution_options",
"//reference/async_reference/entity_manager",
"//reference/async_reference/tick_manager",
"//reference/async_reference/util",
"//reference/async_reference/util:types",
],
)

cc_library(
name = "async",
srcs = ["async.cc"],
copts = copts,
defines = ["ECSACT_ASYNC_API_EXPORT="],
visibility = ["//visibility:public"],
deps = [
":async_reference",
"//:async",
],
)
35 changes: 35 additions & 0 deletions reference/async_reference/async.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <optional>

#include "ecsact/runtime/async.h"
#include "async_reference.hh"

namespace async {
std::optional<async_reference> reference;
}

ecsact_async_request_id ecsact_async_connect(const char* connection_string) {
async::reference.emplace();
return async::reference->connect(connection_string);
}

void ecsact_async_disconnect() {
async::reference->disconnect();
async::reference.reset();
}

void ecsact_async_flush_events(
const ecsact_execution_events_collector* execution_events,
const ecsact_async_events_collector* async_events
) {
async::reference->flush_events(execution_events, async_events);
}

ecsact_async_request_id ecsact_async_create_entity() {
return async::reference->create_entity_request();
}

ecsact_async_request_id ecsact_async_enqueue_execution_options(
const ecsact_execution_options options
) {
return async::reference->enqueue_execution_options(options);
}
Loading