/*********************************************************************** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY DEVELOPER: Zihan Chen(vczh) ***********************************************************************/ #include "VlppGlrParser.h" #include "VlppReflection.h" #include "VlppOS.h" #include "Vlpp.h" #include "VlppRegex.h" /*********************************************************************** .\WFLIBRARYPREDEFINED.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::Reflection Interfaces: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_PREDEFINED #define VCZH_WORKFLOW_LIBRARY_PREDEFINED #include namespace vl { namespace reflection { namespace description { /*********************************************************************** Coroutine ***********************************************************************/ /// Status of a coroutine. enum class CoroutineStatus { /// The coroutine is waiting for resuming. Waiting, /// The coroutine is being executed. Executing, /// The coroutine has stopped. Stopped, }; /// An object providing input information when resuming a coroutine. class CoroutineResult : public virtual IDescriptable, public Description { protected: Value result; Ptr failure; public: /// Get the object provided to the coroutine. This object is the return value for the pending async operation, like $Await. /// The object provided to the coroutine. Value GetResult(); /// Set the object provided to the coroutine. /// The object provided to the coroutine. void SetResult(const Value& value); /// Get the error provided to the coroutine. When it is not nullptr, the return value of is ignored. /// The error provided to the coroutine. Ptr GetFailure(); /// Set the error provided to the coroutine. /// The error provided to the coroutine. void SetFailure(Ptr value); }; /// A coroutine. This is typically created by a Workflow script. class ICoroutine : public virtual IDescriptable, public Description { public: /// Resume the coroutine. /// Set to true to raise an exception that the coroutine encountered. The same exception is accessible by . /// Input for the coroutine in this resuming. virtual void Resume(bool raiseException, Ptr output) = 0; /// Returns the current exception. /// The current exception. It could cause by the Workflow script that creates this coroutine, or by calling when this coroutine is in an inappropriate state. virtual Ptr GetFailure() = 0; /// Returns the status of the coroutine. /// The status of the coroutine. can be called only when this function returns . virtual CoroutineStatus GetStatus() = 0; }; /*********************************************************************** Coroutine (Enumerable) ***********************************************************************/ class EnumerableCoroutine : public Object, public Description { public: class IImpl : public virtual IValueEnumerator, public Description { public: virtual void OnYield(const Value& value) = 0; virtual void OnJoin(Ptr value) = 0; }; typedef Func(IImpl*)> Creator; static void YieldAndPause(IImpl* impl, const Value& value); static void JoinAndPause(IImpl* impl, Ptr value); static void ReturnAndExit(IImpl* impl); static Ptr Create(const Creator& creator); }; /*********************************************************************** Coroutine (Async) ***********************************************************************/ /// Status of am async operation. enum class AsyncStatus { /// The async operation is ready to execute. Ready, /// The async operation is being executed. Executing, /// The async operation has stopped. Stopped, }; /// A context providing communication between the caller and the async operation. class AsyncContext : public virtual IDescriptable, public Description { protected: SpinLock lock; bool cancelled = false; Value context; public: /// Create a context. /// Set the initial return value for (optional).. AsyncContext(const Value& _context = {}); ~AsyncContext(); /// Test if the current async operation is expected to cancel. /// Returns true if the current async operation is expected to cancel. /// /// This function is accessible by "$.IsCancelled" in an $Async coroutine. /// A cancelable async operation should check this value when it is able to stop properly, and stop when it is true. /// bool IsCancelled(); /// Set to true. /// Returns true when this operation succeeded. bool Cancel(); /// Returns a value that is accessible in Workflow script by "$.Context" in an $Async coroutine. /// A value that is accessible in Workflow script by "$.Context" in an $Async coroutine. const description::Value& GetContext(); /// Set a value that is accessible F /// A value that is accessible in Workflow script by "$.Context" in an $Async coroutine. void SetContext(const description::Value& value); }; /// An async operation. class IAsync : public virtual IDescriptable, public Description { public: /// Get the status of this async operation. /// The status of this async operation. virtual AsyncStatus GetStatus() = 0; /// Run this async operation. /// Returns true when this operation succeeded. This function cannot be called twice on the same object. /// A callback to execute when the async operation finished. /// A context object that is accessible in Workflow script by "$" in an $Async coroutine (optional). virtual bool Execute(const Func)>& callback, Ptr context = nullptr) = 0; /// Create an async operation that finished after a specified moment of time. /// Returns the created async operation. /// The time in milliseconds to wait. It counts from when this function is called, not from when this async operation is executed. static Ptr Delay(vint milliseconds); }; /// A promise object that controls a object. class IPromise : public virtual IDescriptable, public Description { public: /// Mark the object as finished by providing a value. /// Returns true when this operation succeeded. Multiple calls to and cause a failure. /// The result of the object. virtual bool SendResult(const Value& result) = 0; /// Mark the object as finished by providing an exception. /// Returns true when this operation succeeded. Multiple calls to and cause a failure. /// The exception of the object. virtual bool SendFailure(Ptr failure) = 0; }; /// An async operation in the future-promise pattern. class IFuture : public virtual IAsync, public Description { public: /// Get the that controls this future object. /// The that controls this future object. virtual Ptr GetPromise() = 0; /// Create a future object. /// The created future object. static Ptr Create(); }; /// A scheduler that controls how async operations are executed. It needs to be implemented and attached to threads that run async operations. /// See Async Coroutine for more information. class IAsyncScheduler : public virtual IDescriptable, public Description { public: /// Called when a callback needs to be executed in any thread. /// The callback to execute. /// /// You can decide which thread to execute. /// For GacUI, the scheduler that attached to the UI thread will execute this callback in the UI thread. /// virtual void Execute(const Func& callback) = 0; /// Called when a callback needs to be executed in another thread. /// The callback to execute. /// /// You can decide which thread to execute except the current one. /// For GacUI, the scheduler that attached to any thread will execute this callback in a random background thread. /// virtual void ExecuteInBackground(const Func& callback) = 0; /// Called when a callback needs to be executed in any thread after a specified moment of time. /// The callback to execute. /// The time in milliseconds to wait. /// /// You can decide which thread to execute. /// For GacUI, the scheduler that attached to the UI thread will execute this callback in the UI thread. /// virtual void DelayExecute(const Func& callback, vint milliseconds) = 0; /// Attach a scheduler for all threads. /// The scheduler to attach. static void RegisterDefaultScheduler(Ptr scheduler); /// Attach a scheduler for the current thread. /// The scheduler to attach. static void RegisterSchedulerForCurrentThread(Ptr scheduler); /// Detach the scheduler for all threads. /// The previously attached scheduler. static Ptr UnregisterDefaultScheduler(); /// Detach the scheduler for the current thread. /// The previously attached scheduler. static Ptr UnregisterSchedulerForCurrentThread(); /// Get the attached scheduler for the current thread. /// The attached scheduler. If there is no scheduler that is attached to this particular thread, the default scheduler kicks in. static Ptr GetSchedulerForCurrentThread(); }; class AsyncCoroutine : public Object, public Description { public: class IImpl : public virtual IAsync, public Description { public: virtual Ptr GetScheduler() = 0; virtual Ptr GetContext() = 0; virtual void OnContinue(Ptr output) = 0; virtual void OnReturn(const Value& value) = 0; }; typedef Func(IImpl*)> Creator; static void AwaitAndRead(IImpl* impl, Ptr value); static void ReturnAndExit(IImpl* impl, const Value& value); static Ptr QueryContext(IImpl* impl); static Ptr Create(const Creator& creator); static void CreateAndRun(const Creator& creator); }; /*********************************************************************** Coroutine (State Machine) ***********************************************************************/ class StateMachine : public Object, public AggregatableDescription { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA friend struct CustomTypeDescriptorSelector; #endif protected: bool stateMachineInitialized = false; bool stateMachineStopped = false; vint stateMachineInput = -1; Ptr stateMachineCoroutine; void ResumeStateMachine(); public: StateMachine(); ~StateMachine(); CoroutineStatus GetStateMachineStatus(); }; /*********************************************************************** Libraries ***********************************************************************/ /// system::Sys includes a lot of utility functions for type conversion, string operations and date time operations for a Workflow script. class Sys : public Description { public: static vint Int32ToInt(vint32_t value) { return (vint)value; } static vint Int64ToInt(vint64_t value) { return (vint)value; } static vint32_t IntToInt32(vint value) { return (vint32_t)value; } static vint64_t IntToInt64(vint value) { return (vint64_t)value; } static vuint UInt32ToUInt(vuint32_t value) { return (vuint)value; } static vuint UInt64ToUInt(vuint64_t value) { return (vuint)value; } static vuint32_t UIntToUInt32(vuint value) { return (vuint32_t)value; } static vuint64_t UIntToUInt64(vuint value) { return (vuint64_t)value; } static vint Len(const WString& value) { return value.Length(); } static WString Left(const WString& value, vint length) { return value.Left(length); } static WString Right(const WString& value, vint length) { return value.Right(length); } static WString Mid(const WString& value, vint start, vint length) { return value.Sub(start, length); } static vint Find(const WString& value, const WString& substr) { return INVLOC.FindFirst(value, substr, Locale::Normalization::None).key; } static WString UCase(const WString& value) { return wupper(value); } static WString LCase(const WString& value) { return wlower(value); } static WString LoremIpsumTitle(vint bestLength) { return vl::LoremIpsumTitle(bestLength); } static WString LoremIpsumSentence(vint bestLength) { return vl::LoremIpsumSentence(bestLength); } static WString LoremIpsumParagraph(vint bestLength) { return vl::LoremIpsumParagraph(bestLength); } #define DEFINE_COMPARE(TYPE) static vint Compare(TYPE a, TYPE b); REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DEFINE_COMPARE) DEFINE_COMPARE(DateTime) #undef DEFINE_COMPARE static DateTime GetLocalTime(); static DateTime GetUtcTime(); static DateTime ToLocalTime(DateTime dt); static DateTime ToUtcTime(DateTime dt); static DateTime Forward(DateTime dt, vuint64_t milliseconds); static DateTime Backward(DateTime dt, vuint64_t milliseconds); static DateTime CreateDateTime(vint year, vint month, vint day); static DateTime CreateDateTime(vint year, vint month, vint day, vint hour, vint minute, vint second, vint milliseconds); static Ptr ReverseEnumerable(Ptr value); }; /// system::Math includes math functions for a Workflow script. class Math : public Description { public: static double Pi() { return ASin(1) * 2; } static vint8_t Abs(vint8_t value) { return value > 0 ? value : -value; } static vint16_t Abs(vint16_t value) { return value > 0 ? value : -value; } static vint32_t Abs(vint32_t value) { return value > 0 ? value : -value; } static vint64_t Abs(vint64_t value) { return value > 0 ? value : -value; } static float Abs(float value) { return value > 0 ? value : -value; } static double Abs(double value) { return value > 0 ? value : -value; } #define DEFINE_MINMAX(TYPE)\ static TYPE Min(TYPE a, TYPE b);\ static TYPE Max(TYPE a, TYPE b);\ REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DEFINE_MINMAX) DEFINE_MINMAX(DateTime) #undef DEFINE_MINMAX static double Sin(double value) { return sin(value); } static double Cos(double value) { return cos(value); } static double Tan(double value) { return tan(value); } static double ASin(double value) { return asin(value); } static double ACos(double value) { return acos(value); } static double ATan(double value) { return atan(value); } static double ATan2(double x, double y) { return atan2(y, x); } static double Exp(double value) { return exp(value); } static double LogN(double value) { return log(value); } static double Log10(double value) { return log10(value); } static double Log(double value, double base) { return log(value) / log(base); } static double Pow(double value, double power) { return pow(value, power); } static double Ceil(double value) { return ceil(value); } static double Floor(double value) { return floor(value); } static double Round(double value) { return round(value); } static double Trunc(double value) { return trunc(value); } }; /// system::Math includes localization awared formatting operations for a Workflow script. /// ///

/// There are three locales that reflect the configuration of the operating system: ///

    ///
  • Invariant: An invariant locale for general languages.
  • ///
  • System: Locale for the operating system, including the file system.
  • ///
  • User: Locale for UI of the operating system.
  • ///
///

/// class Localization : public Description { public: static Locale Invariant(); static Locale System(); static Locale User(); static collections::LazyList Locales(); static collections::LazyList GetShortDateFormats(Locale locale); static collections::LazyList GetLongDateFormats(Locale locale); static collections::LazyList GetYearMonthDateFormats(Locale locale); static collections::LazyList GetLongTimeFormats(Locale locale); static collections::LazyList GetShortTimeFormats(Locale locale); static WString GetShortDayOfWeekName(Locale locale, vint dayOfWeek); static WString GetLongDayOfWeekName(Locale locale, vint dayOfWeek); static WString GetShortMonthName(Locale locale, vint month); static WString GetLongMonthName(Locale locale, vint month); static WString FormatDate(Locale locale, const WString& format, DateTime date); static WString FormatTime(Locale locale, const WString& format, DateTime date); static WString FormatNumber(Locale locale, const WString& number); static WString FormatCurrency(Locale locale, const WString& number); }; /*********************************************************************** MISC ***********************************************************************/ class Versioning : public Object, public Description { protected: vint version = 0; public: Versioning(); ~Versioning(); vint AllocateVersion(); vint GetVersion(); }; } } } namespace vl { namespace __vwsn { struct att_cpp_File { WString argument; auto operator<=>(const att_cpp_File&) const = default; }; struct att_cpp_UserImpl { auto operator<=>(const att_cpp_UserImpl&) const = default; }; struct att_cpp_Private { auto operator<=>(const att_cpp_Private&) const = default; }; struct att_cpp_Protected { auto operator<=>(const att_cpp_Protected&) const = default; }; struct att_cpp_Friend { reflection::description::ITypeDescriptor* argument = nullptr; auto operator<=>(const att_cpp_Friend&) const = default; }; struct att_rpc_Interface { auto operator<=>(const att_rpc_Interface&) const = default; }; struct att_rpc_Ctor { auto operator<=>(const att_rpc_Ctor&) const = default; }; struct att_rpc_Byval { auto operator<=>(const att_rpc_Byval&) const = default; }; struct att_rpc_Byref { auto operator<=>(const att_rpc_Byref&) const = default; }; struct att_rpc_Cached { auto operator<=>(const att_rpc_Cached&) const = default; }; struct att_rpc_Dynamic { auto operator<=>(const att_rpc_Dynamic&) const = default; }; struct att_rpc_IdString { WString argument; auto operator<=>(const att_rpc_IdString&) const = default; }; struct att_rpc_IdNumber { vint argument = 0; auto operator<=>(const att_rpc_IdNumber&) const = default; }; } } #endif /*********************************************************************** .\WFLIBRARYCPPHELPER.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::Reflection Interfaces: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_CPPLIBRARY #define VCZH_WORKFLOW_LIBRARY_CPPLIBRARY namespace vl { namespace __vwsn { template struct RunOnExit { T* function; RunOnExit(T* _function) :function(_function) { } ~RunOnExit() { function->operator()(); } }; template T* This(T* thisValue) { CHECK_ERROR(thisValue != nullptr, L"The this pointer cannot be null."); return thisValue; } template T* Ensure(T* pointer) { CHECK_ERROR(pointer != nullptr, L"The pointer cannot be null."); return pointer; } template Ptr& Ensure(Ptr& pointer) { CHECK_ERROR(pointer != nullptr, L"The pointer cannot be null."); return pointer; } template Ptr Ensure(Ptr&& pointer) { CHECK_ERROR(pointer != nullptr, L"The pointer cannot be null."); return std::move(pointer); } template Nullable Ensure(Nullable&& nullable) { CHECK_ERROR(nullable, L"The pointer cannot be null."); return std::move(nullable); } template Nullable& Ensure(Nullable& nullable) { CHECK_ERROR(nullable, L"The pointer cannot be null."); return nullable; } template WString ToString(const T& value) { WString str; CHECK_ERROR(reflection::description::TypedValueSerializerProvider>::Serialize(value, str), L"Failed to serialize."); return str; } template T Parse(const WString& str) { T value; CHECK_ERROR(reflection::description::TypedValueSerializerProvider>::Deserialize(str, value), L"Failed to serialize."); return value; } template struct NullableCastHelper { static Nullable Cast(Nullable nullable) { return Nullable(static_cast(nullable.Value())); } }; template struct NullableCastHelper { static Nullable Cast(Nullable nullable) { return Nullable(ToString(nullable.Value())); } }; template struct NullableCastHelper { static Nullable Cast(Nullable nullable) { return Nullable(Parse(nullable.Value())); } }; template Nullable NullableCast(Nullable nullable) { if (!nullable) return Nullable(); return NullableCastHelper::Cast(nullable); } template TTo* RawPtrCast(TFrom* pointer) { if (!pointer) return nullptr; if (auto converted = dynamic_cast(pointer)) return converted; return pointer->template SafeAggregationCast(); } template Ptr SharedPtrCast(TFrom* pointer) { if (!pointer) return nullptr; if (auto converted = dynamic_cast(pointer)) return Ptr(converted); return Ptr(pointer->template SafeAggregationCast()); } template reflection::description::Value Box(T&& value) { return reflection::description::BoxParameter(value); } template T Unbox(const reflection::description::Value& value) { auto unboxed = reflection::description::UnboxParameter>(value); if (std::is_reference_v) { CHECK_ERROR(!unboxed.IsOwned(), L"It is impossible to return a reference from a unboxed value, when the unboxing has to call new T(...)."); } return unboxed.Ref(); } template struct UnboxWeakHelper { }; template struct UnboxWeakHelper { static T* Unbox(const reflection::description::Value& value) { if (value.IsNull()) return nullptr; auto rawPtr = value.GetRawPtr(); if (!rawPtr) return nullptr; if (auto converted = dynamic_cast(rawPtr)) return converted; try { return rawPtr->SafeAggregationCast(); } catch (const Exception&) { return nullptr; } } }; template struct UnboxWeakHelper> { static Ptr Unbox(const reflection::description::Value& value) { if (value.IsNull()) return nullptr; auto rawPtr = value.GetRawPtr(); if (!rawPtr) return nullptr; if (auto converted = dynamic_cast(rawPtr)) return Ptr(converted); try { return Ptr(rawPtr->SafeAggregationCast()); } catch (const Exception&) { return nullptr; } } }; template struct UnboxWeakHelper> { static Nullable Unbox(const reflection::description::Value& value) { if (value.IsNull()) return Nullable(); auto boxed = value.GetBoxedValue().Cast>(); if (!boxed) return Nullable(); return Nullable(boxed->value); } }; template T UnboxWeak(const reflection::description::Value& value) { return UnboxWeakHelper>::Unbox(value); } template collections::LazyList Range(T begin, T end) { return collections::Range(begin, end - begin); } template bool InSet(const T& value, const collections::LazyList& collection) { return collection.Any([&](const T& element) {return element == value; }); } template bool InSet(const T& value, Ptr collection) { return InSet(value, reflection::description::GetLazyList(collection)); } template Ptr UnboxCollection(U&& value) { auto boxedValue = reflection::description::BoxParameter(value); return reflection::description::UnboxParameter>(boxedValue).Ref(); } template Ptr UnboxCollection(const collections::LazyList& value) { auto boxedValue = reflection::description::BoxParameter(const_cast&>(value)); return reflection::description::UnboxParameter>(boxedValue).Ref(); } struct CreateArray { using IValueArray = reflection::description::IValueArray; Ptr list; CreateArray(); CreateArray(Ptr _list); CreateArray Resize(vint size) { list->Resize(size); return{ list }; } template CreateArray Set(vint index, const T& value) { list->Set(index, Box(value)); return{ list }; } }; struct CreateList { using IValueList = reflection::description::IValueList; Ptr list; CreateList(); CreateList(Ptr _list); template CreateList Add(const T& value) { list->Add(Box(value)); return{ list }; } }; struct CreateObservableList { using IValueObservableList = reflection::description::IValueObservableList; Ptr list; CreateObservableList(); CreateObservableList(Ptr _list); template CreateObservableList Add(const T& value) { list->Add(Box(value)); return{ list }; } }; struct CreateDictionary { using IValueDictionary = reflection::description::IValueDictionary; Ptr dictionary; CreateDictionary(); CreateDictionary(Ptr _dictionary); template CreateDictionary Add(const K& key, const V& value) { dictionary->Set(Box(key), Box(value)); return{ dictionary }; } }; template struct EventHelper { }; template Ptr EventAttach(T& e, typename EventHelper::Handler handler) { return EventHelper::Attach(e, handler); } template bool EventDetach(T& e, Ptr handler) { return EventHelper::Detach(e, handler); } template decltype(auto) EventInvoke(T& e) { return EventHelper::Invoke(e); } template struct EventHelper> { using Handler = const Func&; class EventHandlerImpl : public Object, public reflection::description::IEventHandler { public: Ptr handler; EventHandlerImpl(Ptr _handler) :handler(_handler) { } bool IsAttached()override { return handler->IsAttached(); } }; static Ptr Attach(Event& e, Handler handler) { return Ptr(new EventHandlerImpl(e.Add(handler))); } static bool Detach(Event& e, Ptr handler) { auto impl = handler.Cast(); if (!impl) return false; return e.Remove(impl->handler); } static Event& Invoke(Event& e) { return e; } }; } } #endif /*********************************************************************** .\RPC\WFLIBRARYRPC.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::RPC Interfaces: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC #define VCZH_WORKFLOW_LIBRARY_RPC namespace vl { namespace rpc_controller { constexpr vint RpcTypeId_NotFound = -100; constexpr vint RpcClientId_Invalid = -1; constexpr vint RpcObjectId_Invalid = -1; struct RpcObjectReference { vint clientId = RpcClientId_Invalid; vint objectId = RpcObjectId_Invalid; vint typeId = RpcTypeId_NotFound; auto operator<=>(const RpcObjectReference&) const = default; }; struct RpcException { WString message; auto operator<=>(const RpcException&) const = default; }; using RpcEventExceptionMap = Ptr; using RpcLocalServiceMap = collections::Dictionary>; extern void MergeRpcEventExceptionMap(RpcEventExceptionMap target, RpcEventExceptionMap source); class RpcByvalReturnValue : public Object , public reflection::Description { public: reflection::description::Value value; vint slot = -1; }; inline constexpr vint RpcTypeId_IValueEnumerable = -1; inline constexpr vint RpcTypeId_IValueEnumerator = -2; inline constexpr vint RpcTypeId_IValueArray = -3; inline constexpr vint RpcTypeId_IValueList = -4; inline constexpr vint RpcTypeId_IValueObservableList = -5; inline constexpr vint RpcTypeId_IValueDictionary = -6; inline constexpr vint RpcTypeId_IValueReadonlyList = -7; inline constexpr vint RpcMethodId_IValueEnumerable_CreateEnumerator = -1; inline constexpr vint RpcMethodId_IValueEnumerator_Next = -2; inline constexpr vint RpcMethodId_IValueEnumerator_GetCurrent = -3; inline constexpr vint RpcMethodId_IValueReadonlyList_GetCount = -4; inline constexpr vint RpcMethodId_IValueReadonlyList_Get = -5; inline constexpr vint RpcMethodId_IValueList_Set = -6; inline constexpr vint RpcMethodId_IValueList_Add = -7; inline constexpr vint RpcMethodId_IValueList_Insert = -8; inline constexpr vint RpcMethodId_IValueList_RemoveAt = -9; inline constexpr vint RpcMethodId_IValueList_Clear = -10; inline constexpr vint RpcMethodId_IValueReadonlyList_Contains = -11; inline constexpr vint RpcMethodId_IValueReadonlyList_IndexOf = -12; inline constexpr vint RpcMethodId_IValueReadonlyDictionary_GetCount = -13; inline constexpr vint RpcMethodId_IValueReadonlyDictionary_Get = -14; inline constexpr vint RpcMethodId_IValueDictionary_Set = -15; inline constexpr vint RpcMethodId_IValueDictionary_Remove = -16; inline constexpr vint RpcMethodId_IValueDictionary_Clear = -17; inline constexpr vint RpcMethodId_IValueReadonlyDictionary_ContainsKey = -18; inline constexpr vint RpcMethodId_IValueReadonlyDictionary_GetKeys = -19; inline constexpr vint RpcMethodId_IValueReadonlyDictionary_GetValues = -20; inline constexpr vint RpcMethodId_IValueArray_Resize = -21; inline constexpr vint RpcEventId_IValueObservableList_ItemChanged = -1; /*********************************************************************** * Interfaces (Serialization) ***********************************************************************/ class IRpcSerializer : public virtual reflection::IDescriptable , public reflection::Description { public: virtual reflection::description::Value Serialize(const reflection::description::Value& value) = 0; virtual reflection::description::Value Deserialize(const reflection::description::Value& value) = 0; }; /*********************************************************************** * Interfaces (Operations) ***********************************************************************/ class IRpcListOps : public virtual reflection::IDescriptable , public reflection::Description { public: virtual RpcObjectReference EnumCreate(RpcObjectReference ref) = 0; virtual bool EnumNext(RpcObjectReference enumerator) = 0; virtual reflection::description::Value EnumGetCurrent(RpcObjectReference enumerator) = 0; virtual vint ListGetCount(RpcObjectReference ref) = 0; virtual reflection::description::Value ListGet(RpcObjectReference ref, vint index) = 0; virtual void ListSet(RpcObjectReference ref, vint index, const reflection::description::Value& value) = 0; virtual vint ListAdd(RpcObjectReference ref, const reflection::description::Value& value) = 0; virtual vint ListInsert(RpcObjectReference ref, vint index, const reflection::description::Value& value) = 0; virtual bool ListRemoveAt(RpcObjectReference ref, vint index) = 0; virtual void ListClear(RpcObjectReference ref) = 0; virtual bool ListContains(RpcObjectReference ref, const reflection::description::Value& value) = 0; virtual vint ListIndexOf(RpcObjectReference ref, const reflection::description::Value& value) = 0; virtual void ArrayResize(RpcObjectReference ref, vint size) = 0; virtual vint DictGetCount(RpcObjectReference ref) = 0; virtual reflection::description::Value DictGet(RpcObjectReference ref, const reflection::description::Value& key) = 0; virtual void DictSet(RpcObjectReference ref, const reflection::description::Value& key, const reflection::description::Value& value) = 0; virtual bool DictRemove(RpcObjectReference ref, const reflection::description::Value& key) = 0; virtual void DictClear(RpcObjectReference ref) = 0; virtual bool DictContainsKey(RpcObjectReference ref, const reflection::description::Value& key) = 0; virtual RpcObjectReference DictGetKeys(RpcObjectReference ref) = 0; virtual RpcObjectReference DictGetValues(RpcObjectReference ref) = 0; }; class IRpcObjectOps : public virtual reflection::IDescriptable , public reflection::Description { public: virtual reflection::description::Value InvokeMethod(RpcObjectReference ref, vint methodId, Ptr arguments) = 0; virtual void EndInvokeMethod(vint slot) = 0; virtual void ObjectHold(RpcObjectReference ref, vint remoteClientId, bool hold) = 0; }; class IRpcListEventOps : public virtual reflection::IDescriptable , public reflection::Description { public: virtual reflection::description::Value OnItemChanged(RpcObjectReference ref, vint index, vint oldCount, vint newCount) = 0; }; class IRpcObjectEventOps : public virtual reflection::IDescriptable , public reflection::Description { public: virtual reflection::description::Value InvokeEvent(RpcObjectReference ref, vint eventId, Ptr arguments) = 0; }; /*********************************************************************** * Interfaces (Lifecycle) ***********************************************************************/ class IRpcOperations : public virtual reflection::IDescriptable , public reflection::Description { public: virtual IRpcObjectOps* GetObjectOps() = 0; virtual IRpcObjectEventOps* GetObjectEventOps() = 0; }; class IRpcDispatcher : public virtual reflection::IDescriptable , public reflection::Description { public: virtual void Finalize() = 0; virtual void Initialize() = 0; virtual void DeclareLocalService(RpcObjectReference ref) = 0; virtual IRpcObjectEventOps* BroadcastFromClient_ObjectEventOps(vint selfClientId) = 0; virtual IRpcObjectOps* SendToClient_ObjectOps(vint targetClientId) = 0; }; class IRpcController : public virtual IRpcOperations , public reflection::Description { public: virtual void Finalize() = 0; virtual void SetEventSuppressedFlag(RpcObjectReference ref, vint eventId, bool suppressed) = 0; virtual bool GetEventSuppressedFlag(RpcObjectReference ref, vint eventId) = 0; virtual void SetItemChangedSuppressedFlag(RpcObjectReference ref, bool suppressed) = 0; virtual bool GetItemChangedSuppressedFlag(RpcObjectReference ref) = 0; }; /* * [Configuration] * * RunRpcTestCase_JsonRequest configures one RpcJsonDispatcher and one RpcJsonLifecycle for each client. * messageDispatcher = shared IRpcJsonMessageDispatcher * dispatcher = RpcJsonDispatcher(clientId, messageDispatcher) * lifecycle = RpcJsonLifecycle(clientId, dispatcher) * serializer = rpcops_IRpcSerializer() * getTypeId = [rpcwrapper_GetTypeId(BoxValue(obj))] * lifecycle->Register(serializer, rpcops_IRpcObjectOpsJson(lifecycle), rpcops_IRpcObjectEventOpsJson(lifecycle), getTypeId, eventAttacher) * * Triggering RpcLifecycleBase::AttachLocalObjectEvents * call rpclistener_Attach(ref.typeId, this, ref, obj, (cached)rpcops_IOps_CreateJson(this)) * * [Call graph for JSON based RPC] * * Calling Method of Remote Object: * -> IMyInterface::Method (generated Workflow code) * -> rpcops_IOps_::InvokeMethod_IMyInterface_Method (generated Workflow code) * { * -> IRpcLifecycle->GetDispatcher()->SendToClient_ObjectOps()->InvokeMethod * -> RpcJsonObjectOps::InvokeMethod * -> IRpcJsonMessageDispatcher::OnJsonRequest * ---- NETWORK PROTOCOL (request) ---- * -> RpcJsonObjectOps::Translate * -> IRpcLifecycle->GetController()->GetObjectOps()->InvokeMethod * -> RpcCalleeObjectOpsForList::InvokeMethod * -> rpcops_IRpcObjectOpsJson()->InvokeMethod (generated Workflow code) * -> IMyInterface::Method (actual) * ---- NETWORK PROTOCOL (response) ---- * } * { optional EndInvokeMethod when @rpc:Byval on return value } * * Triggering Event of Remote Object (events are automatically hooked when creating a wrapper for a remote object): * -> IMyInterface::SomethingHappened * -> rpcops_IOps_::InvokeMethod_IMyInterface_SomethingHappened (generated Workflow code) * { * -> IRpcLifecycle->GetDispatcher()->BroadcastFromClient_ObjectEventOps()->InvokeEvent * -> RpcJsonEventObjectOps::InvokeEvent * -> IRpcJsonMessageDispatcher::OnJsonRequest * ---- NETWORK PROTOCOL (broadcast) ---- * -> RpcJsonEventObjectOps::Translate * -> IRpcLifecycle->GetController()->GetObjectOps()->InvokeEvent * -> RpcCalleeObjectEventOpsForList::InvokeEvent * -> rpcops_IRpcObjectEventOpsJson()->InvokeEvent (generated Workflow code) * -> IMyInterface::SomethingHappened * ---- NETWORK PROTOCOL (response) ---- * } * * Triggering Event of Local Object (when a local object is tracked, RpcLifecycleBase::AttachLocalObjectEvents will be called) * The same to remote object. * * Registering Service: * -> IRpcLifecycle->RegisterLocalService * { * -> IRpcLifecycle->GetDispatcher()->DeclareLocalService(ref) * ---- NETWORK PROTOCOL (broadcast) ---- * -> IRpcLifecycle::DeclareRemoteService(ref) * } */ class IRpcLifecycle : public virtual reflection::IDescriptable , public reflection::Description { public: virtual void Finalize() = 0; virtual void Initialize() = 0; virtual vint GetClientId() = 0; virtual IRpcDispatcher* GetDispatcher() = 0; virtual IRpcController* GetController() = 0; virtual IRpcSerializer* GetSerializer() = 0; virtual const RpcLocalServiceMap& GetRegisteredLocalServices() = 0; virtual Ptr RefToPtr(RpcObjectReference ref) = 0; virtual RpcObjectReference PtrToRef(Ptr obj) = 0; virtual void LocalObjectHold(RpcObjectReference ref, vint remoteClientId) = 0; virtual void LocalObjectUnhold(RpcObjectReference ref, vint remoteClientId) = 0; virtual void RegisterLocalService(vint typeId, Ptr service) = 0; virtual void DeclareRemoteService(RpcObjectReference ref) = 0; virtual vint GetTypeIdFromName(WString typeName) = 0; virtual Ptr RequestService(WString typeName) = 0; }; class IRpcWrapperBase : public virtual reflection::IDescriptable , public reflection::Description { public: virtual void DisconnectFromLifecycle() = 0; }; /*********************************************************************** * Helpers ***********************************************************************/ extern RpcObjectReference RpcBoxByref(Ptr trivial, IRpcLifecycle* lc); extern Ptr RpcUnboxByref(RpcObjectReference serializable, IRpcLifecycle* lc); extern reflection::description::Value RpcCopyByval(const reflection::description::Value& trivial, IRpcLifecycle* lc); extern reflection::description::Value RpcBoxByval(Ptr trivial, IRpcLifecycle* lc); extern reflection::description::Value RpcBoxByval(const reflection::description::Value& trivial, IRpcLifecycle* lc); extern Ptr RpcUnboxByval(const reflection::description::Value& serializable, IRpcLifecycle* lc); extern void ReadMethodException(const reflection::description::Value& value); extern void ReadEventException(RpcEventExceptionMap exceptions); } } #endif /*********************************************************************** .\RPC\WFLIBRARYRPCCONTROLLER.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::RPC Interfaces: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_CONTROLLER #define VCZH_WORKFLOW_LIBRARY_RPC_CONTROLLER namespace vl { namespace rpc_controller { struct RpcEventSuppressionKey { RpcObjectReference ref; vint eventId = 0; auto operator<=>(const RpcEventSuppressionKey&) const = default; }; class RpcControllerDefault : public Object, public IRpcController { protected: Ptr objectCallback; Ptr eventCallback; collections::Dictionary eventSuppressedFlags; collections::Dictionary itemChangedSuppressedFlags; template static void SetSuppressedFlag(collections::Dictionary& flags, const TKey& key, bool suppressed); template static bool GetSuppressedFlag(const collections::Dictionary& flags, const TKey& key); public: RpcControllerDefault(); ~RpcControllerDefault(); void Register(Ptr objectCallback, Ptr eventCallback); // IRpcController IRpcObjectOps* GetObjectOps()override; IRpcObjectEventOps* GetObjectEventOps()override; void Finalize()override; void SetEventSuppressedFlag(RpcObjectReference ref, vint eventId, bool suppressed)override; bool GetEventSuppressedFlag(RpcObjectReference ref, vint eventId)override; void SetItemChangedSuppressedFlag(RpcObjectReference ref, bool suppressed)override; bool GetItemChangedSuppressedFlag(RpcObjectReference ref)override; }; } } #endif /*********************************************************************** .\RPC\WFLIBRARYRPCLIFECYCLE.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::RPC Lifecycle: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_LIFECYCLE #define VCZH_WORKFLOW_LIBRARY_RPC_LIFECYCLE namespace vl { namespace rpc_controller { class IRpcSerializer; class RpcLifecycleBase; class RpcLocalObjectTracker : public Object { friend class RpcLifecycleBase; private: RpcLifecycleBase* lifecycle = nullptr; RpcObjectReference ref; public: RpcLocalObjectTracker(RpcLifecycleBase* lc, RpcObjectReference r); ~RpcLocalObjectTracker(); void Attach(RpcLifecycleBase* lc, RpcObjectReference r); void Detach(); RpcObjectReference GetRef() const { return ref; } vint GetClientId() const { return ref.clientId; } RpcLifecycleBase* GetLifecycle() const { return lifecycle; } bool IsTracked() const { return lifecycle != nullptr; } }; class RpcWrapperTracker : public Object { friend class RpcLifecycleBase; private: RpcLifecycleBase* lifecycle = nullptr; RpcObjectReference ref; public: RpcWrapperTracker(RpcLifecycleBase* lc, RpcObjectReference r); ~RpcWrapperTracker(); void Detach(); RpcObjectReference GetRef() const { return ref; } RpcLifecycleBase* GetLifecycle() const { return lifecycle; } }; struct RpcLocalObjectProperties : public Object { RpcObjectReference ref; collections::SortedList interestedClients; reflection::IDescriptable* rawPtr = nullptr; Ptr ownedPtr; Ptr eventHandler; }; class RpcLifecycleBase : public Object, public IRpcLifecycle { friend class RpcLocalObjectTracker; friend class RpcWrapperTracker; public: using UniversalWrapperFactory = Func(RpcObjectReference, IRpcLifecycle*)>; private: struct RpcWrapperProperties { reflection::DescriptableObject* root = nullptr; IRpcWrapperBase* proxy = nullptr; }; using LocalProperties = collections::Dictionary>; using WrapperProperties = collections::Dictionary; private: RpcControllerDefault controller; vint clientId = RpcClientId_Invalid; vint nextObjectId = RpcObjectId_Invalid; bool initialized = false; LocalProperties localObjectProperties; RpcLocalServiceMap registeredLocalServices; collections::Dictionary registeredRemoteServices; static WString InternalProperty_LocalObjectTracker; static WString InternalProperty_WrapperTracker; UniversalWrapperFactory universalWrapperFactory; WrapperProperties wrapperProperties; void TrackWrapper(reflection::DescriptableObject* root, IRpcWrapperBase* proxy, RpcObjectReference ref); void UntrackWrapper(RpcObjectReference ref); bool TryGetTrackedWrapperRef(reflection::DescriptableObject* obj, RpcObjectReference& ref)const; IRpcWrapperBase* GetTrackedWrapper(RpcObjectReference ref)const; void TrackLocalObject(RpcObjectReference ref, reflection::IDescriptable* obj); RpcObjectReference CreateLocalObject(Ptr obj, RpcObjectReference ref); void UntrackLocalObject(RpcObjectReference ref, bool clearInternalProperty); void RemoveLocalObject(RpcObjectReference ref, bool clearInternalProperty); bool IsTracked(vint objectId)const; Ptr CreateCallerProxy(RpcObjectReference ref, IRpcSerializer* serializer); void DisconnectWrappersForFinalize(); protected: collections::Dictionary idMap; Ptr serializer; virtual vint DecideTypeId(reflection::IDescriptable* obj)const; virtual void AttachLocalObjectEvents(RpcObjectReference ref, reflection::IDescriptable* obj) = 0; public: RpcLifecycleBase(vint _clientId); ~RpcLifecycleBase(); void SetIdMap(const collections::Dictionary& _idMap); void RegisterWrapperFactory(UniversalWrapperFactory factory); void SetSerializer(Ptr _serializer); IRpcSerializer* GetSerializer() override; // IRpcLifecycle void Finalize()override; void Initialize()override; vint GetClientId()override; RpcControllerDefault* GetController()override; const RpcLocalServiceMap& GetRegisteredLocalServices()override; void LocalObjectHold(RpcObjectReference ref, vint remoteClientId)override; void LocalObjectUnhold(RpcObjectReference ref, vint remoteClientId)override; void RegisterLocalService(vint typeId, Ptr service)override; void DeclareRemoteService(RpcObjectReference ref)override; vint GetTypeIdFromName(WString typeName)override; Ptr RequestService(WString typeName)override; Ptr RefToPtr(RpcObjectReference ref)override; Ptr RefToPtr(RpcObjectReference ref, IRpcSerializer* serializer); RpcObjectReference PtrToRef(Ptr obj)override; }; } } #endif /*********************************************************************** .\RPC\WFLIBRARYRPCWRAPPERS.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::RPC Collection Wrappers: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_WRAPPERS #define VCZH_WORKFLOW_LIBRARY_RPC_WRAPPERS namespace vl { namespace rpc_controller { /*********************************************************************** * Collection Caller Wrappers ***********************************************************************/ class RpcByrefEnumerator : public Object, public reflection::Description, public reflection::description::IValueEnumerator, public virtual IRpcWrapperBase { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; RpcObjectReference ref; vint index = -1; public: RpcByrefEnumerator(IRpcLifecycle* lc, RpcObjectReference enumeratorRef, IRpcSerializer* _serializer); ~RpcByrefEnumerator(); void DisconnectFromLifecycle()override; reflection::description::Value GetCurrent()override; vint GetIndex()override; bool Next()override; }; class RpcByrefEnumerable : public Object, public reflection::Description, public reflection::description::IValueEnumerable, public virtual IRpcWrapperBase { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; RpcObjectReference ref; public: RpcByrefEnumerable(IRpcLifecycle* lc, RpcObjectReference enumerableRef, IRpcSerializer* _serializer); ~RpcByrefEnumerable(); void DisconnectFromLifecycle()override; Ptr CreateEnumerator()override; }; class RpcByrefReadonlyList : public Object, public reflection::Description, public virtual reflection::description::IValueReadonlyList, public virtual IRpcWrapperBase { protected: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; RpcObjectReference ref; public: RpcByrefReadonlyList(IRpcLifecycle* lc, RpcObjectReference listRef, IRpcSerializer* _serializer); ~RpcByrefReadonlyList(); void DisconnectFromLifecycle()override; Ptr CreateEnumerator()override; vint GetCount()override; reflection::description::Value Get(vint index)override; bool Contains(const reflection::description::Value& value)override; vint IndexOf(const reflection::description::Value& value)override; }; class RpcByrefList : public RpcByrefReadonlyList, public reflection::Description, public virtual reflection::description::IValueList { public: RpcByrefList(IRpcLifecycle* lc, RpcObjectReference listRef, IRpcSerializer* _serializer); ~RpcByrefList()override; Ptr CreateEnumerator()override; vint GetCount()override; reflection::description::Value Get(vint index)override; bool Contains(const reflection::description::Value& value)override; vint IndexOf(const reflection::description::Value& value)override; void Set(vint index, const reflection::description::Value& value)override; vint Add(const reflection::description::Value& value)override; vint Insert(vint index, const reflection::description::Value& value)override; bool Remove(const reflection::description::Value& value)override; bool RemoveAt(vint index)override; void Clear()override; }; class RpcByrefArray : public Object, public reflection::Description, public reflection::description::IValueArray, public virtual IRpcWrapperBase { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; RpcObjectReference ref; public: RpcByrefArray(IRpcLifecycle* lc, RpcObjectReference arrayRef, IRpcSerializer* _serializer); ~RpcByrefArray(); void DisconnectFromLifecycle()override; Ptr CreateEnumerator()override; vint GetCount()override; reflection::description::Value Get(vint index)override; bool Contains(const reflection::description::Value& value)override; vint IndexOf(const reflection::description::Value& value)override; void Set(vint index, const reflection::description::Value& value)override; void Resize(vint size)override; }; class RpcByrefObservableList : public Object, public reflection::Description, public reflection::description::IValueObservableList, public virtual IRpcWrapperBase { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; RpcObjectReference ref; public: RpcByrefObservableList(IRpcLifecycle* lc, RpcObjectReference listRef, IRpcSerializer* _serializer); ~RpcByrefObservableList(); void DisconnectFromLifecycle()override; Ptr CreateEnumerator()override; vint GetCount()override; reflection::description::Value Get(vint index)override; bool Contains(const reflection::description::Value& value)override; vint IndexOf(const reflection::description::Value& value)override; void Set(vint index, const reflection::description::Value& value)override; vint Add(const reflection::description::Value& value)override; vint Insert(vint index, const reflection::description::Value& value)override; bool Remove(const reflection::description::Value& value)override; bool RemoveAt(vint index)override; void Clear()override; }; class RpcByrefDictionary : public Object, public reflection::Description, public reflection::description::IValueDictionary, public virtual IRpcWrapperBase { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; RpcObjectReference ref; public: RpcByrefDictionary(IRpcLifecycle* lc, RpcObjectReference dictRef, IRpcSerializer* _serializer); ~RpcByrefDictionary(); void DisconnectFromLifecycle()override; Ptr GetKeys()override; Ptr GetValues()override; vint GetCount()override; reflection::description::Value Get(const reflection::description::Value& key)override; void Set(const reflection::description::Value& key, const reflection::description::Value& value)override; bool Remove(const reflection::description::Value& key)override; void Clear()override; }; /*********************************************************************** * Collection Callee Wrappers ***********************************************************************/ class RpcCalleeListOps : public Object, public IRpcListOps { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; public: RpcCalleeListOps(IRpcLifecycle* lc, IRpcSerializer* _serializer); RpcObjectReference EnumCreate(RpcObjectReference ref)override; bool EnumNext(RpcObjectReference enumerator)override; reflection::description::Value EnumGetCurrent(RpcObjectReference enumerator)override; vint ListGetCount(RpcObjectReference ref)override; reflection::description::Value ListGet(RpcObjectReference ref, vint index)override; void ListSet(RpcObjectReference ref, vint index, const reflection::description::Value& value)override; vint ListAdd(RpcObjectReference ref, const reflection::description::Value& value)override; vint ListInsert(RpcObjectReference ref, vint index, const reflection::description::Value& value)override; bool ListRemoveAt(RpcObjectReference ref, vint index)override; void ListClear(RpcObjectReference ref)override; bool ListContains(RpcObjectReference ref, const reflection::description::Value& value)override; vint ListIndexOf(RpcObjectReference ref, const reflection::description::Value& value)override; void ArrayResize(RpcObjectReference ref, vint size)override; vint DictGetCount(RpcObjectReference ref)override; reflection::description::Value DictGet(RpcObjectReference ref, const reflection::description::Value& key)override; void DictSet(RpcObjectReference ref, const reflection::description::Value& key, const reflection::description::Value& value)override; bool DictRemove(RpcObjectReference ref, const reflection::description::Value& key)override; void DictClear(RpcObjectReference ref)override; bool DictContainsKey(RpcObjectReference ref, const reflection::description::Value& key)override; RpcObjectReference DictGetKeys(RpcObjectReference ref)override; RpcObjectReference DictGetValues(RpcObjectReference ref)override; }; class RpcCalleeListEventOps : public Object, public IRpcListEventOps { private: IRpcLifecycle* lifecycle = nullptr; IRpcSerializer* serializer = nullptr; public: RpcCalleeListEventOps(IRpcLifecycle* lc, IRpcSerializer* _serializer); reflection::description::Value OnItemChanged(RpcObjectReference ref, vint index, vint oldCount, vint newCount)override; }; class RpcCalleeObjectOpsForList : public Object, public IRpcObjectOps { private: Ptr listOps; Ptr objectOps; IRpcSerializer* serializer = nullptr; public: RpcCalleeObjectOpsForList(Ptr _listOps, Ptr _objectOps, IRpcSerializer* _serializer); reflection::description::Value InvokeMethod(RpcObjectReference ref, vint methodId, Ptr arguments)override; void EndInvokeMethod(vint slot)override; void ObjectHold(RpcObjectReference ref, vint remoteClientId, bool hold)override; }; class RpcCalleeObjectEventOpsForList : public Object, public IRpcObjectEventOps { private: Ptr listEventOps; Ptr objectEventOps; IRpcSerializer* serializer = nullptr; public: RpcCalleeObjectEventOpsForList(Ptr _listEventOps, Ptr _objectEventOps, IRpcSerializer* _serializer); reflection::description::Value InvokeEvent(RpcObjectReference ref, vint eventId, Ptr arguments)override; }; class RpcCallerListOps : public Object, public IRpcListOps { private: IRpcObjectOps* objectOps = nullptr; IRpcSerializer* serializer = nullptr; public: RpcCallerListOps(IRpcObjectOps* _objectOps, IRpcSerializer* _serializer); RpcObjectReference EnumCreate(RpcObjectReference ref)override; bool EnumNext(RpcObjectReference enumerator)override; reflection::description::Value EnumGetCurrent(RpcObjectReference enumerator)override; vint ListGetCount(RpcObjectReference ref)override; reflection::description::Value ListGet(RpcObjectReference ref, vint index)override; void ListSet(RpcObjectReference ref, vint index, const reflection::description::Value& value)override; vint ListAdd(RpcObjectReference ref, const reflection::description::Value& value)override; vint ListInsert(RpcObjectReference ref, vint index, const reflection::description::Value& value)override; bool ListRemoveAt(RpcObjectReference ref, vint index)override; void ListClear(RpcObjectReference ref)override; bool ListContains(RpcObjectReference ref, const reflection::description::Value& value)override; vint ListIndexOf(RpcObjectReference ref, const reflection::description::Value& value)override; void ArrayResize(RpcObjectReference ref, vint size)override; vint DictGetCount(RpcObjectReference ref)override; reflection::description::Value DictGet(RpcObjectReference ref, const reflection::description::Value& key)override; void DictSet(RpcObjectReference ref, const reflection::description::Value& key, const reflection::description::Value& value)override; bool DictRemove(RpcObjectReference ref, const reflection::description::Value& key)override; void DictClear(RpcObjectReference ref)override; bool DictContainsKey(RpcObjectReference ref, const reflection::description::Value& key)override; RpcObjectReference DictGetKeys(RpcObjectReference ref)override; RpcObjectReference DictGetValues(RpcObjectReference ref)override; }; class RpcCallerListEventOps : public Object, public IRpcListEventOps { private: IRpcObjectEventOps* objectEventOps = nullptr; IRpcSerializer* serializer = nullptr; public: RpcCallerListEventOps(IRpcObjectEventOps* _objectEventOps, IRpcSerializer* _serializer); reflection::description::Value OnItemChanged(RpcObjectReference ref, vint index, vint oldCount, vint newCount)override; }; } } #endif /*********************************************************************** .\RPCJSON\WFLIBRARYRPCJSON.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::RPC JSON Helpers: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON #define VCZH_WORKFLOW_LIBRARY_RPC_JSON namespace vl { namespace rpc_controller { class RpcCalleeListOps; class RpcCalleeListEventOps; class RpcCalleeObjectOpsForList; class RpcCalleeObjectEventOpsForList; using RpcJsonSerializeCallback = Func(const reflection::description::Value&)>; using RpcJsonDeserializeCallback = Func)>; extern Ptr JsonSerializePredefinedTypes(const reflection::description::Value& value, const RpcJsonSerializeCallback& rpcjson_Serialize); extern reflection::description::Value JsonDeserializePredefinedTypes(const reflection::description::Value& value, const RpcJsonDeserializeCallback& rpcjson_Deserialize); class IRpcJsonMessageDispatcher : public virtual reflection::IDescriptable , public reflection::Description { public: enum class RequestType { Direct, Broadcast, BroadcastAndDrop, }; virtual vint AllocateRequestId() = 0; virtual Ptr OnJsonRequest(Ptr message, RequestType requestType) = 0; static Ptr DefaultTranslate( Ptr message, RequestType requestType, IRpcObjectOps* objectOps, IRpcObjectEventOps* objectEventOps, IRpcDispatcher* dispatcher, IRpcLifecycle* lifecycle ); }; class RpcJsonObjectOps : public Object, public IRpcObjectOps { private: vint sourceClientId = RpcClientId_Invalid; vint targetClientId = RpcClientId_Invalid; IRpcJsonMessageDispatcher* dispatcher = nullptr; public: RpcJsonObjectOps(IRpcJsonMessageDispatcher* _dispatcher); RpcJsonObjectOps(vint _sourceClientId, vint _targetClientId, IRpcJsonMessageDispatcher* _dispatcher); ~RpcJsonObjectOps(); reflection::description::Value InvokeMethod(RpcObjectReference ref, vint methodId, Ptr arguments)override; void EndInvokeMethod(vint slot)override; void ObjectHold(RpcObjectReference ref, vint remoteClientId, bool hold)override; static Ptr Translate(Ptr message, IRpcObjectOps* ops, IRpcLifecycle* lifecycle = nullptr); }; class RpcJsonObjectEventOps : public Object, public IRpcObjectEventOps { private: vint sourceClientId = RpcClientId_Invalid; IRpcJsonMessageDispatcher* dispatcher = nullptr; public: RpcJsonObjectEventOps(IRpcJsonMessageDispatcher* _dispatcher); RpcJsonObjectEventOps(vint _sourceClientId, IRpcJsonMessageDispatcher* _dispatcher); ~RpcJsonObjectEventOps(); reflection::description::Value InvokeEvent(RpcObjectReference ref, vint eventId, Ptr arguments)override; static Ptr Translate(Ptr message, IRpcObjectEventOps* ops, IRpcLifecycle* lifecycle = nullptr); }; class RpcJsonDispatcher : public Object, public IRpcDispatcher { private: vint sourceClientId = RpcClientId_Invalid; IRpcJsonMessageDispatcher* dispatcher = nullptr; Ptr objectEventOps; collections::Dictionary> objectOps; public: RpcJsonDispatcher(vint _sourceClientId, IRpcJsonMessageDispatcher* _dispatcher); void Finalize()override; void Initialize()override; void DeclareLocalService(RpcObjectReference ref)override; IRpcObjectEventOps* BroadcastFromClient_ObjectEventOps(vint selfClientId)override; IRpcObjectOps* SendToClient_ObjectOps(vint targetClientId)override; static Ptr Translate(Ptr message, IRpcDispatcher* dispatcher, IRpcLifecycle* lifecycle); }; class RpcJsonLifecycle : public RpcLifecycleBase { private: RpcJsonDispatcher* dispatcher = nullptr; Func getTypeId; Func eventAttacher; Ptr listOps; Ptr listEventOps; Ptr objectOpsForList; Ptr objectEventOpsForList; protected: vint DecideTypeId(reflection::IDescriptable* obj)const override; void AttachLocalObjectEvents(RpcObjectReference ref, reflection::IDescriptable* obj)override; public: RpcJsonLifecycle(vint _clientId, RpcJsonDispatcher* _dispatcher); void Register( Ptr _serializer, Ptr _objectOps, Ptr _objectEventOps, Func _getTypeId, Func _eventAttacher ); IRpcSerializer* GetSerializer()override; IRpcDispatcher* GetDispatcher()override; }; extern vint ReadRequestId(Ptr message); extern void WriteRequestId(Ptr message, vint requestId); } } #endif /*********************************************************************** .\WFLIBRARYREFLECTION.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Framework::Reflection Interfaces: ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_REFLECTION #define VCZH_WORKFLOW_LIBRARY_REFLECTION namespace vl { namespace reflection { namespace description { /*********************************************************************** Predefined Types ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION #define WORKFLOW_LIBRARY_ATTRIBUTE_TYPES(F)\ F(vl::__vwsn::att_cpp_File)\ F(vl::__vwsn::att_cpp_UserImpl)\ F(vl::__vwsn::att_cpp_Private)\ F(vl::__vwsn::att_cpp_Protected)\ F(vl::__vwsn::att_cpp_Friend)\ F(vl::__vwsn::att_rpc_Interface)\ F(vl::__vwsn::att_rpc_Ctor)\ F(vl::__vwsn::att_rpc_Byval)\ F(vl::__vwsn::att_rpc_Byref)\ F(vl::__vwsn::att_rpc_Cached)\ F(vl::__vwsn::att_rpc_Dynamic)\ F(vl::__vwsn::att_rpc_IdString)\ F(vl::__vwsn::att_rpc_IdNumber)\ #define WORKFLOW_LIBRARY_TYPES(F)\ F(Sys) \ F(Math) \ F(Localization) \ F(CoroutineStatus) \ F(CoroutineResult) \ F(ICoroutine) \ F(EnumerableCoroutine::IImpl) \ F(EnumerableCoroutine) \ F(AsyncStatus) \ F(AsyncContext) \ F(IAsync) \ F(IPromise) \ F(IFuture) \ F(IAsyncScheduler) \ F(AsyncCoroutine::IImpl) \ F(AsyncCoroutine) \ F(StateMachine) \ F(Versioning) \ F(vl::rpc_controller::RpcObjectReference)\ F(vl::rpc_controller::RpcException)\ F(vl::rpc_controller::RpcByvalReturnValue)\ F(vl::rpc_controller::IRpcSerializer)\ F(vl::rpc_controller::IRpcJsonMessageDispatcher::RequestType)\ F(vl::rpc_controller::IRpcJsonMessageDispatcher)\ F(vl::rpc_controller::IRpcListOps)\ F(vl::rpc_controller::IRpcListEventOps)\ F(vl::rpc_controller::IRpcObjectOps)\ F(vl::rpc_controller::IRpcObjectEventOps)\ F(vl::rpc_controller::IRpcOperations)\ F(vl::rpc_controller::IRpcDispatcher)\ F(vl::rpc_controller::IRpcController)\ F(vl::rpc_controller::IRpcLifecycle)\ F(vl::rpc_controller::IRpcWrapperBase)\ F(vl::rpc_controller::RpcByrefEnumerator)\ F(vl::rpc_controller::RpcByrefEnumerable)\ F(vl::rpc_controller::RpcByrefReadonlyList)\ F(vl::rpc_controller::RpcByrefList)\ F(vl::rpc_controller::RpcByrefArray)\ F(vl::rpc_controller::RpcByrefObservableList)\ F(vl::rpc_controller::RpcByrefDictionary)\ WORKFLOW_LIBRARY_ATTRIBUTE_TYPES(F)\ WORKFLOW_LIBRARY_TYPES(DECL_TYPE_INFO) #endif /*********************************************************************** Interface Implementation Proxy (Implement) ***********************************************************************/ #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA #pragma warning(push) #pragma warning(disable:4250) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcSerializer) vl::reflection::description::Value Serialize(const vl::reflection::description::Value& value)override { INVOKEGET_INTERFACE_PROXY(Serialize, value); } vl::reflection::description::Value Deserialize(const vl::reflection::description::Value& value)override { INVOKEGET_INTERFACE_PROXY(Deserialize, value); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcSerializer) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcJsonMessageDispatcher) vl::vint AllocateRequestId()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(AllocateRequestId); } vl::Ptr OnJsonRequest(vl::Ptr message, vl::rpc_controller::IRpcJsonMessageDispatcher::RequestType requestType)override { INVOKEGET_INTERFACE_PROXY(OnJsonRequest, message, requestType); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcJsonMessageDispatcher) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcListOps) vl::rpc_controller::RpcObjectReference EnumCreate(vl::rpc_controller::RpcObjectReference ref)override { INVOKEGET_INTERFACE_PROXY(EnumCreate, ref); } bool EnumNext(vl::rpc_controller::RpcObjectReference enumerator)override { INVOKEGET_INTERFACE_PROXY(EnumNext, enumerator); } vl::reflection::description::Value EnumGetCurrent(vl::rpc_controller::RpcObjectReference enumerator)override { INVOKEGET_INTERFACE_PROXY(EnumGetCurrent, enumerator); } vl::vint ListGetCount(vl::rpc_controller::RpcObjectReference ref)override { INVOKEGET_INTERFACE_PROXY(ListGetCount, ref); } vl::reflection::description::Value ListGet(vl::rpc_controller::RpcObjectReference ref, vl::vint index)override { INVOKEGET_INTERFACE_PROXY(ListGet, ref, index); } void ListSet(vl::rpc_controller::RpcObjectReference ref, vl::vint index, const vl::reflection::description::Value& value)override { INVOKE_INTERFACE_PROXY(ListSet, ref, index, value); } vl::vint ListAdd(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& value)override { INVOKEGET_INTERFACE_PROXY(ListAdd, ref, value); } vl::vint ListInsert(vl::rpc_controller::RpcObjectReference ref, vl::vint index, const vl::reflection::description::Value& value)override { INVOKEGET_INTERFACE_PROXY(ListInsert, ref, index, value); } bool ListRemoveAt(vl::rpc_controller::RpcObjectReference ref, vl::vint index)override { INVOKEGET_INTERFACE_PROXY(ListRemoveAt, ref, index); } void ListClear(vl::rpc_controller::RpcObjectReference ref)override { INVOKE_INTERFACE_PROXY(ListClear, ref); } bool ListContains(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& value)override { INVOKEGET_INTERFACE_PROXY(ListContains, ref, value); } vl::vint ListIndexOf(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& value)override { INVOKEGET_INTERFACE_PROXY(ListIndexOf, ref, value); } void ArrayResize(vl::rpc_controller::RpcObjectReference ref, vl::vint size)override { INVOKE_INTERFACE_PROXY(ArrayResize, ref, size); } vl::vint DictGetCount(vl::rpc_controller::RpcObjectReference ref)override { INVOKEGET_INTERFACE_PROXY(DictGetCount, ref); } vl::reflection::description::Value DictGet(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key)override { INVOKEGET_INTERFACE_PROXY(DictGet, ref, key); } void DictSet(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key, const vl::reflection::description::Value& value)override { INVOKE_INTERFACE_PROXY(DictSet, ref, key, value); } bool DictRemove(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key)override { INVOKEGET_INTERFACE_PROXY(DictRemove, ref, key); } void DictClear(vl::rpc_controller::RpcObjectReference ref)override { INVOKE_INTERFACE_PROXY(DictClear, ref); } bool DictContainsKey(vl::rpc_controller::RpcObjectReference ref, const vl::reflection::description::Value& key)override { INVOKEGET_INTERFACE_PROXY(DictContainsKey, ref, key); } vl::rpc_controller::RpcObjectReference DictGetKeys(vl::rpc_controller::RpcObjectReference ref)override { INVOKEGET_INTERFACE_PROXY(DictGetKeys, ref); } vl::rpc_controller::RpcObjectReference DictGetValues(vl::rpc_controller::RpcObjectReference ref)override { INVOKEGET_INTERFACE_PROXY(DictGetValues, ref); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcListOps) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcObjectOps) vl::reflection::description::Value InvokeMethod(vl::rpc_controller::RpcObjectReference ref, vl::vint methodId, vl::Ptr arguments)override { INVOKEGET_INTERFACE_PROXY(InvokeMethod, ref, methodId, arguments); } void EndInvokeMethod(vl::vint slot)override { INVOKE_INTERFACE_PROXY(EndInvokeMethod, slot); } void ObjectHold(vl::rpc_controller::RpcObjectReference ref, vl::vint remoteClientId, bool hold)override { INVOKE_INTERFACE_PROXY(ObjectHold, ref, remoteClientId, hold); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcObjectOps) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcListEventOps) vl::reflection::description::Value OnItemChanged(vl::rpc_controller::RpcObjectReference ref, vl::vint index, vl::vint oldCount, vl::vint newCount)override { INVOKEGET_INTERFACE_PROXY(OnItemChanged, ref, index, oldCount, newCount); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcListEventOps) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcObjectEventOps) vl::reflection::description::Value InvokeEvent(vl::rpc_controller::RpcObjectReference ref, vl::vint eventId, vl::Ptr arguments)override { INVOKEGET_INTERFACE_PROXY(InvokeEvent, ref, eventId, arguments); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcObjectEventOps) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::rpc_controller::IRpcWrapperBase) void DisconnectFromLifecycle()override { INVOKE_INTERFACE_PROXY_NOPARAMS(DisconnectFromLifecycle); } END_INTERFACE_PROXY(vl::rpc_controller::IRpcWrapperBase) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(ICoroutine) void Resume(bool raiseException, Ptr output)override { INVOKE_INTERFACE_PROXY(Resume, raiseException, output); } Ptr GetFailure()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetFailure); } CoroutineStatus GetStatus()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetStatus); } END_INTERFACE_PROXY(ICoroutine) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IAsync) AsyncStatus GetStatus()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetStatus); } bool Execute(const Func)>& callback, Ptr context)override { INVOKEGET_INTERFACE_PROXY(Execute, callback, context); } END_INTERFACE_PROXY(IAsync) #pragma warning(pop) #endif /*********************************************************************** LoadPredefinedTypes ***********************************************************************/ extern bool WfLoadLibraryTypes(); } } } #endif /*********************************************************************** .\RPCJSON\WFLIBRARYRPCJSONDISPATCHERSHARED.H ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SHARED #define VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SHARED namespace vl::rpc_controller::channeling { using JsonPackage = vl::Ptr; using JsonChannel = vl::inter_process::IChannel; using JsonChannelClient = vl::inter_process::IChannelClient; using JsonChannelServer = vl::inter_process::IChannelServer; using JsonNetworkChannelClient = vl::inter_process::NetworkProtocolChannelClient; using JsonLocalChannelClient = vl::inter_process::NetworkProtocolLocalChannelClient; template using JsonNetworkChannelServer = vl::inter_process::NetworkProtocolChannelServer; using TaskQueue = vl::TaskQueue; } #endif /*********************************************************************** .\RPCJSON\WFLIBRARYRPCJSONDISPATCHERCLIENT.H ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_CLIENT #define VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_CLIENT namespace vl::rpc_controller::channeling { /// /// A IChannelReader for hosting and connecting RPC services /// class RpcJsonDispatcherClient : public vl::Object , public virtual vl::rpc_controller::IRpcJsonMessageDispatcher , public virtual vl::inter_process::IChannelReader { protected: using RequestType = vl::rpc_controller::IRpcJsonMessageDispatcher::RequestType; private: struct ReceivedJsonMessage { vl::vint senderClientId = -1; JsonPackage message; }; JsonChannel* rpcChannel = nullptr; vl::atomic_vint nextRequestId = 0; vl::atomic_vint activeJsonRequests = 0; vl::atomic_vint initialized = 0; vl::atomic_vint serverLocalClientId = -1; vl::Ptr rpcDispatcher; vl::Ptr lifecycle; // covers messages and bufferedResponses vl::SpinLock lockMessages; vl::Semaphore semaphoreMessages; vl::collections::List messages; vl::collections::List bufferedResponses; // covers cachedIncomingServiceDeclarations and cachedOutgoingServiceDeclarations vl::SpinLock lockServiceDeclarations; vl::collections::List cachedIncomingServiceDeclarations; vl::collections::List cachedOutgoingServiceDeclarations; // covers waitingForServices vl::SpinLock lockWaitingForServices; vl::collections::List waitingForServices; vl::EventObject eventWaitingForServices; bool eventWaitingForServicesCreated = false; vl::EventObject eventServerLocalClientId; void PrepareConnection(JsonChannel* channel, const vl::collections::List& _waitingForServices); void ProcessCachedIncomingServiceDeclarations(); void SendCachedOutgoingServiceDeclarations(); void ProcessIncomingServiceDeclaration(JsonPackage request); void UpdateWaitingForServices(JsonPackage request); void WaitForServerClientId(); void WaitForExpectedServices(); void SendJsonRequest(JsonPackage message, RequestType requestType); void PushReceivedMessage(vl::vint senderClientId, JsonPackage message); ReceivedJsonMessage PopReceivedMessage(); bool TryPopBufferedResponse(vl::vint requestId, ReceivedJsonMessage& message); void PushBufferedResponse(ReceivedJsonMessage message); void SendJsonResponse(vl::vint receiverClientId, JsonPackage response); void FlushChannel(); void ProcessRequestAndSendResponse(vl::vint senderClientId, JsonPackage request); JsonPackage TranslateRequest(JsonPackage request); protected: virtual void ScheduleTask(vl::Func task) = 0; void SetRpcObjects(vl::Ptr _rpcDispatcher, vl::Ptr _lifecycle); vl::rpc_controller::RpcJsonLifecycle* GetRpcJsonLifecycle(); public: RpcJsonDispatcherClient(); void WaitForServer(JsonChannelClient* channelClient, JsonChannel* channel, const vl::collections::List& _waitingForServices); vl::vint ConnectLocalServer(JsonChannelServer* channelServer, vl::Ptr localClient, JsonChannel* channel, const vl::collections::List& _waitingForServices); void Initialize(); vl::rpc_controller::IRpcLifecycle* GetRpcLifecycle(); vl::rpc_controller::IRpcDispatcher* GetRpcDispatcher(); void SetServerLocalClientId(vl::vint clientId); void NotifyServerClientDisconnected(); vl::vint AllocateRequestId() override; JsonPackage OnJsonRequest(JsonPackage message, RequestType requestType) override; void OnRead(vl::vint senderClientId, const JsonPackage& package) override; virtual void FinalizeRpc(); }; class RpcJsonDispatcherClientForTaskQueue : public RpcJsonDispatcherClient { private: vl::Ptr taskQueue; protected: void ScheduleTask(vl::Func task) override; public: RpcJsonDispatcherClientForTaskQueue(vl::Ptr _taskQueue); }; } #endif /*********************************************************************** .\RPCJSON\WFLIBRARYRPCJSONDISPATCHERSERVER.H ***********************************************************************/ #ifndef VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SERVER #define VCZH_WORKFLOW_LIBRARY_RPC_JSON_DISPATCHER_SERVER namespace vl::rpc_controller::channeling { /// /// A IChannelReader for RPC service delivering and request broadcasting /// class RpcJsonDispatcherServer : public vl::Object , public virtual vl::inter_process::IChannelReader { public: struct PendingBroadcast : public vl::Object { vl::vint originalClientId = -1; vl::vint originalRequestId = -1; vl::vint redirectedRequestId = -1; bool hasNonNullResponse = false; vl::collections::List expectedClientIds; vl::collections::Dictionary responses; }; struct CompletedBroadcast { vl::vint originalClientId = -1; JsonPackage response; }; private: JsonChannel* rpcChannel = nullptr; JsonChannelClient* serverClient = nullptr; vl::atomic_vint nextRequestId = 0; // covers connectedClientIds, pendingBroadcasts, redirectedBroadcasts and cachedServiceDeclarations vl::SpinLock lockBroadcasts; vl::collections::SortedList connectedClientIds; vl::collections::Dictionary> pendingBroadcasts; vl::collections::Dictionary redirectedBroadcasts; vl::collections::List cachedServiceDeclarations; vl::vint AllocateRequestId(); vl::WString MakeBroadcastKey(vl::vint clientId, vl::vint requestId); JsonPackage CreateBroadcastResponse(vl::vint sourceClientId, vl::vint targetClientId, vl::vint requestId, vl::Ptr pending); CompletedBroadcast CompleteBroadcastLocked(const vl::WString& key); void DeliverCompletedBroadcast(const CompletedBroadcast& completed); JsonPackage StartBroadcast(vl::vint originalClientId, vl::vint originalRequestId, JsonPackage message); void StartBroadcastAndDrop(vl::vint originalClientId, JsonPackage message); bool TryHandleBroadcastResponse(vl::vint senderClientId, JsonPackage response); void HandleServiceDeclaration(vl::vint senderClientId, JsonPackage request); void SendLoginMessages(vl::vint clientId); void SendJsonResponse(vl::vint receiverClientId, JsonPackage response); void FlushChannel(); protected: virtual void ScheduleTask(vl::Func task) = 0; public: RpcJsonDispatcherServer(JsonChannelClient* _serverClient, JsonChannel* channel); bool HasServerClientId(); void RegisterClient(vl::vint clientId); void DisconnectClient(vl::vint clientId); vl::vint GetServerClientId(); void OnRead(vl::vint senderClientId, const JsonPackage& package) override; }; class RpcJsonDispatcherServerForTaskQueue : public RpcJsonDispatcherServer { private: vl::Ptr taskQueue; protected: void ScheduleTask(vl::Func task) override; public: RpcJsonDispatcherServerForTaskQueue(JsonChannelClient* _serverClient, JsonChannel* channel, vl::Ptr _taskQueue); }; } #endif