theKernel 10.0
Loading...
Searching...
No Matches
MkCall_rb.c
Go to the documentation of this file.
1
9/* LABEL-NO */
10
11/* LABEL-START */
12#define META_FILE_NAME "MkCall_rb.c"
13
15#include "misc_check_rb.h"
16
17/* LABEL-END */
18
19mk_inline VALUE NS(sRescue) (
21 MK_MNG const mng,
22 VALUE(*proc)(ANYARGS),
23 VALUE data
24) {
25 int state;
26 VALUE ret = rb_protect(proc, data, &state);
27 if (state) {
28 OT_ERROR_LNG_2_META_2(mng,"ProcessEvent");
29 }
30 return ret;
31}
32
33// ==========================================================================
34
35// method callback with ARRAY of args
36static VALUE NS(sCallMethod) (VALUE array) {
37 const VALUE *valP = rb_array_const_ptr(array);
38 return rb_method_call((int)RARRAY_LEN(array)-1, &valP[1], valP[0]);
39}
40
41// proc callback with ARRAY of args
42static VALUE NS(sCallProc) (VALUE array) {
43 const VALUE *valP = rb_array_const_ptr(array);
44 return rb_proc_call_with_block(valP[0], (int)RARRAY_LEN(array)-1, &valP[1], Qnil);
45}
46
49 MK_PTR *retP
50) {
51 if ((*skipP) >= objc) {
52 WrongNumArgs(hdl, (*skipP), objc, -999, +999, arg);
53 goto error;
54 }
55
56 VALUE val = objv[(*skipP)++];
57
58 struct MkCallS *call = *retP;
59 if (*retP == NULL) {
60 call = (struct MkCallS *) MkSysCalloc(MK_ERROR_PANIC,1,sizeof(struct MkCallS));
61 call->isAlloc = true;
62 }
63
64 call->hdl = hdl;
65 call->mkrt = MK_RT_PTR;
66 call->procArgs = rb_ary_new();
67 INCR_REF(&call->procArgs);
68
69 if (rb_obj_is_kind_of(val, rb_cMethod) == Qtrue) {
70 // val belongs to calling object, but is NOT callable from other
72 call->procCallback = val;
73 INCR_REF(&call->procCallback);
74 } else if (rb_obj_is_kind_of(val, rb_cProc) == Qtrue) {
75 // val belongs to global proc and is callable from other
76 call->procType = MkCallS_proc;
77 call->procCallback = val;
78 INCR_REF(&call->procCallback);
79 } else if (NIL_P(val)) {
80 call->procCallback = Qnil;
81 } else if (rb_obj_is_kind_of(val, rb_cUnboundMethod) == Qtrue) {
82 // val belongs to calling object, but is NOT callable from other
84 call->procCallback = val;
85 INCR_REF(&call->procCallback);
86 } else if (rb_obj_is_kind_of(val, rb_cString) == Qtrue) {
87 const MkStringR tmp = VAL2MkStringR(val);
88 if (MkStringIsNULL(tmp)) {
89 call->procCallback = Qnil;
90 } else {
92 goto error;
93 }
94 } else {
95 WrongCallableError(OT_OBJ_TYPE_STRING(val));
96 goto error;
97 }
98
99 if (call->procCallback == Qnil) {
100 DECR_REF(&call->procArgs);
101 call->procArgs = Qnil;
102 if ( call->isAlloc ) MkSysFree(call);
103 *retP = NULL;
104 } else {
105 call->procArity = VAL2I32(rb_funcallv(call->procCallback,NS(id_arity),0,NULL));
106 *retP = call;
107 }
108 return MK_OK;
109error:
110 return OT_ERROR_STACK;
111}
112
113// cleanup call->procCallback from above
114void NS(CallFree) (MK_PTR* callP) {
115 // BUG FIX → ruby crash on object allocation during GC at "Nhi1Exec Bug3.rb".
116 // The crash accourse because of GC is active after a raise of an error at constructor AND
117 // the service-callback is deleted in "DECR_REG" which create a NEW object in "rb_ary_delete" !!
118 // if (callP == NULL || *callP == NULL || rb_during_gc() ) return;
119 if (callP == NULL || *callP == NULL ) return;
120 struct MkCallS *call = (struct MkCallS*) *callP;
121 if (!OT_LNG_NULL_IS(call->procCallback)) {
122 DECR_REF(&call->procCallback);
123 call->procCallback = Qnil;
124 }
125 if (!OT_LNG_NULL_IS(call->procArgs)) {
126 DECR_REF(&call->procArgs);
127 call->procArgs = Qnil;
128 }
129//printV("call=%p, data=%p\n", call, call->procCallback)
130 if (call->isAlloc) MkSysFree(*callP);
131 else *callP = NULL;
132}
133
134void MK(CallFreeOnce) ( MK_CBP *callP )
135{
136 MK(CallFree) (callP);
137}
138
139
140// *********************************************************************
141
142/*
143[ObjectDeleteCall signature]
144 callback-args := typeName:MK_STRN[in], typeHdl:MK_HDL[in], objHdl:MK_HDL[in]
145 [static] def callback ( callback-args )
146 [instance] class YYY
147 def callback ( callback-args )
148 [class] class ZZZ
149 def self.callback ( callback-args )
150[ObjectDeleteCall signature]
151*/
152
153enum MkErrorE
154NS(ObjectDeleteCall) ( MkObjectDeleteCallF_ARGS )
155{
157
158 // if NO self object is available than NO callback is called
159 if (!MkSelfExists(obj)) return MK_OK;
160
161 struct MkCallS *call = __data__;
162 int argNum = 3;
163
164 rb_set_errinfo(Qnil);
165
166 // 1. check environment
167 if (OT_LNG_NULL_IS(call->procCallback)) return MK_OK;
168
169 // 2. if not already done initialize
170 if (call->procCall == NULL) {
171 switch (call->procType) {
172 case MkCallS_own_method: {
173 call->procCall = NS(sCallMethod);
174 if (argNum != call->procArity) goto methode_arg_error;
175 }
176 break;
177 case MkCallS_proc:
178 call->procCall = NS(sCallProc);
179 if (argNum != call->procArity) goto methode_arg_error;
180 break;
181 default:
182 MkErrorSetV_3M(obj, "WrongInitError", "found invalid procType for callback '%s'", VAL2STRN(call->procCallback));
183 goto error;
184 break;
185 }
186 }
187
188 // 3. call callback
189 VALUE ary = rb_ary_resize(call->procArgs,4);
190 rb_ary_store(ary,0,call->procCallback);
191 rb_ary_store(ary,1,STRN2VAL(typeName));
192 rb_ary_store(ary,2,HDL2VAL(typeHdl));
193 rb_ary_store(ary,3,HDL2VAL(objHdl));
194 // info: https://docs.ruby-lang.org/en/master/extension_rdoc.html#label-Appendix+E.+RB_GC_GUARD+to+protect+from+premature+GC
195 NS(sRescue)(MK_RT_CALL call->hdl,call->procCall,ary);
197 return MkErrorGetCode_0E();
198
199methode_arg_error:
200 MkErrorSetV_3M(obj, "WrongNumberOfArgError",
201 "for callback '%s' exactly '%d' argument is required, but '%d' was received",
202 VAL2STRN(call->procCallback), argNum, call->procArity);
203 goto error;
204
205error:
206MkDbgDeepX_3(mqctx, "EEE", "cmd=%s", VAL2STRN(rb_inspect(call->procCallback)));
207 return MkErrorStack_0E();
208}
209
210void NS(ObjectDeleteFree) ( MkObjectDeleteFreeF_ARGS )
211{
212 MK(CallFree)(dataP);
213}
214
#define MkErrorCheck_0E()
check return-code and goto error on error …
tag: nhi1-release-250425
#define HDL2VAL(nat)
#define MK(n)
#define OT_Check_ARGS
#define INCR_REF(valP)
#define NS(n)
#define OT_LNG_NULL_IS(obj)
#define VAL2STRN(val)
#define DECR_REF(valP)
#define VAL2I32(val)
#define VAL2MkStringR(_obj)
#define STRN2VAL(nat)
#define OT_ERROR_LNG_2_META_2(m, s)
#define MkErrorGetCode_0E()
#define MkErrorStack_0E()
#define MkErrorSetV_3M(err, callfunc, printfmt,...)
#define MK_ERROR_PANIC
#define mk_inline
MkErrorE
collection for the different error-codes …
@ MK_OK
(persistent) everything is OK.
static bool MkStringIsNULL(MkStringR const strR)
check if strR is MK_NULL_STR return true or false …
MK_PTRB * MK_PTR
generic pointer data-type
MK_PTRB * MK_MNG
managed object pointer, datatype will be checked at runtime
MK_PTRB * MK_CBP
generic pointer to call-back data
#define MkDbgDeepX_3(m, ident, fmt,...)
static bool MkSelfExists(MK_OBJN obj)
Check if the MkObjectS::self exists …
MK_PTR MkSysCalloc(MK_OBJN fmtobj, size_t const nmemb, size_t const size)
calloc syscall with rbmkkernel error plugin
#define MkSysFree(pointer)
#define MkObjectDeleteCallF_CHECK
validate call to MkObjectDeleteCallF
#define MkObjectDeleteCallF_ARGS
the MkObjectDeleteCallF arguments with default names
#define MkObjectDeleteFreeF_ARGS
the MkObjectDeleteFreeF arguments with default names
#define MK_RT_PTR
#define MK_RT_CALL
#define MK_RT_ARGS
#define OT_ERROR_STACK
#define WrongNumArgs(...)
#define WrongCallableError(got)
MK_EXTERN enum MkErrorE MK_DECL MK CheckCallable(OT_Check_ARGS, MK_CBP *)
VALUE procCallback
VALUE procArgs
MK_I32 procArity
enum MkCallS::@0 procType
@ MkCallS_unbound_method
rbmkkernel_procCallF procCall
string data default format …
MK_STRN ptr
pointer to the string data