mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-08-17 23:55:04 +00:00
Compare commits
5 Commits
d479359613
...
a2a802eaa2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2a802eaa2 | ||
|
|
e801dcf397 | ||
|
|
469cf0d275 | ||
|
|
cca7224252 | ||
|
|
2433aeb2d8 |
@ -1,15 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <tactility/service/service_instance.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace tt::service {
|
||||
|
||||
enum class State {
|
||||
Starting,
|
||||
Started,
|
||||
Stopping,
|
||||
Stopped
|
||||
};
|
||||
using State = ::ServiceState;
|
||||
|
||||
// Forward declaration
|
||||
class ServiceContext;
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/service/service_paths.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ void attachDevices() {
|
||||
// We search for the manifest first, because during the initial start() during boot
|
||||
// the service won't be registered yet.
|
||||
if (service::findManifestById("Gui") != nullptr) {
|
||||
if (service::getState("Gui") == service::State::Stopped) {
|
||||
if (service::getState("Gui") == SERVICE_STATE_STOPPED) {
|
||||
service::startService("Gui");
|
||||
} else {
|
||||
LOG_E(TAG, "Gui service is not in Stopped state");
|
||||
@ -112,7 +112,7 @@ void attachDevices() {
|
||||
// We search for the manifest first, because during the initial start() during boot
|
||||
// the service won't be registered yet.
|
||||
if (service::findManifestById("Statusbar") != nullptr) {
|
||||
if (service::getState("Statusbar") == service::State::Stopped) {
|
||||
if (service::getState("Statusbar") == SERVICE_STATE_STOPPED) {
|
||||
service::startService("Statusbar");
|
||||
} else {
|
||||
LOG_E(TAG, "Statusbar service is not in Stopped state");
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
#include <Tactility/service/ServiceInstance.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
|
||||
#include <tactility/service/service_registration.h>
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/service/service_manager.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -13,45 +13,32 @@ namespace tt::service {
|
||||
|
||||
constexpr auto* TAG = "ServiceRegistration";
|
||||
|
||||
static State toCppState(ServiceState state) {
|
||||
switch (state) {
|
||||
case SERVICE_STATE_STARTING: return State::Starting;
|
||||
case SERVICE_STATE_STARTED: return State::Started;
|
||||
case SERVICE_STATE_STOPPING: return State::Stopping;
|
||||
case SERVICE_STATE_STOPPED:
|
||||
default: return State::Stopped;
|
||||
}
|
||||
}
|
||||
|
||||
// Bridges the kernel's context-free C ServiceManifest/Service callbacks to the
|
||||
// C++ Service instances they wrap. Declared extern "C" to match the linkage of
|
||||
// the C function-pointer types they're assigned to (see e.g. gpio_controller.cpp).
|
||||
extern "C" {
|
||||
|
||||
static error_t cppOnStartTrampoline(::Service* cService, ::ServiceInstance* cContext) {
|
||||
auto& servicePtr = *static_cast<std::shared_ptr<Service>*>(cService->data);
|
||||
static error_t cppOnStartTrampoline(::ServiceInstance* cContext) {
|
||||
auto& servicePtr = *static_cast<std::shared_ptr<Service>*>(cContext->data);
|
||||
ServiceInstance context(cContext);
|
||||
return servicePtr->onStart(context) ? ERROR_NONE : ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
static void cppOnStopTrampoline(::Service* cService, ::ServiceInstance* cContext) {
|
||||
auto& servicePtr = *static_cast<std::shared_ptr<Service>*>(cService->data);
|
||||
static void cppOnStopTrampoline(::ServiceInstance* cContext) {
|
||||
auto& servicePtr = *static_cast<std::shared_ptr<Service>*>(cContext->data);
|
||||
ServiceInstance context(cContext);
|
||||
servicePtr->onStop(context);
|
||||
}
|
||||
|
||||
static ::Service* cppCreateServiceTrampoline(void* context) {
|
||||
static void cppCreateServiceTrampoline(::ServiceInstance* cContext, void* context) {
|
||||
auto& cppManifest = *static_cast<std::shared_ptr<const ServiceManifest>*>(context);
|
||||
auto* cService = new ::Service();
|
||||
cService->data = new std::shared_ptr(cppManifest->createService());
|
||||
cService->on_start = cppOnStartTrampoline;
|
||||
cService->on_stop = cppOnStopTrampoline;
|
||||
return cService;
|
||||
cContext->data = new std::shared_ptr(cppManifest->createService());
|
||||
cContext->on_start = cppOnStartTrampoline;
|
||||
cContext->on_stop = cppOnStopTrampoline;
|
||||
}
|
||||
|
||||
static void cppDestroyServiceTrampoline(::Service* cService, void* /*context*/) {
|
||||
delete static_cast<std::shared_ptr<Service>*>(cService->data);
|
||||
delete cService;
|
||||
static void cppDestroyServiceTrampoline(::ServiceInstance* cContext, void* /*context*/) {
|
||||
delete static_cast<std::shared_ptr<Service>*>(cContext->data);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@ -62,7 +49,7 @@ void addService(std::shared_ptr<const ServiceManifest> manifest, bool autoStart)
|
||||
|
||||
LOG_I(TAG, "Adding %s", id.c_str());
|
||||
|
||||
if (service_registration_find_manifest(id.c_str()) != nullptr) {
|
||||
if (service_manager_find_manifest(id.c_str()) != nullptr) {
|
||||
LOG_E(TAG, "Service id in use: %s", id.c_str());
|
||||
return;
|
||||
}
|
||||
@ -79,7 +66,7 @@ void addService(std::shared_ptr<const ServiceManifest> manifest, bool autoStart)
|
||||
.context = cppManifestPtr
|
||||
};
|
||||
|
||||
error_t error = service_registration_add(cManifest, autoStart);
|
||||
error_t error = service_manager_add(cManifest, autoStart);
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to add service %s: %s", id.c_str(), error_to_string(error));
|
||||
}
|
||||
@ -90,7 +77,7 @@ void addService(const ServiceManifest& manifest, bool autoStart) {
|
||||
}
|
||||
|
||||
std::shared_ptr<const ServiceManifest> findManifestById(const std::string& id) {
|
||||
const auto* cManifest = service_registration_find_manifest(id.c_str());
|
||||
const auto* cManifest = service_manager_find_manifest(id.c_str());
|
||||
if (cManifest == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -99,7 +86,7 @@ std::shared_ptr<const ServiceManifest> findManifestById(const std::string& id) {
|
||||
|
||||
bool startService(const std::string& id) {
|
||||
LOG_I(TAG, "Starting %s", id.c_str());
|
||||
error_t error = service_registration_start(id.c_str());
|
||||
error_t error = service_manager_start(id.c_str());
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_E(TAG, "Starting %s failed: %s", id.c_str(), error_to_string(error));
|
||||
return false;
|
||||
@ -109,7 +96,7 @@ bool startService(const std::string& id) {
|
||||
}
|
||||
|
||||
std::shared_ptr<ServiceContext> findServiceContextById(const std::string& id) {
|
||||
auto* cContext = service_registration_find_context(id.c_str());
|
||||
auto* cContext = service_manager_find_context(id.c_str());
|
||||
if (cContext == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -117,16 +104,16 @@ std::shared_ptr<ServiceContext> findServiceContextById(const std::string& id) {
|
||||
}
|
||||
|
||||
std::shared_ptr<Service> findServiceById(const std::string& id) {
|
||||
auto* cService = service_registration_find_service(id.c_str());
|
||||
if (cService == nullptr) {
|
||||
auto* cContext = service_manager_find_context(id.c_str());
|
||||
if (cContext == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return *static_cast<std::shared_ptr<Service>*>(cService->data);
|
||||
return *static_cast<std::shared_ptr<Service>*>(cContext->data);
|
||||
}
|
||||
|
||||
bool stopService(const std::string& id) {
|
||||
LOG_I(TAG, "Stopping %s", id.c_str());
|
||||
error_t error = service_registration_stop(id.c_str());
|
||||
error_t error = service_manager_stop(id.c_str());
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_W(TAG, "Service not running: %s", id.c_str());
|
||||
return false;
|
||||
@ -136,7 +123,7 @@ bool stopService(const std::string& id) {
|
||||
}
|
||||
|
||||
State getState(const std::string& id) {
|
||||
return toCppState(service_registration_get_state(id.c_str()));
|
||||
return service_manager_get_state(id.c_str());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tactility/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ServiceContext (declared in service_context.h) is a typedef alias of ServiceInstance,
|
||||
// so callbacks below are declared directly in terms of ServiceInstance to avoid a
|
||||
// conflicting forward-declaration of an unrelated "ServiceContext" struct tag.
|
||||
struct ServiceInstance;
|
||||
|
||||
/**
|
||||
* A service is a long-running background process (e.g. Wi-Fi, GPS, GUI).
|
||||
* Concrete services keep their own state behind the `data` pointer.
|
||||
*/
|
||||
struct Service {
|
||||
/** Service-specific data, owned by the service implementation. Can be NULL. */
|
||||
void* data;
|
||||
/**
|
||||
* Called when the service is starting.
|
||||
* Can be NULL, in which case starting always succeeds.
|
||||
* @param[in,out] service this service
|
||||
* @param[in,out] context the context (a ServiceInstance) for this running service
|
||||
* @return ERROR_NONE if the service started successfully
|
||||
*/
|
||||
error_t (*on_start)(struct Service* service, struct ServiceInstance* context);
|
||||
/**
|
||||
* Called when the service is stopping.
|
||||
* Can be NULL, in which case stopping is a no-op.
|
||||
* @param[in,out] service this service
|
||||
* @param[in,out] context the context (a ServiceInstance) for this running service
|
||||
*/
|
||||
void (*on_stop)(struct Service* service, struct ServiceInstance* context);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -23,8 +23,21 @@ typedef enum {
|
||||
struct ServiceInstance {
|
||||
/** The manifest that spawned this instance. */
|
||||
const struct ServiceManifest* manifest;
|
||||
/** The service created via manifest->create_service(). */
|
||||
struct Service* service;
|
||||
/** Service-specific data, owned by the service implementation. Can be NULL. */
|
||||
void* data;
|
||||
/**
|
||||
* Called when the service is starting.
|
||||
* Can be NULL, in which case starting always succeeds.
|
||||
* @param[in,out] instance this service instance (also its own ServiceContext)
|
||||
* @return ERROR_NONE if the service started successfully
|
||||
*/
|
||||
error_t (*on_start)(struct ServiceInstance* instance);
|
||||
/**
|
||||
* Called when the service is stopping.
|
||||
* Can be NULL, in which case stopping is a no-op.
|
||||
* @param[in,out] instance this service instance (also its own ServiceContext)
|
||||
*/
|
||||
void (*on_stop)(struct ServiceInstance* instance);
|
||||
/**
|
||||
* Internal state managed by the kernel.
|
||||
* ServiceInstance implementers should initialize this to NULL.
|
||||
@ -60,11 +73,11 @@ error_t service_instance_destruct(struct ServiceInstance* instance);
|
||||
const struct ServiceManifest* service_instance_get_manifest(struct ServiceInstance* instance);
|
||||
|
||||
/**
|
||||
* @brief Get the service of a service instance.
|
||||
* @brief Get the data of a service instance.
|
||||
* @param[in] instance non-null service instance pointer
|
||||
* @return the service
|
||||
* @return the data (can be NULL)
|
||||
*/
|
||||
struct Service* service_instance_get_service(struct ServiceInstance* instance);
|
||||
void* service_instance_get_data(struct ServiceInstance* instance);
|
||||
|
||||
/**
|
||||
* @brief Get the state of a service instance.
|
||||
|
||||
@ -20,7 +20,7 @@ extern "C" {
|
||||
* @retval ERROR_RESOURCE if auto_start is true and starting the service failed
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t service_registration_add(const struct ServiceManifest* manifest, bool auto_start);
|
||||
error_t service_manager_add(const struct ServiceManifest* manifest, bool auto_start);
|
||||
|
||||
/**
|
||||
* @brief Unregister a previously-added manifest.
|
||||
@ -29,7 +29,14 @@ error_t service_registration_add(const struct ServiceManifest* manifest, bool au
|
||||
* @retval ERROR_NOT_FOUND if no manifest with this id is registered
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t service_registration_remove(const char* id);
|
||||
error_t service_manager_remove(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Find a registered manifest by id.
|
||||
* @param[in] id non-null service id
|
||||
* @return the manifest, or NULL if not found
|
||||
*/
|
||||
const struct ServiceManifest* service_manager_find_manifest(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Start a registered service by id.
|
||||
@ -39,7 +46,7 @@ error_t service_registration_remove(const char* id);
|
||||
* @retval ERROR_RESOURCE if the service's on_start callback failed
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t service_registration_start(const char* id);
|
||||
error_t service_manager_start(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Stop a running service by id.
|
||||
@ -47,35 +54,21 @@ error_t service_registration_start(const char* id);
|
||||
* @retval ERROR_NOT_FOUND if no service with this id is running
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t service_registration_stop(const char* id);
|
||||
error_t service_manager_stop(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Get the state of a service by id.
|
||||
* @param[in] id non-null service id
|
||||
* @return the current state, or SERVICE_STATE_STOPPED if the id is unknown
|
||||
*/
|
||||
ServiceState service_registration_get_state(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Find a registered manifest by id.
|
||||
* @param[in] id non-null service id
|
||||
* @return the manifest, or NULL if not found
|
||||
*/
|
||||
const struct ServiceManifest* service_registration_find_manifest(const char* id);
|
||||
ServiceState service_manager_get_state(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Find the context of a running service by id.
|
||||
* @param[in] id non-null service id
|
||||
* @return the context, or NULL if the service isn't running
|
||||
*/
|
||||
ServiceContext* service_registration_find_context(const char* id);
|
||||
|
||||
/**
|
||||
* @brief Find the service instance of a running service by id.
|
||||
* @param[in] id non-null service id
|
||||
* @return the service, or NULL if not running
|
||||
*/
|
||||
struct Service* service_registration_find_service(const char* id);
|
||||
ServiceContext* service_manager_find_context(const char* id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -2,25 +2,35 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tactility/service/service.h>
|
||||
#include <tactility/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocates and initializes a new Service instance.
|
||||
* @param[in] context the manifest's context (ServiceManifest::context)
|
||||
* @return the new service, never NULL
|
||||
*/
|
||||
typedef struct Service* (*ServiceCreate)(void* context);
|
||||
// ServiceContext (declared in service_context.h) is a typedef alias of ServiceInstance,
|
||||
// so ServiceCreate/ServiceDestroy below are declared directly in terms of ServiceInstance
|
||||
// to avoid a conflicting forward-declaration of an unrelated "ServiceContext" struct tag.
|
||||
struct ServiceInstance;
|
||||
|
||||
/**
|
||||
* Frees a Service instance that was created by the matching ServiceCreate function.
|
||||
* @param[in] service the service to free
|
||||
* Initializes a newly-registered service instance in place.
|
||||
* Implementations should set instance->data, instance->on_start and instance->on_stop
|
||||
* as needed; all three may be left at their zeroed defaults (NULL) if the service has
|
||||
* no state or lifecycle callbacks.
|
||||
* @param[in,out] instance the instance to populate (manifest and internal are already set)
|
||||
* @param[in] context the manifest's context (ServiceManifest::context)
|
||||
*/
|
||||
typedef void (*ServiceDestroy)(struct Service* service, void* context);
|
||||
typedef void (*ServiceCreate)(struct ServiceInstance* instance, void* context);
|
||||
|
||||
/**
|
||||
* Tears down state that was set up by the matching ServiceCreate function
|
||||
* (e.g. frees instance->data). Should not clear instance->data/on_start/on_stop;
|
||||
* the caller does that.
|
||||
* @param[in,out] instance the instance to tear down
|
||||
* @param[in] context the manifest's context (ServiceManifest::context)
|
||||
*/
|
||||
typedef void (*ServiceDestroy)(struct ServiceInstance* instance, void* context);
|
||||
|
||||
/**
|
||||
* Describes a registrable service type.
|
||||
|
||||
@ -24,7 +24,10 @@ error_t service_instance_construct(ServiceInstance* instance, const ServiceManif
|
||||
mutex_construct(&instance->internal->mutex);
|
||||
|
||||
instance->manifest = manifest;
|
||||
instance->service = manifest->create_service(manifest->context);
|
||||
instance->data = nullptr;
|
||||
instance->on_start = nullptr;
|
||||
instance->on_stop = nullptr;
|
||||
manifest->create_service(instance, manifest->context);
|
||||
|
||||
LOG_D(TAG, "construct %s", manifest->id);
|
||||
return ERROR_NONE;
|
||||
@ -42,8 +45,10 @@ error_t service_instance_destruct(ServiceInstance* instance) {
|
||||
|
||||
LOG_D(TAG, "destruct %s", instance->manifest->id);
|
||||
|
||||
instance->manifest->destroy_service(instance->service, instance->manifest->context);
|
||||
instance->service = nullptr;
|
||||
instance->manifest->destroy_service(instance, instance->manifest->context);
|
||||
instance->data = nullptr;
|
||||
instance->on_start = nullptr;
|
||||
instance->on_stop = nullptr;
|
||||
|
||||
instance->internal = nullptr;
|
||||
mutex_destruct(&internal->mutex);
|
||||
@ -56,8 +61,8 @@ const ServiceManifest* service_instance_get_manifest(ServiceInstance* instance)
|
||||
return instance->manifest;
|
||||
}
|
||||
|
||||
Service* service_instance_get_service(ServiceInstance* instance) {
|
||||
return instance->service;
|
||||
void* service_instance_get_data(ServiceInstance* instance) {
|
||||
return instance->data;
|
||||
}
|
||||
|
||||
ServiceState service_instance_get_state(ServiceInstance* instance) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include <tactility/service/service_registration.h>
|
||||
#include <tactility/service/service_manager.h>
|
||||
#include <tactility/concurrent/mutex.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
@ -45,7 +45,7 @@ static InstanceLedger& get_instance_ledger() {
|
||||
|
||||
extern "C" {
|
||||
|
||||
error_t service_registration_add(const ServiceManifest* manifest, bool auto_start) {
|
||||
error_t service_manager_add(const ServiceManifest* manifest, bool auto_start) {
|
||||
mutex_lock(&manifest_ledger.mutex);
|
||||
if (manifest_ledger.manifests.contains(manifest->id)) {
|
||||
mutex_unlock(&manifest_ledger.mutex);
|
||||
@ -58,14 +58,14 @@ error_t service_registration_add(const ServiceManifest* manifest, bool auto_star
|
||||
LOG_I(TAG, "add %s", manifest->id);
|
||||
|
||||
if (auto_start) {
|
||||
return service_registration_start(manifest->id);
|
||||
return service_manager_start(manifest->id);
|
||||
}
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t service_registration_remove(const char* id) {
|
||||
if (service_registration_find_context(id) != nullptr) {
|
||||
error_t service_manager_remove(const char* id) {
|
||||
if (service_manager_find_context(id) != nullptr) {
|
||||
return ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ error_t service_registration_remove(const char* id) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t service_registration_start(const char* id) {
|
||||
error_t service_manager_start(const char* id) {
|
||||
mutex_lock(&manifest_ledger.mutex);
|
||||
const auto manifest_iterator = manifest_ledger.manifests.find(id);
|
||||
if (manifest_iterator == manifest_ledger.manifests.end()) {
|
||||
@ -98,7 +98,7 @@ error_t service_registration_start(const char* id) {
|
||||
return ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
auto* instance = new(std::nothrow) ServiceInstance { .manifest = nullptr, .service = nullptr, .internal = nullptr };
|
||||
auto* instance = new(std::nothrow) ServiceInstance { .manifest = nullptr, .data = nullptr, .on_start = nullptr, .on_stop = nullptr, .internal = nullptr };
|
||||
if (instance == nullptr) {
|
||||
mutex_unlock(&instance_ledger.mutex);
|
||||
return ERROR_OUT_OF_MEMORY;
|
||||
@ -118,8 +118,7 @@ error_t service_registration_start(const char* id) {
|
||||
service_instance_set_state(instance, SERVICE_STATE_STARTING);
|
||||
|
||||
LOG_I(TAG, "start %s", id);
|
||||
Service* service = instance->service;
|
||||
error = (service->on_start != nullptr) ? service->on_start(service, instance) : ERROR_NONE;
|
||||
error = (instance->on_start != nullptr) ? instance->on_start(instance) : ERROR_NONE;
|
||||
|
||||
if (error == ERROR_NONE) {
|
||||
service_instance_set_state(instance, SERVICE_STATE_STARTED);
|
||||
@ -139,7 +138,7 @@ error_t service_registration_start(const char* id) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
error_t service_registration_stop(const char* id) {
|
||||
error_t service_manager_stop(const char* id) {
|
||||
mutex_lock(&instance_ledger.mutex);
|
||||
const auto iterator = instance_ledger.instances.find(id);
|
||||
if (iterator == instance_ledger.instances.end()) {
|
||||
@ -153,9 +152,8 @@ error_t service_registration_stop(const char* id) {
|
||||
|
||||
service_instance_set_state(instance, SERVICE_STATE_STOPPING);
|
||||
|
||||
Service* service = instance->service;
|
||||
if (service->on_stop != nullptr) {
|
||||
service->on_stop(service, instance);
|
||||
if (instance->on_stop != nullptr) {
|
||||
instance->on_stop(instance);
|
||||
}
|
||||
|
||||
service_instance_set_state(instance, SERVICE_STATE_STOPPED);
|
||||
@ -170,7 +168,7 @@ error_t service_registration_stop(const char* id) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
ServiceState service_registration_get_state(const char* id) {
|
||||
ServiceState service_manager_get_state(const char* id) {
|
||||
mutex_lock(&instance_ledger.mutex);
|
||||
const auto iterator = instance_ledger.instances.find(id);
|
||||
if (iterator == instance_ledger.instances.end()) {
|
||||
@ -183,7 +181,7 @@ ServiceState service_registration_get_state(const char* id) {
|
||||
return service_instance_get_state(instance);
|
||||
}
|
||||
|
||||
const ServiceManifest* service_registration_find_manifest(const char* id) {
|
||||
const ServiceManifest* service_manager_find_manifest(const char* id) {
|
||||
mutex_lock(&manifest_ledger.mutex);
|
||||
const auto iterator = manifest_ledger.manifests.find(id);
|
||||
const ServiceManifest* manifest = (iterator != manifest_ledger.manifests.end()) ? iterator->second : nullptr;
|
||||
@ -191,7 +189,7 @@ const ServiceManifest* service_registration_find_manifest(const char* id) {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
ServiceContext* service_registration_find_context(const char* id) {
|
||||
ServiceContext* service_manager_find_context(const char* id) {
|
||||
mutex_lock(&instance_ledger.mutex);
|
||||
const auto iterator = instance_ledger.instances.find(id);
|
||||
ServiceInstance* instance = (iterator != instance_ledger.instances.end()) ? iterator->second : nullptr;
|
||||
@ -199,9 +197,4 @@ ServiceContext* service_registration_find_context(const char* id) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
Service* service_registration_find_service(const char* id) {
|
||||
ServiceInstance* instance = service_registration_find_context(id);
|
||||
return (instance != nullptr) ? instance->service : nullptr;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@ -2,7 +2,6 @@ project(TactilityTests)
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
file(GLOB_RECURSE TEST_SOURCES ${PROJECT_SOURCE_DIR}/Source/*.cpp)
|
||||
add_executable(TactilityTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "../../TactilityCore/Source/TestFile.h"
|
||||
#include "TestFile.h"
|
||||
#include "../../Tactility/Private/Tactility/app/AppManifestParsing.h"
|
||||
#include "../../Tactility/Private/Tactility/app/AppManifestParsingInternal.h"
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "../../TactilityCore/Source/TestFile.h"
|
||||
#include "TestFile.h"
|
||||
#include "../../Tactility/Include/Tactility/file/PropertiesFile.h"
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
@ -2,7 +2,6 @@ project(TactilityFreeRtosTests)
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
file(GLOB_RECURSE TEST_SOURCES ${PROJECT_SOURCE_DIR}/Source/*.cpp)
|
||||
add_executable(TactilityFreeRtosTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||
|
||||
@ -2,7 +2,6 @@ project(TactilityKernelTests)
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
file(GLOB_RECURSE TEST_SOURCES ${PROJECT_SOURCE_DIR}/Source/*.cpp)
|
||||
add_executable(TactilityKernelTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "doctest.h"
|
||||
#include <tactility/service/service_registration.h>
|
||||
#include <tactility/service/service_manager.h>
|
||||
|
||||
// Defined in service_instance.cpp. Internal-only, exposed here to test try_get/put gating.
|
||||
extern "C" void service_instance_set_state(ServiceInstance* instance, ServiceState state);
|
||||
|
||||
static int create_called = 0;
|
||||
static int destroy_called = 0;
|
||||
@ -9,22 +12,20 @@ static error_t on_start_result = ERROR_NONE;
|
||||
static void* last_create_context = nullptr;
|
||||
static void* last_destroy_context = nullptr;
|
||||
|
||||
static Service* test_create_service(void* context) {
|
||||
static void test_create_service(ServiceInstance* instance, void* context) {
|
||||
create_called++;
|
||||
last_create_context = context;
|
||||
static Service service;
|
||||
service.data = nullptr;
|
||||
service.on_start = [](Service*, ServiceContext*) -> error_t {
|
||||
instance->data = nullptr;
|
||||
instance->on_start = [](ServiceInstance*) -> error_t {
|
||||
on_start_called++;
|
||||
return on_start_result;
|
||||
};
|
||||
service.on_stop = [](Service*, ServiceContext*) {
|
||||
instance->on_stop = [](ServiceInstance*) {
|
||||
on_stop_called++;
|
||||
};
|
||||
return &service;
|
||||
}
|
||||
|
||||
static void test_destroy_service(Service*, void* context) {
|
||||
static void test_destroy_service(ServiceInstance*, void* context) {
|
||||
destroy_called++;
|
||||
last_destroy_context = context;
|
||||
}
|
||||
@ -50,12 +51,13 @@ TEST_CASE("ServiceInstance construction and destruction") {
|
||||
.context = &context_marker
|
||||
};
|
||||
|
||||
ServiceInstance instance = { .manifest = nullptr, .service = nullptr, .internal = nullptr };
|
||||
ServiceInstance instance = { .manifest = nullptr, .data = nullptr, .on_start = nullptr, .on_stop = nullptr, .internal = nullptr };
|
||||
|
||||
CHECK_EQ(service_instance_construct(&instance, &manifest), ERROR_NONE);
|
||||
CHECK_NE(instance.internal, nullptr);
|
||||
CHECK_EQ(instance.manifest, &manifest);
|
||||
CHECK_NE(instance.service, nullptr);
|
||||
CHECK_NE(instance.on_start, nullptr);
|
||||
CHECK_NE(instance.on_stop, nullptr);
|
||||
CHECK_EQ(create_called, 1);
|
||||
CHECK_EQ(last_create_context, &context_marker);
|
||||
CHECK_EQ(service_instance_get_state(&instance), SERVICE_STATE_STOPPED);
|
||||
@ -66,7 +68,7 @@ TEST_CASE("ServiceInstance construction and destruction") {
|
||||
CHECK_EQ(last_destroy_context, &context_marker);
|
||||
}
|
||||
|
||||
TEST_CASE("service_registration_add rejects duplicate ids") {
|
||||
TEST_CASE("service_manager_add rejects duplicate ids") {
|
||||
reset_counters();
|
||||
|
||||
static const ServiceManifest manifest = {
|
||||
@ -75,10 +77,10 @@ TEST_CASE("service_registration_add rejects duplicate ids") {
|
||||
.destroy_service = test_destroy_service
|
||||
};
|
||||
|
||||
CHECK_EQ(service_registration_add(&manifest, false), ERROR_NONE);
|
||||
CHECK_EQ(service_registration_add(&manifest, false), ERROR_INVALID_ARGUMENT);
|
||||
CHECK_EQ(service_manager_add(&manifest, false), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_add(&manifest, false), ERROR_INVALID_ARGUMENT);
|
||||
|
||||
CHECK_EQ(service_registration_remove("duplicate-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_remove("duplicate-test"), ERROR_NONE);
|
||||
}
|
||||
|
||||
TEST_CASE("service_registration start/stop lifecycle") {
|
||||
@ -90,33 +92,32 @@ TEST_CASE("service_registration start/stop lifecycle") {
|
||||
.destroy_service = test_destroy_service
|
||||
};
|
||||
|
||||
CHECK_EQ(service_registration_add(&manifest, false), ERROR_NONE);
|
||||
CHECK_EQ(service_registration_get_state("lifecycle-test"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_manager_add(&manifest, false), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_get_state("lifecycle-test"), SERVICE_STATE_STOPPED);
|
||||
|
||||
CHECK_EQ(service_registration_start("lifecycle-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_start("lifecycle-test"), ERROR_NONE);
|
||||
CHECK_EQ(on_start_called, 1);
|
||||
CHECK_EQ(service_registration_get_state("lifecycle-test"), SERVICE_STATE_STARTED);
|
||||
CHECK_NE(service_registration_find_context("lifecycle-test"), nullptr);
|
||||
CHECK_NE(service_registration_find_service("lifecycle-test"), nullptr);
|
||||
CHECK_EQ(service_manager_get_state("lifecycle-test"), SERVICE_STATE_STARTED);
|
||||
CHECK_NE(service_manager_find_context("lifecycle-test"), nullptr);
|
||||
|
||||
// Starting again while already started should fail
|
||||
CHECK_EQ(service_registration_start("lifecycle-test"), ERROR_INVALID_STATE);
|
||||
CHECK_EQ(service_manager_start("lifecycle-test"), ERROR_INVALID_STATE);
|
||||
|
||||
// Removing while running should fail
|
||||
CHECK_EQ(service_registration_remove("lifecycle-test"), ERROR_INVALID_STATE);
|
||||
CHECK_EQ(service_manager_remove("lifecycle-test"), ERROR_INVALID_STATE);
|
||||
|
||||
CHECK_EQ(service_registration_stop("lifecycle-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_stop("lifecycle-test"), ERROR_NONE);
|
||||
CHECK_EQ(on_stop_called, 1);
|
||||
CHECK_EQ(service_registration_get_state("lifecycle-test"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_registration_find_context("lifecycle-test"), nullptr);
|
||||
CHECK_EQ(service_manager_get_state("lifecycle-test"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_manager_find_context("lifecycle-test"), nullptr);
|
||||
|
||||
// Stopping again while already stopped should fail
|
||||
CHECK_EQ(service_registration_stop("lifecycle-test"), ERROR_NOT_FOUND);
|
||||
CHECK_EQ(service_manager_stop("lifecycle-test"), ERROR_NOT_FOUND);
|
||||
|
||||
CHECK_EQ(service_registration_remove("lifecycle-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_remove("lifecycle-test"), ERROR_NONE);
|
||||
}
|
||||
|
||||
TEST_CASE("service_registration_add with auto_start") {
|
||||
TEST_CASE("service_manager_add with auto_start") {
|
||||
reset_counters();
|
||||
|
||||
static const ServiceManifest manifest = {
|
||||
@ -125,15 +126,15 @@ TEST_CASE("service_registration_add with auto_start") {
|
||||
.destroy_service = test_destroy_service
|
||||
};
|
||||
|
||||
CHECK_EQ(service_registration_add(&manifest, true), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_add(&manifest, true), ERROR_NONE);
|
||||
CHECK_EQ(on_start_called, 1);
|
||||
CHECK_EQ(service_registration_get_state("auto-start-test"), SERVICE_STATE_STARTED);
|
||||
CHECK_EQ(service_manager_get_state("auto-start-test"), SERVICE_STATE_STARTED);
|
||||
|
||||
CHECK_EQ(service_registration_stop("auto-start-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_registration_remove("auto-start-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_stop("auto-start-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_remove("auto-start-test"), ERROR_NONE);
|
||||
}
|
||||
|
||||
TEST_CASE("service_registration_start failure leaves service stopped") {
|
||||
TEST_CASE("service_manager_start failure leaves service stopped") {
|
||||
reset_counters();
|
||||
on_start_result = ERROR_RESOURCE;
|
||||
|
||||
@ -143,20 +144,19 @@ TEST_CASE("service_registration_start failure leaves service stopped") {
|
||||
.destroy_service = test_destroy_service
|
||||
};
|
||||
|
||||
CHECK_EQ(service_registration_add(&manifest, false), ERROR_NONE);
|
||||
CHECK_EQ(service_registration_start("failing-start-test"), ERROR_RESOURCE);
|
||||
CHECK_EQ(service_registration_get_state("failing-start-test"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_registration_find_context("failing-start-test"), nullptr);
|
||||
CHECK_EQ(service_manager_add(&manifest, false), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_start("failing-start-test"), ERROR_RESOURCE);
|
||||
CHECK_EQ(service_manager_get_state("failing-start-test"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_manager_find_context("failing-start-test"), nullptr);
|
||||
|
||||
CHECK_EQ(service_registration_remove("failing-start-test"), ERROR_NONE);
|
||||
CHECK_EQ(service_manager_remove("failing-start-test"), ERROR_NONE);
|
||||
}
|
||||
|
||||
TEST_CASE("service_registration lookup functions with unknown id") {
|
||||
CHECK_EQ(service_registration_get_state("unknown-service-id"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_registration_find_manifest("unknown-service-id"), nullptr);
|
||||
CHECK_EQ(service_registration_find_context("unknown-service-id"), nullptr);
|
||||
CHECK_EQ(service_registration_find_service("unknown-service-id"), nullptr);
|
||||
CHECK_EQ(service_registration_start("unknown-service-id"), ERROR_NOT_FOUND);
|
||||
CHECK_EQ(service_registration_stop("unknown-service-id"), ERROR_NOT_FOUND);
|
||||
CHECK_EQ(service_registration_remove("unknown-service-id"), ERROR_NOT_FOUND);
|
||||
CHECK_EQ(service_manager_get_state("unknown-service-id"), SERVICE_STATE_STOPPED);
|
||||
CHECK_EQ(service_manager_find_manifest("unknown-service-id"), nullptr);
|
||||
CHECK_EQ(service_manager_find_context("unknown-service-id"), nullptr);
|
||||
CHECK_EQ(service_manager_start("unknown-service-id"), ERROR_NOT_FOUND);
|
||||
CHECK_EQ(service_manager_stop("unknown-service-id"), ERROR_NOT_FOUND);
|
||||
CHECK_EQ(service_manager_remove("unknown-service-id"), ERROR_NOT_FOUND);
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@ project(CryptModuleTests)
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
file(GLOB_RECURSE TEST_SOURCES ${PROJECT_SOURCE_DIR}/Source/*.cpp)
|
||||
add_executable(CryptModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user