Move app/service code from tactility-core to tactility (#14)
* Move app/service code from tactility-core to tactility * fix formatting * updated dev docs
This commit is contained in:
committed by
GitHub
parent
0c724e2e68
commit
e2209ccba8
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "core.h"
|
||||
#include "event_flag.h"
|
||||
|
||||
typedef EventFlag* ApiLock;
|
||||
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
#include "app_i.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static AppFlags tt_app_get_flags_default(AppType type);
|
||||
|
||||
// region Alloc/free
|
||||
|
||||
App tt_app_alloc(const AppManifest* manifest, Bundle* _Nullable parameters) {
|
||||
AppData* data = malloc(sizeof(AppData));
|
||||
*data = (AppData) {
|
||||
.mutex = tt_mutex_alloc(MutexTypeRecursive),
|
||||
.state = APP_STATE_INITIAL,
|
||||
.flags = tt_app_get_flags_default(manifest->type),
|
||||
.manifest = manifest,
|
||||
.parameters = parameters,
|
||||
.data = NULL
|
||||
};
|
||||
return (App*)data;
|
||||
}
|
||||
|
||||
void tt_app_free(App app) {
|
||||
AppData* data = (AppData*)app;
|
||||
if (data->parameters) {
|
||||
tt_bundle_free(data->parameters);
|
||||
}
|
||||
tt_mutex_free(data->mutex);
|
||||
free(data);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Internal
|
||||
|
||||
static void tt_app_lock(AppData* data) {
|
||||
tt_mutex_acquire(data->mutex, MutexTypeRecursive);
|
||||
}
|
||||
|
||||
static void tt_app_unlock(AppData* data) {
|
||||
tt_mutex_release(data->mutex);
|
||||
}
|
||||
|
||||
static AppFlags tt_app_get_flags_default(AppType type) {
|
||||
static const AppFlags DEFAULT_DESKTOP_FLAGS = {
|
||||
.show_toolbar = false,
|
||||
.show_statusbar = true
|
||||
};
|
||||
|
||||
static const AppFlags DEFAULT_APP_FLAGS = {
|
||||
.show_toolbar = true,
|
||||
.show_statusbar = true
|
||||
};
|
||||
|
||||
return type == AppTypeDesktop
|
||||
? DEFAULT_DESKTOP_FLAGS
|
||||
: DEFAULT_APP_FLAGS;
|
||||
}
|
||||
|
||||
// endregion Internal
|
||||
|
||||
// region Public getters & setters
|
||||
|
||||
void tt_app_set_state(App app, AppState state) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
data->state = state;
|
||||
tt_app_unlock(data);
|
||||
}
|
||||
|
||||
AppState tt_app_get_state(App app) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
AppState state = data->state;
|
||||
tt_app_unlock(data);
|
||||
return state;
|
||||
}
|
||||
|
||||
const AppManifest* tt_app_get_manifest(App app) {
|
||||
AppData* data = (AppData*)app;
|
||||
// No need to lock const data;
|
||||
return data->manifest;
|
||||
}
|
||||
|
||||
AppFlags tt_app_get_flags(App app) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
AppFlags flags = data->flags;
|
||||
tt_app_unlock(data);
|
||||
return flags;
|
||||
}
|
||||
|
||||
void tt_app_set_flags(App app, AppFlags flags) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
data->flags = flags;
|
||||
tt_app_unlock(data);
|
||||
}
|
||||
|
||||
void* tt_app_get_data(App app) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
void* value = data->data;
|
||||
tt_app_unlock(data);
|
||||
return value;
|
||||
}
|
||||
|
||||
void tt_app_set_data(App app, void* value) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
data->data = value;
|
||||
tt_app_unlock(data);
|
||||
}
|
||||
|
||||
/** TODO: Make this thread-safe.
|
||||
* In practice, the bundle is writeable, so someone could be writing to it
|
||||
* while it is being accessed from another thread.
|
||||
* Consider creating MutableBundle vs Bundle.
|
||||
* Consider not exposing bundle, but expose `app_get_bundle_int(key)` methods with locking in it.
|
||||
*/
|
||||
Bundle* _Nullable tt_app_get_parameters(App app) {
|
||||
AppData* data = (AppData*)app;
|
||||
tt_app_lock(data);
|
||||
Bundle* bundle = data->parameters;
|
||||
tt_app_unlock(data);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
// endregion Public getters & setters
|
||||
@@ -1,51 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "app_manifest.h"
|
||||
#include "bundle.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
APP_STATE_INITIAL, // App is being activated in loader
|
||||
APP_STATE_STARTED, // App is in memory
|
||||
APP_STATE_SHOWING, // App view is created
|
||||
APP_STATE_HIDING, // App view is destroyed
|
||||
APP_STATE_STOPPED // App is not in memory
|
||||
} AppState;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
bool show_statusbar : 1;
|
||||
bool show_toolbar : 1;
|
||||
};
|
||||
unsigned char flags;
|
||||
} AppFlags;
|
||||
|
||||
typedef void* App;
|
||||
|
||||
/** @brief Create an app
|
||||
* @param manifest
|
||||
* @param parameters optional bundle. memory ownership is transferred to App
|
||||
* @return
|
||||
*/
|
||||
App tt_app_alloc(const AppManifest* manifest, Bundle* _Nullable parameters);
|
||||
void tt_app_free(App app);
|
||||
|
||||
void tt_app_set_state(App app, AppState state);
|
||||
AppState tt_app_get_state(App app);
|
||||
|
||||
const AppManifest* tt_app_get_manifest(App app);
|
||||
|
||||
AppFlags tt_app_get_flags(App app);
|
||||
void tt_app_set_flags(App app, AppFlags flags);
|
||||
|
||||
void* _Nullable tt_app_get_data(App app);
|
||||
void tt_app_set_data(App app, void* data);
|
||||
|
||||
Bundle* _Nullable tt_app_get_parameters(App app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "app.h"
|
||||
|
||||
#include "app_manifest.h"
|
||||
#include "mutex.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
Mutex* mutex;
|
||||
const AppManifest* manifest;
|
||||
AppState state;
|
||||
AppFlags flags;
|
||||
/** @brief Optional parameters to start the app with
|
||||
* When these are stored in the app struct, the struct takes ownership.
|
||||
* Do not mutate after app creation.
|
||||
*/
|
||||
Bundle* _Nullable parameters;
|
||||
/** @brief @brief Contextual data related to the running app's instance
|
||||
* The app can attach its data to this.
|
||||
* The lifecycle is determined by the on_start and on_stop methods in the AppManifest.
|
||||
* These manifest methods can optionally allocate/free data that is attached here.
|
||||
*/
|
||||
void* _Nullable data;
|
||||
} AppData;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,70 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Forward declarations
|
||||
typedef struct _lv_obj_t lv_obj_t;
|
||||
typedef void* App;
|
||||
|
||||
typedef enum {
|
||||
AppTypeDesktop,
|
||||
AppTypeSystem,
|
||||
AppTypeSettings,
|
||||
AppTypeUser
|
||||
} AppType;
|
||||
|
||||
typedef void (*AppOnStart)(App app);
|
||||
typedef void (*AppOnStop)(App app);
|
||||
typedef void (*AppOnShow)(App app, lv_obj_t* parent);
|
||||
typedef void (*AppOnHide)(App app);
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* The identifier by which the app is launched by the system and other apps.
|
||||
*/
|
||||
const char* id;
|
||||
|
||||
/**
|
||||
* The user-readable name of the app. Used in UI.
|
||||
*/
|
||||
const char* name;
|
||||
|
||||
/**
|
||||
* Optional icon.
|
||||
*/
|
||||
const char* _Nullable icon;
|
||||
|
||||
/**
|
||||
* App type affects launch behaviour.
|
||||
*/
|
||||
const AppType type;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when app is started.
|
||||
*/
|
||||
const AppOnStart _Nullable on_start;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when app is stopped.
|
||||
*/
|
||||
const AppOnStop _Nullable on_stop;
|
||||
|
||||
/**
|
||||
* Non-blocking method to create the GUI
|
||||
*/
|
||||
const AppOnShow _Nullable on_show;
|
||||
|
||||
/**
|
||||
* Non-blocking method, called before gui is destroyed
|
||||
*/
|
||||
const AppOnHide _Nullable on_hide;
|
||||
} AppManifest;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
#include "app_manifest_registry.h"
|
||||
|
||||
#include "m-dict.h"
|
||||
#include "m_cstr_dup.h"
|
||||
#include "mutex.h"
|
||||
#include "tactility_core.h"
|
||||
|
||||
#define TAG "app_registry"
|
||||
|
||||
DICT_DEF2(AppManifestDict, const char*, M_CSTR_DUP_OPLIST, const AppManifest*, M_PTR_OPLIST)
|
||||
|
||||
#define APP_REGISTRY_FOR_EACH(manifest_var_name, code_to_execute) \
|
||||
{ \
|
||||
app_registry_lock(); \
|
||||
AppManifestDict_it_t it; \
|
||||
for (AppManifestDict_it(it, app_manifest_dict); !AppManifestDict_end_p(it); AppManifestDict_next(it)) { \
|
||||
const AppManifest*(manifest_var_name) = AppManifestDict_cref(it)->value; \
|
||||
code_to_execute; \
|
||||
} \
|
||||
app_registry_unlock(); \
|
||||
}
|
||||
|
||||
AppManifestDict_t app_manifest_dict;
|
||||
Mutex* hash_mutex = NULL;
|
||||
|
||||
void tt_app_manifest_registry_init() {
|
||||
tt_assert(hash_mutex == NULL);
|
||||
hash_mutex = tt_mutex_alloc(MutexTypeNormal);
|
||||
AppManifestDict_init(app_manifest_dict);
|
||||
}
|
||||
|
||||
void app_registry_lock() {
|
||||
tt_assert(hash_mutex != NULL);
|
||||
tt_mutex_acquire(hash_mutex, TtWaitForever);
|
||||
}
|
||||
|
||||
void app_registry_unlock() {
|
||||
tt_assert(hash_mutex != NULL);
|
||||
tt_mutex_release(hash_mutex);
|
||||
}
|
||||
|
||||
void tt_app_manifest_registry_add(const AppManifest _Nonnull* manifest) {
|
||||
TT_LOG_I(TAG, "adding %s", manifest->id);
|
||||
|
||||
app_registry_lock();
|
||||
AppManifestDict_set_at(app_manifest_dict, manifest->id, manifest);
|
||||
app_registry_unlock();
|
||||
}
|
||||
|
||||
void tt_app_manifest_registry_remove(const AppManifest _Nonnull* manifest) {
|
||||
TT_LOG_I(TAG, "removing %s", manifest->id);
|
||||
app_registry_lock();
|
||||
AppManifestDict_erase(app_manifest_dict, manifest->id);
|
||||
app_registry_unlock();
|
||||
}
|
||||
|
||||
const AppManifest _Nullable* tt_app_manifest_registry_find_by_id(const char* id) {
|
||||
app_registry_lock();
|
||||
const AppManifest _Nullable** manifest = AppManifestDict_get(app_manifest_dict, id);
|
||||
app_registry_unlock();
|
||||
return (manifest != NULL) ? *manifest : NULL;
|
||||
}
|
||||
|
||||
void tt_app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback) {
|
||||
APP_REGISTRY_FOR_EACH(manifest, {
|
||||
if (manifest->type == type) {
|
||||
callback(manifest, context);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tt_app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context) {
|
||||
APP_REGISTRY_FOR_EACH(manifest, {
|
||||
callback(manifest, context);
|
||||
});
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "app_manifest.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*AppManifestCallback)(const AppManifest*, void* context);
|
||||
|
||||
void tt_app_manifest_registry_init();
|
||||
void tt_app_manifest_registry_add(const AppManifest _Nonnull* manifest);
|
||||
void tt_app_manifest_registry_remove(const AppManifest _Nonnull* manifest);
|
||||
const AppManifest _Nullable* tt_app_manifest_registry_find_by_id(const char* id);
|
||||
void tt_app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context);
|
||||
void tt_app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "core.h"
|
||||
|
||||
#include "app_manifest_registry.h"
|
||||
#include "service_registry.h"
|
||||
|
||||
#define TAG "tactility"
|
||||
|
||||
void tt_core_init() {
|
||||
TT_LOG_I(TAG, "core init start");
|
||||
tt_assert(!tt_kernel_is_irq());
|
||||
tt_service_registry_init();
|
||||
tt_app_manifest_registry_init();
|
||||
TT_LOG_I(TAG, "core init complete");
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tactility_core.h"
|
||||
|
||||
#include "event_flag.h"
|
||||
#include "kernel.h"
|
||||
#include "message_queue.h"
|
||||
#include "mutex.h"
|
||||
#include "pubsub.h"
|
||||
#include "semaphore.h"
|
||||
#include "string.h"
|
||||
#include "thread.h"
|
||||
#include "timer.h"
|
||||
#include "tt_stream_buffer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void tt_core_init();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -8,18 +8,20 @@
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TT_RETURNS_NONNULL __attribute__((returns_nonnull))
|
||||
|
||||
#define TT_WARN_UNUSED __attribute__((warn_unused_result))
|
||||
|
||||
#define TT_UNUSED __attribute__((unused))
|
||||
|
||||
#define TT_WEAK __attribute__((weak))
|
||||
|
||||
#define TT_PACKED __attribute__((packed))
|
||||
|
||||
#define TT_PLACE_IN_SECTION(x) __attribute__((section(x)))
|
||||
|
||||
#define TT_ALIGN(n) __attribute__((aligned(n)))
|
||||
|
||||
// Used by portENABLE_INTERRUPTS and portDISABLE_INTERRUPTS?
|
||||
#ifdef ESP_TARGET
|
||||
#define TT_IS_IRQ_MODE() (xPortInIsrContext() == pdTRUE)
|
||||
@@ -30,7 +32,3 @@ extern "C" {
|
||||
#define TT_IS_ISR() (TT_IS_IRQ_MODE())
|
||||
|
||||
#define TT_CHECK_RETURN __attribute__((__warn_unused_result__))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,114 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) \
|
||||
#define TT_MAX(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) \
|
||||
#define TT_MIN(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(a) ({ (a) < 0 ? -(a) : (a); })
|
||||
#endif
|
||||
#define TT_ABS(a) ({ (a) < 0 ? -(a) : (a); })
|
||||
|
||||
#ifndef ROUND_UP_TO
|
||||
#define ROUND_UP_TO(a, b) \
|
||||
#define TT_ROUND_UP_TO(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a / _b + !!(_a % _b); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef CLAMP
|
||||
#define CLAMP(x, upper, lower) (MIN(upper, MAX(x, lower)))
|
||||
#endif
|
||||
#define TT_CLAMP(x, upper, lower) (TT_MIN(upper, TT_MAX(x, lower)))
|
||||
|
||||
#ifndef COUNT_OF
|
||||
#define COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
#define TT_COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#ifndef TT_SWAP
|
||||
#define TT_SWAP(x, y) \
|
||||
#define TT_SWAP(x, y) \
|
||||
do { \
|
||||
typeof(x) SWAP = x; \
|
||||
x = y; \
|
||||
y = SWAP; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef PLACE_IN_SECTION
|
||||
#define PLACE_IN_SECTION(x) __attribute__((section(x)))
|
||||
#endif
|
||||
#define TT_STRINGIFY(x) #x
|
||||
|
||||
#ifndef ALIGN
|
||||
#define ALIGN(n) __attribute__((aligned(n)))
|
||||
#endif
|
||||
#define TT_TOSTRING(x) TT_STRINGIFY(x)
|
||||
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
#define TT_CONCATENATE(a, b) CONCATENATE_(a, b)
|
||||
#define TT_CONCATENATE_(a, b) a##b
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(X) (void)(X)
|
||||
#endif
|
||||
|
||||
#ifndef STRINGIFY
|
||||
#define STRINGIFY(x) #x
|
||||
#endif
|
||||
|
||||
#ifndef TOSTRING
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#endif
|
||||
|
||||
#ifndef CONCATENATE
|
||||
#define CONCATENATE(a, b) CONCATENATE_(a, b)
|
||||
#define CONCATENATE_(a, b) a##b
|
||||
#endif
|
||||
|
||||
#ifndef REVERSE_BYTES_U32
|
||||
#define REVERSE_BYTES_U32(x) \
|
||||
#define TT_REVERSE_BYTES_U32(x) \
|
||||
((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | \
|
||||
(((x) & 0xFF000000) >> 24))
|
||||
#endif
|
||||
|
||||
#ifndef TT_BIT
|
||||
#define TT_BIT(x, n) (((x) >> (n)) & 1)
|
||||
#endif
|
||||
|
||||
#ifndef TT_BIT_SET
|
||||
#define TT_BIT_SET(x, n) \
|
||||
#define TT_BIT_SET(x, n) \
|
||||
({ \
|
||||
__typeof__(x) _x = (1); \
|
||||
(x) |= (_x << (n)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef TT_BIT_CLEAR
|
||||
#define TT_BIT_CLEAR(x, n) \
|
||||
#define TT_BIT_CLEAR(x, n) \
|
||||
({ \
|
||||
__typeof__(x) _x = (1); \
|
||||
(x) &= ~(_x << (n)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define TT_SW_MEMBARRIER() asm volatile("" : : : "memory")
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/** @file:m_cstr_dup.h
|
||||
* @brief Helpers for mlib
|
||||
*/
|
||||
#pragma once
|
||||
#include <m-core.h>
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
#include "log.h"
|
||||
#include "service_i.h"
|
||||
#include "tactility_core.h"
|
||||
|
||||
// region Alloc/free
|
||||
|
||||
ServiceData* tt_service_alloc(const ServiceManifest* _Nonnull manifest) {
|
||||
ServiceData* data = malloc(sizeof(ServiceData));
|
||||
*data = (ServiceData) {
|
||||
.manifest = manifest,
|
||||
.mutex = tt_mutex_alloc(MutexTypeRecursive),
|
||||
.data = NULL
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
void tt_service_free(ServiceData* data) {
|
||||
tt_assert(data);
|
||||
tt_mutex_free(data->mutex);
|
||||
free(data);
|
||||
}
|
||||
|
||||
// endregion Alloc/free
|
||||
|
||||
// region Internal
|
||||
|
||||
static void tt_service_lock(ServiceData * data) {
|
||||
tt_mutex_acquire(data->mutex, MutexTypeRecursive);
|
||||
}
|
||||
|
||||
static void tt_service_unlock(ServiceData* data) {
|
||||
tt_mutex_release(data->mutex);
|
||||
}
|
||||
|
||||
// endregion Internal
|
||||
|
||||
// region Getters & Setters
|
||||
|
||||
const ServiceManifest* tt_service_get_manifest(Service service) {
|
||||
ServiceData* data = (ServiceData*)service;
|
||||
tt_service_lock(data);
|
||||
const ServiceManifest* manifest = data->manifest;
|
||||
tt_service_unlock(data);
|
||||
return manifest;
|
||||
}
|
||||
|
||||
void tt_service_set_data(Service service, void* value) {
|
||||
ServiceData* data = (ServiceData*)service;
|
||||
tt_service_lock(data);
|
||||
data->data = value;
|
||||
tt_service_unlock(data);
|
||||
}
|
||||
|
||||
void* _Nullable tt_service_get_data(Service service) {
|
||||
ServiceData* data = (ServiceData*)service;
|
||||
tt_service_lock(data);
|
||||
void* value = data->data;
|
||||
tt_service_unlock(data);
|
||||
return value;
|
||||
}
|
||||
|
||||
// endregion Getters & Setters
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "service_manifest.h"
|
||||
|
||||
typedef void* Service;
|
||||
|
||||
const ServiceManifest* tt_service_get_manifest(Service service);
|
||||
|
||||
void tt_service_set_data(Service service, void* value);
|
||||
void* _Nullable tt_service_get_data(Service service);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "service.h"
|
||||
|
||||
#include "mutex.h"
|
||||
#include "service_manifest.h"
|
||||
|
||||
typedef struct {
|
||||
Mutex* mutex;
|
||||
const ServiceManifest* manifest;
|
||||
void* data;
|
||||
} ServiceData;
|
||||
|
||||
ServiceData* tt_service_alloc(const ServiceManifest* _Nonnull manifest);
|
||||
void tt_service_free(ServiceData* _Nonnull service);
|
||||
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* Service;
|
||||
|
||||
typedef void (*ServiceOnStart)(Service service);
|
||||
typedef void (*ServiceOnStop)(Service service);
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* The identifier by which the app is launched by the system and other apps.
|
||||
*/
|
||||
const char* _Nonnull id;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when service is started.
|
||||
*/
|
||||
const ServiceOnStart _Nullable on_start;
|
||||
|
||||
/**
|
||||
* Non-blocking method to call when service is stopped.
|
||||
*/
|
||||
const ServiceOnStop _Nullable on_stop;
|
||||
|
||||
} ServiceManifest;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,136 +0,0 @@
|
||||
#include "service_registry.h"
|
||||
|
||||
#include "m-dict.h"
|
||||
#include "m_cstr_dup.h"
|
||||
#include "mutex.h"
|
||||
#include "service_i.h"
|
||||
#include "tactility_core.h"
|
||||
|
||||
#define TAG "service_registry"
|
||||
|
||||
DICT_DEF2(ServiceManifestDict, const char*, M_CSTR_DUP_OPLIST, const ServiceManifest*, M_PTR_OPLIST)
|
||||
DICT_DEF2(ServiceInstanceDict, const char*, M_CSTR_DUP_OPLIST, const ServiceData*, M_PTR_OPLIST)
|
||||
|
||||
#define APP_REGISTRY_FOR_EACH(manifest_var_name, code_to_execute) \
|
||||
{ \
|
||||
service_registry_manifest_lock(); \
|
||||
ServiceManifestDict_it_t it; \
|
||||
for (ServiceManifestDict_it(it, service_manifest_dict); !ServiceManifestDict_end_p(it); ServiceManifestDict_next(it)) { \
|
||||
const ServiceManifest*(manifest_var_name) = ServiceManifestDict_cref(it)->value; \
|
||||
code_to_execute; \
|
||||
} \
|
||||
service_registry_manifest_unlock(); \
|
||||
}
|
||||
|
||||
static ServiceManifestDict_t service_manifest_dict;
|
||||
static ServiceInstanceDict_t service_instance_dict;
|
||||
static Mutex* manifest_mutex = NULL;
|
||||
static Mutex* instance_mutex = NULL;
|
||||
|
||||
void tt_service_registry_init() {
|
||||
tt_assert(manifest_mutex == NULL);
|
||||
manifest_mutex = tt_mutex_alloc(MutexTypeNormal);
|
||||
ServiceManifestDict_init(service_manifest_dict);
|
||||
|
||||
tt_assert(instance_mutex == NULL);
|
||||
instance_mutex = tt_mutex_alloc(MutexTypeNormal);
|
||||
ServiceInstanceDict_init(service_instance_dict);
|
||||
}
|
||||
|
||||
void service_registry_instance_lock() {
|
||||
tt_assert(instance_mutex != NULL);
|
||||
tt_mutex_acquire(instance_mutex, TtWaitForever);
|
||||
}
|
||||
|
||||
void service_registry_instance_unlock() {
|
||||
tt_assert(instance_mutex != NULL);
|
||||
tt_mutex_release(instance_mutex);
|
||||
}
|
||||
|
||||
void service_registry_manifest_lock() {
|
||||
tt_assert(manifest_mutex != NULL);
|
||||
tt_mutex_acquire(manifest_mutex, TtWaitForever);
|
||||
}
|
||||
|
||||
void service_registry_manifest_unlock() {
|
||||
tt_assert(manifest_mutex != NULL);
|
||||
tt_mutex_release(manifest_mutex);
|
||||
}
|
||||
void tt_service_registry_add(const ServiceManifest _Nonnull* manifest) {
|
||||
TT_LOG_I(TAG, "adding %s", manifest->id);
|
||||
|
||||
service_registry_manifest_lock();
|
||||
ServiceManifestDict_set_at(service_manifest_dict, manifest->id, manifest);
|
||||
service_registry_manifest_unlock();
|
||||
}
|
||||
|
||||
void tt_service_registry_remove(const ServiceManifest _Nonnull* manifest) {
|
||||
TT_LOG_I(TAG, "removing %s", manifest->id);
|
||||
service_registry_manifest_lock();
|
||||
ServiceManifestDict_erase(service_manifest_dict, manifest->id);
|
||||
service_registry_manifest_unlock();
|
||||
}
|
||||
|
||||
const ServiceManifest* _Nullable tt_service_registry_find_manifest_by_id(const char* id) {
|
||||
service_registry_manifest_lock();
|
||||
const ServiceManifest** _Nullable manifest = ServiceManifestDict_get(service_manifest_dict, id);
|
||||
service_registry_manifest_unlock();
|
||||
return (manifest != NULL) ? *manifest : NULL;
|
||||
}
|
||||
|
||||
ServiceData* _Nullable service_registry_find_instance_by_id(const char* id) {
|
||||
service_registry_instance_lock();
|
||||
const ServiceData** _Nullable service_ptr = ServiceInstanceDict_get(service_instance_dict, id);
|
||||
if (service_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ServiceData* service = (ServiceData*)*service_ptr;
|
||||
service_registry_instance_unlock();
|
||||
return service;
|
||||
}
|
||||
|
||||
void tt_service_registry_for_each_manifest(ServiceManifestCallback callback, void* _Nullable context) {
|
||||
APP_REGISTRY_FOR_EACH(manifest, {
|
||||
callback(manifest, context);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: return proper error/status instead of BOOL
|
||||
bool tt_service_registry_start(const char* service_id) {
|
||||
TT_LOG_I(TAG, "starting %s", service_id);
|
||||
const ServiceManifest* manifest = tt_service_registry_find_manifest_by_id(service_id);
|
||||
if (manifest == NULL) {
|
||||
TT_LOG_E(TAG, "manifest not found for service %s", service_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
Service service = tt_service_alloc(manifest);
|
||||
manifest->on_start(service);
|
||||
|
||||
service_registry_instance_lock();
|
||||
ServiceInstanceDict_set_at(service_instance_dict, manifest->id, service);
|
||||
service_registry_instance_unlock();
|
||||
TT_LOG_I(TAG, "started %s", service_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tt_service_registry_stop(const char* service_id) {
|
||||
TT_LOG_I(TAG, "stopping %s", service_id);
|
||||
ServiceData* service = service_registry_find_instance_by_id(service_id);
|
||||
if (service == NULL) {
|
||||
TT_LOG_W(TAG, "service not running: %s", service_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
service->manifest->on_stop(service);
|
||||
tt_service_free(service);
|
||||
|
||||
service_registry_instance_lock();
|
||||
ServiceInstanceDict_erase(service_instance_dict, service_id);
|
||||
service_registry_instance_unlock();
|
||||
|
||||
TT_LOG_I(TAG, "stopped %s", service_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "service_manifest.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void (*ServiceManifestCallback)(const ServiceManifest*, void* context);
|
||||
|
||||
void tt_service_registry_init();
|
||||
|
||||
void tt_service_registry_add(const ServiceManifest* manifest);
|
||||
void tt_service_registry_remove(const ServiceManifest* manifest);
|
||||
const ServiceManifest _Nullable* tt_service_registry_find_manifest_by_id(const char* id);
|
||||
void tt_service_registry_for_each_manifest(ServiceManifestCallback callback, void* _Nullable context);
|
||||
|
||||
bool tt_service_registry_start(const char* service_id);
|
||||
bool tt_service_registry_stop(const char* service_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -3,13 +3,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "app.h"
|
||||
#include "check.h"
|
||||
#include "core.h"
|
||||
#include "core_defines.h"
|
||||
#include "core_extra_defines.h"
|
||||
#include "core_types.h"
|
||||
#include "critical.h"
|
||||
#include "event_flag.h"
|
||||
#include "log.h"
|
||||
#include "service.h"
|
||||
|
||||
Reference in New Issue
Block a user