8#ifndef SEN_CORE_OBJ_NATIVE_OBJECT_H
9#define SEN_CORE_OBJ_NATIVE_OBJECT_H
41#include <shared_mutex>
45#include <unordered_map>
106 [[nodiscard]] ObjectId
getId() const noexcept final;
107 [[nodiscard]] const
std::
string&
getName() const noexcept final;
128 return senImplComputeMaxReliableSerializedPropertySizeImpl();
132 impl::BufferProvider uni,
133 impl::BufferProvider multi) = 0;
141 [[nodiscard]]
virtual uint32_t senImplComputeMaxReliableSerializedPropertySizeImpl()
const = 0;
149 template <typename R, typename... Args, typename F, class C>
153 template <typename R, typename... Args, typename F, class C>
161 template <typename R, typename... Args, typename F, class C>
165 template <typename R>
171 template <typename... T>
176 bool addToTransportQueue,
188 void setLocalPrefix(
std::string_view localPrefix) noexcept;
192 void setQueues(impl::WorkQueue* workQueue, impl::SerializableEventQueue* eventQueue) noexcept;
196 void setRegistrationTime(
TimeStamp time) noexcept { registrationTime_ =
time; }
199 [[nodiscard]]
TimeStamp getRegistrationTime() const noexcept {
return registrationTime_; }
202 template <
typename... T>
203 friend class impl::EventBuffer;
205 struct EventCallbackData
208 std::shared_ptr<EventCallback<VarList>> callback;
211 using EventCallbackList = std::vector<EventCallbackData>;
213 struct EventCallbackInfo
215 EventCallbackList list;
219 using EventCallbackMap = std::unordered_map<MemberHash, EventCallbackInfo>;
224 return std::lock_guard(dataAccessMutex_);
229 return std::shared_lock(dataAccessMutex_);
233 friend class impl::NativeObjectProxy;
234 friend class impl::FilteredProvider;
235 friend class kernel::impl::RemoteParticipant;
236 friend class kernel::impl::LocalParticipant;
237 friend class kernel::impl::Runner;
238 friend class kernel::impl::ObjectUpdate;
239 friend class kernel::PipelineComponent;
240 friend impl::WorkQueue* impl::getWorkQueue(
NativeObject*
object)
noexcept;
243 mutable std::atomic<impl::WorkQueue*> workQueue_;
244 mutable std::atomic<impl::SerializableEventQueue*> outputEventQueue_;
245 mutable impl::WorkQueue postCommitEvents_;
247 mutable std::shared_mutex dataAccessMutex_;
250 std::string localName_;
251 std::atomic_uint32_t nextConnection_ = 1U;
252 std::unique_ptr<EventCallbackMap> eventCallbacks_;
253 std::recursive_mutex eventCallbacksMutex_;
265inline WorkQueue* getWorkQueue(
NativeObject*
object)
noexcept {
return object->workQueue_.load(); }
271template <
typename R,
typename... Args,
typename F,
class C>
272[[nodiscard]]
inline MethodResult<R> executeCallWithArgs(C instance, F&& f,
const Args&... args)
noexcept
276 if constexpr (std::is_void_v<R>)
278 (*instance.*f)(args...);
283 return ::sen::Ok((*instance.*f)(args...));
288 return ::sen::Err(std::current_exception());
292template <
typename R,
typename... Args,
typename F,
class C>
293[[nodiscard]]
inline std::exception_ptr executeDeferredCallWithArgs(C instance,
295 std::promise<R> promise,
296 const Args&... args)
noexcept
300 (*instance.*f)(args..., std::move(promise));
305 return std::current_exception();
311template <
typename R,
typename... Args,
typename F,
class C>
320 func = std::forward<F>(f),
321 responseCallback = std::move(callback),
322 us = weak_from_this()]()
mutable
327 if (
auto callbackLock = responseCallback.lock(); callbackLock.isValid())
329 auto err =
MethodResult<R> {
Err(std::make_exception_ptr(std::runtime_error(
"object no longer exists")))};
330 auto work = [rcb = std::move(responseCallback), err = std::move(err)]()
mutable { rcb.invoke({}, err); };
331 callbackLock.pushAnswer(std::move(work), forcePush);
336 auto result = impl::executeCallWithArgs<R, Args...>(instance, std::move(func), args...);
337 if (
auto callbackLock = responseCallback.lock(); callbackLock.isValid())
339 auto work = [ret = std::move(result), rcb = std::move(responseCallback)]()
mutable { rcb.invoke({}, ret); };
340 callbackLock.pushAnswer(std::move(work), forcePush);
354template <
typename R,
typename... Args,
typename F,
class C>
365 func = std::forward<F>(f),
366 responseCallback = std::move(callback),
367 us = weak_from_this()]()
mutable
371 if (
auto callbackLock = responseCallback.lock(); callbackLock.isValid())
373 auto err =
MethodResult<R> {
Err(std::make_exception_ptr(std::runtime_error(
"object no longer exists")))};
374 auto work = [rcb = std::move(responseCallback), err = std::move(err)]()
mutable { rcb.invoke({}, err); };
375 callbackLock.pushAnswer(std::move(work), forcePush);
380 auto result = impl::executeCallWithArgs<R, Args...>(instance, std::move(func), args...);
381 if (
auto callbackLock = responseCallback.lock(); callbackLock.isValid())
383 auto work = [ret = std::move(result), rcb = std::move(responseCallback)]()
mutable { rcb.invoke({}, ret); };
384 callbackLock.pushAnswer(std::move(work), forcePush);
391template <
typename R,
typename... Args,
typename F,
class C>
402 func = std::forward<F>(f),
403 responseCallback = std::move(callback),
404 us = weak_from_this()]()
mutable
408 if (
auto callbackLock = responseCallback.lock(); callbackLock.isValid())
410 auto err =
MethodResult<R> {
Err(std::make_exception_ptr(std::runtime_error(
"object no longer exists")))};
411 auto work = [err = std::move(err), rcb = std::move(responseCallback)]()
mutable { rcb.invoke({}, err); };
412 callbackLock.pushAnswer(std::move(work), forcePush);
417 std::promise<R> promise;
418 auto future = std::make_shared<std::future<R>>(promise.get_future());
419 auto exceptionPtr = impl::executeDeferredCallWithArgs(instance, func, std::move(promise), args...);
421 if (
auto callbackLock = responseCallback.lock(); callbackLock.isValid())
426 auto work = [err = std::move(err), rcb = std::move(responseCallback)]()
mutable { rcb.invoke({}, err); };
427 callbackLock.pushAnswer(std::move(work), forcePush);
431 callbackLock.pushAnswer([fut = std::move(future), cb = std::move(responseCallback), forcePush]()
mutable
444 if (!future->valid())
447 if (
auto callbackLock = callback.lock(); callbackLock.isValid())
449 callbackLock.pushAnswer([fut = std::move(future), cb = std::move(callback), forcePush]()
mutable
457 auto status = future->wait_for(std::chrono::microseconds(0));
464 case std::future_status::deferred:
466 if constexpr (std::is_same_v<R, void>)
469 callback.invoke({},
Ok());
473 callback.invoke({},
Ok(future->get()));
477 case std::future_status::ready:
479 if constexpr (std::is_same_v<R, void>)
482 callback.invoke({},
Ok());
486 auto value = future->get();
487 callback.invoke({},
Ok(value));
491 case std::future_status::timeout:
494 if (
auto callbackLock = callback.lock(); callbackLock.isValid())
496 callbackLock.pushAnswer([fut = std::move(future), cb = std::move(callback), forcePush]()
mutable
508 callback.invoke({},
Err(std::current_exception()));
513template <
typename... T>
518 bool addToTransportQueue,
521 eventBuffer.produce(emissionMode,
527 outputEventQueue_.load(),
Here we define a set of template meta-programming helpers to let the compiler take some decisions bas...
Represents an event.
Definition core/include/sen/core/meta/event.h:34
Represents a method.
Definition method.h:96
An object instantiated in this process. This is the base class for all user-implemented objects.
Definition native_object.h:63
ConnectionGuard onEventUntyped(const Event *ev, EventCallback< VarList > &&callback) final
Reflection-based interface for reacting to events.
virtual void preCommit()
Implement this function if you need to perform some action before the commit is called in the compone...
Definition native_object.h:97
void senImplAsyncDeferredCall(C *instance, MethodCallback< R > &&callback, F &&f, bool forcePush, Args... args)
Queues a call to a method for future execution with deferred semantics (non-const version).
Definition native_object.h:392
ObjectId getId() const noexcept final
Global unique object identification.
ConnId senImplMakeConnectionId() noexcept
virtual void preDrain()
Implement this function if you need to perform some action before the draining inputs the component w...
Definition native_object.h:91
virtual void update(kernel::RunApi &runApi)
Implement this function to perform changes to your object state or interactions with other objects....
virtual void senImplStreamCall(MemberHash methodId, InputStream &in, StreamCallForwarder &&fwd)=0
NativeObject(const std::string &name)
std::shared_lock< std::shared_mutex > createReaderLock() const
Definition native_object.h:227
void invokeUntyped(const Method *method, const VarList &args, MethodCallback< Var > &&onDone) final
Reflection- and variant- based interface for (asynchronously) invoking a method on this object....
Definition native_object.h:347
virtual void senImplWriteChangedPropertiesToStream(OutputStream &confirmed, impl::BufferProvider uni, impl::BufferProvider multi)=0
uint32_t senImplComputeMaxReliableSerializedPropertySize() const
Definition native_object.h:125
NativeObject * asNativeObject() noexcept final
Helper that checks if the object is local (without dynamic casts).
virtual Var senImplGetPropertyImpl(MemberHash propertyId) const =0
ConnectionGuard onPropertyChangedUntyped(const Property *prop, EventCallback< VarList > &&callback) final
Reflection-based interface for detecting property changes.
virtual impl::FieldValueGetter senImplGetFieldValueGetter(MemberHash propertyId, Span< uint16_t > fields) const =0
void addWorkToQueue(sen::std_util::move_only_function< void()> &&call, bool forcePush) const
Queues a function (no specific task) into the work queue.
Var getNextPropertyUntyped(const Property *property) const
Untyped version of the getNext family of methods that get generated by subclasses.
std::lock_guard< std::shared_mutex > createWriterLock() const
Definition native_object.h:222
const std::string & getName() const noexcept final
The name given to the object upon construction.
virtual void senImplSetNextPropertyUntyped(MemberHash propertyId, const Var &value)=0
const std::string & getLocalName() const noexcept final
An alias used as an alternate way of identifying this object locally.
virtual void senImplCommitImpl(TimeStamp time)=0
virtual void unregistered(kernel::RegistrationApi &api)
Implement this function to react to the fact that the object has been unregistered from the execution...
impl::SerializableEventQueue * getOutputEventQueue() noexcept
Var getPropertyUntyped(const Property *prop) const final
Variant-based property getter.
void senImplProduceEvent(impl::EventBuffer< T... > &eventBuffer, Emit emissionMode, MemberHash eventId, TransportMode transportMode, bool addToTransportQueue, MaybeRef< T >... args)
Helper to call eventBuffer.produce() with our data.
Definition native_object.h:514
void senImplAsyncCall(C *instance, MethodCallback< R > &&callback, F &&f, bool forcePush, Args... args)
Queues a call to a method for future execution (non-const version).
Definition native_object.h:312
friend class impl::EventBuffer
Definition native_object.h:203
void setNextPropertyUntyped(const Property *property, const Var &value)
Untyped version of the setNext family of methods that get generated by subclasses.
virtual Var senImplGetNextPropertyUntyped(MemberHash propertyId) const =0
static void tryToGetResult(std::shared_ptr< std::future< R > > future, MethodCallback< R > &&callback, bool forcePush)
Tries to get a result from the future, queuing back the check until timed out.
Definition native_object.h:442
virtual void senImplVariantCall(MemberHash methodId, const VarList &args, VariantCallForwarder &&fwd)=0
void senImplRemoveUntypedConnection(ConnId id, MemberHash memberHash) override
virtual void registered(kernel::RegistrationApi &api)
Implement this function to react to the fact that the object has been created and registered into the...
virtual bool needsPreDrainOrPreCommit() const noexcept
True if preUpdate and postUpdate needs to be called for this object. Defaults to false.
Definition native_object.h:85
void senImplEventEmitted(MemberHash id, std::function< VarList()> &&argsGetter, const EventInfo &info) final
Called by EventBuffer when emitting an event.
void commit(TimeStamp time)
TimeStamp getLastCommitTime() const noexcept override
The point in time when the last commit was called.
friend class ConnectionGuard
Definition object.h:141
Represents a property.
Definition property.h:79
Contiguous view of elements of type T. Inspired by http://www.open-std.org/jtc1/sc22/wg21/docs/papers...
Definition span.h:34
A point in time.
Definition timestamp.h:26
API for objects when registered.
Definition component_api.h:170
What can be done while a component is running.
Definition component_api.h:224
impl::Err< void > Err() noexcept
If E is void, use the void specialization of Err.
Definition result.h:439
impl::Ok< void > Ok() noexcept
If T is void, use the void specialization of Ok.
Definition result.h:434
InputStreamTemplate< LittleEndian > InputStream
Definition input_stream.h:84
sen::std_util::move_only_function< void(OutputStream &)> StreamCall
Definition native_object.h:55
Emit
How to emit an event.
Definition object.h:51
Result< R, std::exception_ptr > MethodResult
The result of a method (which can be an exception in case of error).
Definition callback.h:204
Callback< MethodCallInfo, MethodResult< R > > MethodCallback
A method callback.
Definition callback.h:212
sen::std_util::move_only_function< void(Var &)> VariantCall
Definition native_object.h:56
sen::std_util::move_only_function< void(StreamCall &&)> StreamCallForwarder
Definition native_object.h:57
sen::std_util::move_only_function< void(VariantCall &&)> VariantCallForwarder
Definition native_object.h:58
Callback< EventInfo, Args... > EventCallback
An event callback.
Definition callback.h:208
Information about an event emission.
Definition callback.h:50
std::conditional_t< std::is_arithmetic_v< T >||shouldBePassedByValueV< T >, T, AddConstRef< T > > MaybeRef
returns 'const T&' or 'T' depending on the type
Definition class_helpers.h:46
std::vector< Var > VarList
A list of vars to represent sequences.
Definition var.h:104
@ time
Definition unit.h:34
TransportMode
How to transport information.
Definition type.h:56
detail::MoveOnlyFunctionImpl< FwdArgs... > move_only_function
Definition move_only_function.h:256
OutputStreamTemplate< LittleEndian > OutputStream
Definition output_stream.h:64
The hash of a member.
Definition type.h:39
Can hold any supported value type. Wraps std::variant to allow recursion and implements some helpers.
Definition var.h:119