更新接口

This commit is contained in:
2026-08-07 23:44:35 +08:00
parent f9fcac46dc
commit a5041e10bc
22 changed files with 976 additions and 316 deletions
@@ -289,15 +289,15 @@ int main() {
const auto inherited = adminive::to_descriptor_json<Json, Inherited_Config>();
assert(inherited.at("fields").at(0).at("name") == "alpha");
assert(inherited.at("fields").at(1).at("name") == "beta");
adminive::Synchronized_Value<Inherited_Config> synchronized_inherited;
synchronized_inherited.field<0>().write([](int& value) {
adminive::Managed_Value<Inherited_Config> managed_inherited;
managed_inherited.field<0>().write([](int& value) {
value = 12;
});
synchronized_inherited.field<1>().write([](std::string& value) {
managed_inherited.field<1>().write([](std::string& value) {
value = "changed";
});
assert(synchronized_inherited.field<0>().snapshot() == 12);
assert(synchronized_inherited.field<1>().snapshot() == "changed");
assert(managed_inherited.field<0>().snapshot() == 12);
assert(managed_inherited.field<1>().snapshot() == "changed");
Control_Config controls;
const auto control_form = adminive::to_amis_form_schema<Json>(controls);
assert(control_form.at("body").at(0).at("type") == "input-color");
+190
View File
@@ -0,0 +1,190 @@
#include "adminive/adapters/nlohmann_json.hpp"
#include "adminive/http.hpp"
#include <atomic>
#include <cassert>
#include <string>
#include <thread>
namespace managed_test {
using Json = nlohmann::json;
struct Section_Config {
int editable_value{1};
int immutable_value{2};
int backend_value{3};
int unsynchronized_value{4};
};
struct Root_Config {
Section_Config section;
int immutable_value{5};
};
struct Concurrent_Config {
int first{};
int second{};
int immutable_value{7};
};
struct Probe_Lock {
static inline std::atomic<int> exclusive_locks{};
static inline std::atomic<int> shared_locks{};
void lock() noexcept {
exclusive_locks.fetch_add(1, std::memory_order_relaxed);
}
void unlock() noexcept {}
void lock_shared() noexcept {
shared_locks.fetch_add(1, std::memory_order_relaxed);
}
void unlock_shared() noexcept {}
static void reset() noexcept {
exclusive_locks.store(0, std::memory_order_relaxed);
shared_locks.store(0, std::memory_order_relaxed);
}
};
template <class Field>
concept Writable_Field = requires(Field field) {
field.write([](auto& value) {
++value;
});
};
template <class Field>
concept Reference_Escaping_Read = requires(Field field) {
field.read([](const auto& value) -> const auto& {
return value;
});
};
}
namespace adminive {
template <>
struct Type_Descriptor<managed_test::Section_Config> {
static auto get() {
using T = managed_test::Section_Config;
return object<T>("section", "Section", ADMINIVE_FIELD(T, editable_value).editable(), ADMINIVE_FIELD(T, immutable_value), ADMINIVE_FIELD(T, backend_value).read_write(), ADMINIVE_FIELD(T, unsynchronized_value).editable().unsynchronized());
}
};
template <>
struct Type_Descriptor<managed_test::Root_Config> {
static auto get() {
using T = managed_test::Root_Config;
return object<T>("root", "Root", ADMINIVE_FIELD(T, section), ADMINIVE_FIELD(T, immutable_value));
}
};
template <>
struct Type_Descriptor<managed_test::Concurrent_Config> {
static auto get() {
using T = managed_test::Concurrent_Config;
return object<T>("concurrent", "Concurrent", ADMINIVE_FIELD(T, first).editable(), ADMINIVE_FIELD(T, second).editable(), ADMINIVE_FIELD(T, immutable_value));
}
};
}
int main() {
using namespace managed_test;
using Guarded = adminive::Managed_Value<Section_Config, adminive::Mutex_Policy<Probe_Lock>>;
Guarded guarded;
auto immutable = guarded.member<&Section_Config::immutable_value>();
auto editable = guarded.member<&Section_Config::editable_value>();
auto backend = guarded.member<&Section_Config::backend_value>();
auto unsynchronized = guarded.member<&Section_Config::unsynchronized_value>();
static_assert(!Writable_Field<decltype(immutable)>);
static_assert(Writable_Field<decltype(editable)>);
static_assert(Writable_Field<decltype(backend)>);
static_assert(Writable_Field<decltype(unsynchronized)>);
static_assert(!Reference_Escaping_Read<decltype(immutable)>);
const auto resolved = guarded.resolved_synchronization();
assert(resolved.lock_count == 2);
assert(resolved.slot(0) != structive::Resolved_Synchronization_View::unsynchronized_slot);
assert(resolved.slot(1) == structive::Resolved_Synchronization_View::unsynchronized_slot);
assert(resolved.slot(2) != structive::Resolved_Synchronization_View::unsynchronized_slot);
assert(resolved.slot(0) != resolved.slot(2));
assert(resolved.slot(3) == structive::Resolved_Synchronization_View::unsynchronized_slot);
Probe_Lock::reset();
assert(immutable.snapshot() == 2);
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
Probe_Lock::reset();
editable.write([](int& value) {
value = 11;
});
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
Probe_Lock::reset();
backend.write([](int& value) {
value = 12;
});
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
Probe_Lock::reset();
unsynchronized.write([](int& value) {
value = 13;
});
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
const auto descriptor = adminive::to_descriptor_json<Json, Section_Config>();
assert(descriptor.at("protocol_version") == 4);
assert(!descriptor.at("fields").at(0).contains("lock_mode"));
assert(descriptor.at("fields").at(0).at("writable") == true);
assert(descriptor.at("fields").at(0).at("synchronized") == true);
assert(descriptor.at("fields").at(1).at("writable") == false);
assert(descriptor.at("fields").at(1).at("synchronized") == false);
assert(descriptor.at("fields").at(2).at("writable") == true);
assert(descriptor.at("fields").at(2).at("editable") == false);
assert(descriptor.at("fields").at(2).at("synchronized") == true);
assert(descriptor.at("fields").at(3).at("writable") == true);
assert(descriptor.at("fields").at(3).at("synchronized") == false);
adminive::Managed_Value<Root_Config, adminive::Mutex_Policy<Probe_Lock>> nested;
auto section = nested.member<&Root_Config::section>();
static_assert(!Writable_Field<decltype(section)>);
Probe_Lock::reset();
assert(section.member<&Section_Config::immutable_value>().snapshot() == 2);
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
Probe_Lock::reset();
section.member<&Section_Config::editable_value>().write([](int& value) {
value = 31;
});
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
Probe_Lock::reset();
section.member<&Section_Config::unsynchronized_value>().write([](int& value) {
value = 32;
});
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
adminive::Managed_Value<Section_Config, structive::No_Lock_Policy> no_lock;
adminive::Resource_Service<Section_Config, Json> service(no_lock, "/section");
const auto rejected = service.update_response(R"({"backend_value":99,"immutable_value":88})");
assert(rejected.status == 422);
const auto update = service.update_response(R"({"editable_value":21,"unsynchronized_value":22})");
assert(update.status == 200);
const auto no_lock_snapshot = no_lock.snapshot();
assert(no_lock_snapshot.editable_value == 21);
assert(no_lock_snapshot.backend_value == 3);
assert(no_lock_snapshot.immutable_value == 2);
assert(no_lock_snapshot.unsynchronized_value == 22);
adminive::Managed_Value<Concurrent_Config> concurrent;
std::atomic<bool> start{};
auto first_writer = std::thread([&] {
while(!start.load(std::memory_order_acquire)) {}
for(int index = 0; index < 5000; ++index) {
concurrent.member<&Concurrent_Config::first>().write([index](int& value) {
value = index;
});
}
});
auto second_writer = std::thread([&] {
while(!start.load(std::memory_order_acquire)) {}
for(int index = 0; index < 5000; ++index) {
concurrent.member<&Concurrent_Config::second>().write([index](int& value) {
value = index;
});
}
});
auto serializer = std::thread([&] {
while(!start.load(std::memory_order_acquire)) {}
for(int index = 0; index < 1000; ++index) {
const Json value = adminive::to_json<Json>(concurrent);
assert(value.at("immutable_value") == 7);
}
});
start.store(true, std::memory_order_release);
first_writer.join();
second_writer.join();
serializer.join();
const auto concurrent_snapshot = concurrent.snapshot();
assert(concurrent_snapshot.first == 4999);
assert(concurrent_snapshot.second == 4999);
assert(concurrent_snapshot.immutable_value == 7);
return 0;
}