Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
qore_thread_intern.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 qore_thread_intern.h
4
5 POSIX thread library for Qore
6
7 Qore Programming Language
8
9 Copyright (C) 2003 - 2023 Qore Technologies, s.r.o.
10
11 Permission is hereby granted, free of charge, to any person obtaining a
12 copy of this software and associated documentation files (the "Software"),
13 to deal in the Software without restriction, including without limitation
14 the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 and/or sell copies of the Software, and to permit persons to whom the
16 Software is furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28
29 Note that the Qore library is released under a choice of three open-source
30 licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
31 information.
32*/
33
34#ifndef _QORE_QORE_THREAD_INTERN_H
35#define _QORE_QORE_THREAD_INTERN_H
36
37#include <vector>
38#include <set>
39#include <map>
40
41#ifndef QORE_THREAD_STACK_SIZE
42#define QORE_THREAD_STACK_SIZE 1024*512
43#endif
44
45// the values here are subject to change and come from purely empirical testing
46#ifndef QORE_STACK_GUARD
47// "generic" value (tested on OSX i386 and ppc and Linux i386)
48#define QORE_STACK_GUARD (1024 * 8)
49#endif // QORE_STACK_GUARD
50
51class Operator;
52class Context;
53class CVNode;
54class CallNode;
55class CallStack;
56class LocalVar;
57class LocalVarValue;
58class ClosureParseEnvironment;
59class QoreClosureBase;
60hashdecl ClosureVarValue;
61class VLock;
62class ConstantEntry;
63class qore_ns_private;
64class qore_root_ns_private;
65class qore_class_private;
66class AbstractQoreFunctionVariant;
67class AbstractQoreZoneInfo;
68class ThreadProgramData;
69hashdecl ThreadLocalProgramData;
70class QoreAbstractModule;
71class QoreRWLock;
72
73DLLLOCAL extern Operator* OP_BACKGROUND;
74
75class VNode;
76class AbstractQoreZoneInfo;
77class ThreadData;
78
79hashdecl ModuleContextNamespaceCommit {
80 qore_ns_private* parent;
81 qore_ns_private* nns;
82
83 DLLLOCAL ModuleContextNamespaceCommit(qore_ns_private* n_parent, qore_ns_private* n_nns) : parent(n_parent), nns(n_nns) {
84 }
85};
86
87typedef std::vector<ModuleContextNamespaceCommit> mcnl_t;
88
89class ModuleContextNamespaceList : public mcnl_t {
90private:
91 // not implemented
92 DLLLOCAL ModuleContextNamespaceList(const ModuleContextNamespaceList&);
93
94public:
95 DLLLOCAL ModuleContextNamespaceList() {
96 }
97
98 DLLLOCAL ~ModuleContextNamespaceList() {
99 assert(empty());
100 }
101
102 DLLLOCAL void clear();
103};
104
105hashdecl ModuleContextFunctionCommit {
106 qore_ns_private* parent;
107 const char* name;
108 AbstractQoreFunctionVariant* v;
109
110 DLLLOCAL ModuleContextFunctionCommit(qore_ns_private* n_parent, const char* n_name, AbstractQoreFunctionVariant* n_v) : parent(n_parent), name(n_name), v(n_v) {
111 }
112};
113
114typedef std::vector<ModuleContextFunctionCommit> mcfl_t;
115
116class ModuleContextFunctionList : public mcfl_t {
117private:
118 // not implemented
119 DLLLOCAL ModuleContextFunctionList(const ModuleContextFunctionList&);
120
121public:
122 DLLLOCAL ModuleContextFunctionList() {
123 }
124
125 DLLLOCAL ~ModuleContextFunctionList() {
126 assert(empty());
127 }
128
129 DLLLOCAL void clear();
130};
131
132class QoreModuleContext {
133public:
134 ModuleContextNamespaceList mcnl;
135 ModuleContextFunctionList mcfl;
136
137 DLLLOCAL QoreModuleContext(const char* n, qore_root_ns_private* n_rns, ExceptionSink& xs);
138
139 DLLLOCAL ~QoreModuleContext() {
140 assert(!err);
141 }
142
143 DLLLOCAL void error(const char* fmt, ...);
144
145 DLLLOCAL bool hasError() const {
146 return xsink;
147 }
148
149 DLLLOCAL void commit();
150
151 DLLLOCAL void rollback() {
152 mcnl.clear();
153 mcfl.clear();
154 }
155
156 DLLLOCAL qore_root_ns_private* getRootNS() const {
157 return rns;
158 }
159
160 DLLLOCAL const char* getName() const {
161 return name;
162 }
163
164protected:
165 const char* name;
166 qore_root_ns_private* rns;
167 QoreStringNode* err = nullptr;
168 QoreModuleContext* parent;
169 ExceptionSink& xsink;
170};
171
172class QoreModuleDefContext {
173public:
174 typedef std::set<std::string> strset_t;
175 typedef std::map<std::string, std::string> strmap_t;
176
177 QoreValue init_c, // the initialization closure
178 del_c; // the destructor closure
179
180 const QoreProgramLocation* init_loc = nullptr,
181 * del_loc = nullptr;
182
183 DLLLOCAL QoreModuleDefContext() {
184 }
185
186 DLLLOCAL ~QoreModuleDefContext() {
187 init_c.discard(nullptr);
188 del_c.discard(nullptr);
189 }
190
191 // set of valid tags
192 static strset_t vset;
193
194 // set of tag definitions
195 strmap_t vmap;
196
197 DLLLOCAL int set(const QoreProgramLocation* loc, const char* key, QoreValue val);
198
199 DLLLOCAL const char* get(const char* str) const {
200 strmap_t::const_iterator i = vmap.find(str);
201 return i == vmap.end() || i->second.empty() ? nullptr : i->second.c_str();
202 }
203
204 DLLLOCAL int parseInit();
205
206 DLLLOCAL bool hasInit() const {
207 return init_c ? true : false;
208 }
209
210 DLLLOCAL int init(QoreProgram& pgm, ExceptionSink& xsink);
211
212 DLLLOCAL AbstractQoreNode* takeDel();
213
214protected:
215 DLLLOCAL int initClosure(const QoreProgramLocation* loc, QoreValue& c, const char* n);
216};
217
218DLLLOCAL QoreValue do_op_background(const QoreValue left, ExceptionSink* xsink);
219
220// returns 0 if the last mark has been cleared, -1 if there are more marks to check
221DLLLOCAL int purge_thread_resources_to_mark(ExceptionSink* xsink);
222DLLLOCAL void purge_thread_resources(ExceptionSink* xsink);
223DLLLOCAL void purge_pgm_thread_resources(const QoreProgram* pgm, ExceptionSink* xsink);
224DLLLOCAL void mark_thread_resources();
225DLLLOCAL void beginParsing(const char* file, void* ps = NULL, const char* src = nullptr, int offset = 0);
226DLLLOCAL void* endParsing();
227DLLLOCAL Context* get_context_stack();
228DLLLOCAL void update_context_stack(Context* cstack);
229
230DLLLOCAL const QoreStackLocation* get_runtime_stack_location();
231DLLLOCAL const QoreStackLocation* update_get_runtime_stack_location(QoreStackLocation* stack_loc,
232 const AbstractStatement*& current_stmt, QoreProgram*& current_pgm);
233DLLLOCAL const QoreStackLocation* update_get_runtime_stack_builtin_location(QoreStackLocation* stack_loc,
234 const AbstractStatement*& current_stmt, QoreProgram*& current_pgm, const QoreProgramLocation*& old_runtime_loc);
235DLLLOCAL void update_runtime_stack_location(const QoreStackLocation* stack_loc);
236DLLLOCAL void update_runtime_stack_location(const QoreStackLocation* stack_loc, const QoreProgramLocation* runtime_loc);
237
238DLLLOCAL const QoreProgramLocation* get_runtime_location();
239DLLLOCAL void update_get_runtime_statement_location(const AbstractStatement* stmt,
240 const QoreProgramLocation* loc, const AbstractStatement*& old_stmt, const QoreProgramLocation*& old_loc);
241DLLLOCAL void update_runtime_statement_location(const AbstractStatement* stmt, const QoreProgramLocation* loc);
242
243DLLLOCAL void set_parse_file_info(QoreProgramLocation& loc);
244DLLLOCAL const char* get_parse_code();
245
246DLLLOCAL const AbstractStatement* get_runtime_statement();
247
248DLLLOCAL const QoreTypeInfo* parse_set_implicit_arg_type_info(const QoreTypeInfo* ti);
249DLLLOCAL const QoreTypeInfo* parse_get_implicit_arg_type_info();
250
251DLLLOCAL int64 parse_get_parse_options();
252DLLLOCAL int64 runtime_get_parse_options();
253
254DLLLOCAL bool parse_check_parse_option(int64 o);
255DLLLOCAL bool runtime_check_parse_option(int64 o);
256
257DLLLOCAL RootQoreNamespace* getRootNS();
258DLLLOCAL void updateCVarStack(CVNode* ncvs);
259DLLLOCAL CVNode* getCVarStack();
260DLLLOCAL void updateVStack(VNode* nvs);
261DLLLOCAL VNode* getVStack();
262
263//DLLLOCAL void setParseClass(QoreClass* c);
264DLLLOCAL QoreClass* parse_get_class();
265DLLLOCAL qore_class_private* parse_get_class_priv();
266DLLLOCAL void thread_set_class_and_ns(const qore_class_private* new_cls, qore_ns_private* new_ns, const qore_class_private*& old_cls, qore_ns_private*& old_ns);
267DLLLOCAL void thread_set_class_and_ns(const qore_class_private* new_cls, qore_ns_private* new_ns);
268DLLLOCAL void thread_set_ns(qore_ns_private* new_ns, qore_ns_private*& old_ns);
269DLLLOCAL void thread_set_ns(qore_ns_private* new_ns);
270DLLLOCAL qore_ns_private* parse_get_ns();
271
272DLLLOCAL void substituteObjectIfEqual(QoreObject* o);
273DLLLOCAL QoreObject* substituteObject(QoreObject* o);
274
275DLLLOCAL QoreException* catch_swap_exception(QoreException* e);
276DLLLOCAL QoreException* catch_get_exception();
277
278DLLLOCAL VLock* getVLock();
279DLLLOCAL void end_signal_thread(ExceptionSink* xsink);
280DLLLOCAL void delete_thread_local_data();
281DLLLOCAL void parse_cond_push(bool mark = false);
282DLLLOCAL bool parse_cond_else();
283DLLLOCAL bool parse_cond_pop(const QoreProgramLocation* loc);
284DLLLOCAL bool parse_cond_test(const QoreProgramLocation* loc);
285DLLLOCAL void push_parse_options();
286DLLLOCAL void parse_try_module_inc();
287DLLLOCAL bool parse_try_module_dec(const QoreProgramLocation* loc);
288DLLLOCAL unsigned parse_try_module_get();
289DLLLOCAL void parse_try_module_set(unsigned c);
290
291DLLLOCAL void parse_push_name(const char* name);
292DLLLOCAL std::string parse_pop_name(std::string& path);
293
294DLLLOCAL void parse_push_ns_name(const char* name);
295DLLLOCAL std::string parse_pop_ns_name(std::string& path);
296
297DLLLOCAL std::string get_ns_path(const char* name);
298
299DLLLOCAL void set_module_context(QoreModuleContext* qmc);
300DLLLOCAL QoreModuleContext* get_module_context();
301DLLLOCAL QoreModuleDefContext* set_module_def_context(QoreModuleDefContext* qmd);
302DLLLOCAL QoreModuleDefContext* get_module_def_context();
303DLLLOCAL void parse_set_module_def_context_name(const char* name);
304DLLLOCAL const char* set_module_context_name(const char* n);
305DLLLOCAL const char* get_module_context_name();
306
307DLLLOCAL void parse_set_try_reexport(bool tr);
308DLLLOCAL bool parse_get_try_reexport();
309
310DLLLOCAL void set_thread_tz(const AbstractQoreZoneInfo* tz);
311DLLLOCAL const AbstractQoreZoneInfo* get_thread_tz(bool& set);
312DLLLOCAL void clear_thread_tz();
313
314DLLLOCAL ThreadProgramData* get_thread_program_data();
315DLLLOCAL ThreadLocalProgramData* get_thread_local_program_data();
316
317DLLLOCAL int thread_ref_set(const lvalue_ref* r);
318DLLLOCAL void thread_ref_remove(const lvalue_ref* r);
319
320// pushes a new argv reference counter
321DLLLOCAL void new_argv_ref();
322
323// increments the parse argv reference counter
324DLLLOCAL void inc_argv_ref();
325
326// pushes an "ignore numeric reference" context
327DLLLOCAL void push_ignore_numeric_argv_ref();
328
329// pops an "ignore numeric reference" context
330DLLLOCAL void pop_ignore_numeric_argv_ref();
331
332// increments the parse argv reference counter for numeric references (ex: $1)
333DLLLOCAL void inc_numeric_argv_ref();
334
335// gets the parse argv reference counter and pops the context
336DLLLOCAL int get_pop_argv_ref();
337
338// clears the argv reference stack
339DLLLOCAL void clear_argv_ref();
340
341DLLLOCAL int set_constant(ConstantEntry* ce);
342DLLLOCAL void remove_constant(ConstantEntry* ce);
343
344DLLLOCAL QoreAbstractModule* set_reexport(QoreAbstractModule* m, bool current_reexport, bool& old_reexport);
345DLLLOCAL void set_reexport(QoreAbstractModule* m, bool reexport);
346
347DLLLOCAL void parseSetCodeInfo(const char* parse_code, const QoreTypeInfo* returnTypeInfo, const char*& old_code, const QoreTypeInfo*& old_returnTypeInfo);
348DLLLOCAL void parseRestoreCodeInfo(const char* parse_code, const QoreTypeInfo* returnTypeInfo);
349// sets the new type and returns the old
350DLLLOCAL const QoreTypeInfo* saveReturnTypeInfo(const QoreTypeInfo* returnTypeInfo);
351DLLLOCAL const QoreTypeInfo* getReturnTypeInfo();
352
353DLLLOCAL const QoreTypeInfo* parse_get_return_type_info();
354
355DLLLOCAL QoreProgram* get_set_program_call_context(QoreProgram* new_pgm);
356DLLLOCAL void set_program_call_context(QoreProgram* new_pgm);
357
358// issue #3242: make sure we can temporarily set any current lvar stack to nullptr when parsing out of order
359class LVarStackBreakHelper {
360public:
361 DLLLOCAL LVarStackBreakHelper();
362 DLLLOCAL ~LVarStackBreakHelper();
363
364private:
365 VNode* vnode;
366};
367
368class ProgramCallContextHelper {
369public:
370 DLLLOCAL ProgramCallContextHelper(QoreProgram* new_pgm);
371 DLLLOCAL ~ProgramCallContextHelper();
372
373private:
374 QoreProgram* pgm;
375};
376
377class ModuleReExportHelper {
378protected:
379 QoreAbstractModule* m;
380 bool reexport;
381
382public:
383 DLLLOCAL ModuleReExportHelper(QoreAbstractModule* mi, bool reexp);
384 DLLLOCAL ~ModuleReExportHelper();
385};
386
387class QoreParseCountContextHelper {
388protected:
389 unsigned count;
390
391public:
392 DLLLOCAL QoreParseCountContextHelper() : count(parse_try_module_get()) {
393 parse_try_module_set(0);
394 }
395
396 DLLLOCAL ~QoreParseCountContextHelper() {
397 parse_try_module_set(count);
398 }
399};
400
401class QoreProgramStackLocationHelper {
402public:
403 DLLLOCAL QoreProgramStackLocationHelper(QoreStackLocation* stack_loc, const AbstractStatement*& current_stmt,
404 QoreProgram*& current_pgm) :
405 stack_loc(update_get_runtime_stack_location(stack_loc, current_stmt, current_pgm)) {
406 }
407
408 DLLLOCAL ~QoreProgramStackLocationHelper() {
409 update_runtime_stack_location(stack_loc);
410 }
411
412protected:
413 const QoreStackLocation* stack_loc;
414};
415
416class QoreInternalCallStackLocationHelperBase : public QoreStackLocation, public QoreProgramStackLocationHelper {
417public:
418 DLLLOCAL QoreInternalCallStackLocationHelperBase() : QoreProgramStackLocationHelper(this, stmt, pgm) {
419 }
420
421 DLLLOCAL virtual QoreProgram* getProgram() const {
422 return pgm;
423 }
424
425 DLLLOCAL virtual const AbstractStatement* getStatement() const {
426 return stmt;
427 }
428
429protected:
430 const AbstractStatement* stmt;
431 QoreProgram* pgm;
432};
433
434class QoreInternalCallStackLocationHelper : public QoreInternalCallStackLocationHelperBase {
435public:
436 DLLLOCAL QoreInternalCallStackLocationHelper(const QoreProgramLocation& loc, const std::string& call,
437 qore_call_t call_type) : loc(loc), call(call), call_type(call_type) {
438 }
439
441 DLLLOCAL virtual const QoreProgramLocation& getLocation() const {
442 return loc;
443 }
444
446 DLLLOCAL virtual const std::string& getCallName() const {
447 return call;
448 }
449
450 DLLLOCAL virtual qore_call_t getCallType() const {
451 return call_type;
452 }
453
454protected:
455 const QoreProgramLocation& loc;
456 const std::string call;
457 qore_call_t call_type;
458};
459
460class QoreProgramLocationHelper {
461public:
462 DLLLOCAL QoreProgramLocationHelper(const QoreProgramLocation* n_loc, const AbstractStatement* n_stat = nullptr) {
463 update_get_runtime_statement_location(n_stat, n_loc, statement, loc);
464 }
465
466 DLLLOCAL ~QoreProgramLocationHelper() {
467 update_runtime_statement_location(statement, loc);
468 }
469
470protected:
471 const QoreProgramLocation* loc;
472 const AbstractStatement* statement;
473};
474
475class QoreProgramOptionalLocationHelper {
476public:
477 DLLLOCAL QoreProgramOptionalLocationHelper(const QoreProgramLocation* n_loc, const AbstractStatement* n_stat = nullptr) : restore((bool)n_loc) {
478 if (n_loc) {
479 update_get_runtime_statement_location(n_stat, n_loc, statement, loc);
480 }
481 }
482
483 DLLLOCAL ~QoreProgramOptionalLocationHelper() {
484 if (restore) {
485 update_runtime_statement_location(statement, loc);
486 }
487 }
488
489protected:
490 const QoreProgramLocation* loc;
491 const AbstractStatement* statement;
492 bool restore;
493};
494
495// allows for the parse lock for the current program to be acquired by binary modules
496class CurrentProgramRuntimeParseContextHelper {
497public:
498 // acquires the parse lock; if already acquired by another thread, then this call blocks until the lock can be acquired
499 DLLEXPORT CurrentProgramRuntimeParseContextHelper();
500 // releases the parse lock for the current program
501 DLLEXPORT ~CurrentProgramRuntimeParseContextHelper();
502
503private:
504 // not implemented
505 CurrentProgramRuntimeParseContextHelper(const CurrentProgramRuntimeParseContextHelper&) = delete;
506 void* operator new(size_t) = delete;
507};
508
509// allows for implicit argument types to be set at parse time
510class ParseImplicitArgTypeHelper {
511public:
512 DLLLOCAL ParseImplicitArgTypeHelper(const QoreTypeInfo* ti) : ati(parse_set_implicit_arg_type_info(ti)) {
513 }
514
515 DLLLOCAL ~ParseImplicitArgTypeHelper() {
516 parse_set_implicit_arg_type_info(ati);
517 }
518
519private:
520 const QoreTypeInfo* ati;
521};
522
523// acquires a TID and thread entry, returns -1 if not successful
524DLLLOCAL int get_thread_entry(bool reuse_last = false);
525// acquires TID 0 and sets up the signal thread entry, always returns 0
526DLLLOCAL int get_signal_thread_entry();
527DLLLOCAL void deregister_signal_thread();
528DLLLOCAL void register_thread(int tid, pthread_t ptid, QoreProgram* pgm, bool foreign = false);
529DLLLOCAL void deregister_thread(int tid);
530DLLLOCAL void delete_signal_thread();
531
532// returns 1 if data structure is already on stack, 0 if not (=OK)
533DLLLOCAL int thread_push_container(const AbstractQoreNode* n);
534DLLLOCAL void thread_pop_container(const AbstractQoreNode* n);
535
536// called when a StatementBlock has "on block exit" blocks
537DLLLOCAL void pushBlock(block_list_t::iterator i);
538// called when a StatementBlock has "on block exit" blocks
539DLLLOCAL block_list_t::iterator popBlock();
540// called by each "on_block_exit" statement to activate it's code for the block exit
541DLLLOCAL void advance_on_block_exit();
542
543DLLLOCAL LocalVarValue* thread_instantiate_lvar();
544DLLLOCAL void thread_uninstantiate_lvar(ExceptionSink* xsink);
545DLLLOCAL void thread_uninstantiate_self();
546
547DLLLOCAL void thread_set_closure_parse_env(ClosureParseEnvironment* cenv);
548DLLLOCAL ClosureParseEnvironment* thread_get_closure_parse_env();
549
550DLLLOCAL ClosureVarValue* thread_instantiate_closure_var(const char* id, const QoreTypeInfo* typeInfo, QoreValue& nval, bool assign);
551DLLLOCAL void thread_instantiate_closure_var(ClosureVarValue* cvar);
552DLLLOCAL void thread_uninstantiate_closure_var(ExceptionSink* xsink);
553DLLLOCAL ClosureVarValue* thread_find_closure_var(const char* id);
554
555DLLLOCAL ClosureVarValue* thread_get_runtime_closure_var(const LocalVar* id);
556DLLLOCAL const QoreClosureBase* thread_set_runtime_closure_env(const QoreClosureBase* current);
557
558typedef std::vector<ClosureVarValue*> cvv_vec_t;
559DLLLOCAL cvv_vec_t* thread_get_all_closure_vars();
560
561DLLLOCAL void thread_push_frame_boundary();
562DLLLOCAL void thread_pop_frame_boundary();
563
564DLLLOCAL QoreHashNode* thread_get_local_vars(int frame, ExceptionSink* xsink);
565// returns 0 = OK, 1 = no such variable, -1 exception setting variable
566DLLLOCAL int thread_set_local_var_value(int frame, const char* name, const QoreValue& val, ExceptionSink* xsink);
567// returns 0 = OK, 1 = no such variable, -1 exception setting variable
568DLLLOCAL int thread_set_closure_var_value(int frame, const char* name, const QoreValue& val, ExceptionSink* xsink);
569
570DLLLOCAL int get_implicit_element();
571DLLLOCAL int save_implicit_element(int n_element);
572
573DLLLOCAL VNode* update_get_vstack(VNode* vn);
574DLLLOCAL void save_global_vnode(VNode* vn);
575DLLLOCAL VNode* get_global_vnode();
576
577class QoreContainerHelper {
578 const AbstractQoreNode* n;
579 bool err;
580
581public:
582 DLLLOCAL QoreContainerHelper(const AbstractQoreNode* n_n) {
583 // FIXME! need to have an AbstactQoreNode::isContainer() function!
584 qore_type_t t = n_n ? n_n->getType() : NT_NOTHING;
585 if ((t == NT_LIST || t == NT_HASH || t == NT_OBJECT || t >= QORE_NUM_TYPES)) {
586 if (!thread_push_container(n_n)) {
587 n = n_n;
588 err = false;
589 }
590 else {
591 n = nullptr;
592 err = true;
593 }
594 }
595 else {
596 n = nullptr;
597 err = false;
598 }
599 }
600 DLLLOCAL ~QoreContainerHelper() {
601 if (n)
602 thread_pop_container(n);
603 }
604 DLLLOCAL operator bool () const {
605 return !err;
606 }
607};
608
609DLLLOCAL const QoreListNode* thread_get_implicit_args();
610
611DLLLOCAL LocalVarValue* thread_find_lvar(const char* id);
612
613// to get the current runtime object
614DLLLOCAL QoreObject* runtime_get_stack_object();
615// to get the current runtime class
616DLLLOCAL const qore_class_private* runtime_get_class();
617DLLLOCAL void runtime_get_object_and_class(QoreObject*& obj, const qore_class_private*& qc);
618// for methods that behave differently when called within the method itself (methodGate(), memberGate(), etc)
619DLLLOCAL bool runtime_in_object_method(const char* name, const QoreObject* o);
620
621class CodeContextHelperBase {
622private:
623 const char* old_code;
624 QoreObject* old_obj;
625 const qore_class_private* old_class;
626 QoreProgram* old_call_program_context;
627 bool do_ref,
628 do_program_context;
629
630 ExceptionSink* xsink;
631
632public:
633 DLLLOCAL CodeContextHelperBase(const char* code, QoreObject* obj, const qore_class_private* c,
634 ExceptionSink* xsink, bool ref_obj = true);
635 DLLLOCAL ~CodeContextHelperBase();
636};
637
638class ObjectSubstitutionHelper {
639private:
640 QoreObject* old_obj;
641 const qore_class_private* old_class;
642
643public:
644 DLLLOCAL ObjectSubstitutionHelper(QoreObject* obj, const qore_class_private* c);
645 DLLLOCAL ~ObjectSubstitutionHelper();
646};
647
648class OptionalClassObjSubstitutionHelper {
649public:
650 DLLLOCAL OptionalClassObjSubstitutionHelper(const qore_class_private* qc);
651 DLLLOCAL ~OptionalClassObjSubstitutionHelper();
652
653private:
654 QoreObject* old_obj;
655 const qore_class_private* old_class;
656 bool subst;
657};
658
659class OptionalClassOnlySubstitutionHelper {
660public:
661 DLLLOCAL OptionalClassOnlySubstitutionHelper(const qore_class_private* qc);
662 DLLLOCAL ~OptionalClassOnlySubstitutionHelper();
663
664private:
665 const qore_class_private* old_class;
666 bool subst;
667};
668
669class OptionalObjectOnlySubstitutionHelper {
670public:
671 DLLLOCAL OptionalObjectOnlySubstitutionHelper(QoreObject* obj);
672 DLLLOCAL ~OptionalObjectOnlySubstitutionHelper();
673
674private:
675 bool subst;
676 QoreObject* old_obj;
677};
678
679class ThreadSafeLocalVarRuntimeEnvironmentHelper {
680private:
681 const QoreClosureBase* prev;
682
683public:
684 DLLLOCAL ThreadSafeLocalVarRuntimeEnvironmentHelper(const QoreClosureBase* current);
685 DLLLOCAL ~ThreadSafeLocalVarRuntimeEnvironmentHelper();
686};
687
688typedef std::map<const LocalVar*, ClosureVarValue*> cvar_map_t;
689typedef std::set<ClosureVarValue*> cvv_set_t;
690
691class ThreadSafeLocalVarRuntimeEnvironment {
692private:
693 cvar_map_t cmap;
694 cvv_set_t cvvset;
695
696public:
697 DLLLOCAL ThreadSafeLocalVarRuntimeEnvironment(const lvar_set_t* vlist);
698 DLLLOCAL ~ThreadSafeLocalVarRuntimeEnvironment();
699 DLLLOCAL ClosureVarValue* find(const LocalVar* id) const;
700 DLLLOCAL bool hasVar(ClosureVarValue* cvv) const;
701 DLLLOCAL void del(ExceptionSink* xsink);
702
703 DLLLOCAL bool empty() {
704 return cmap.empty();
705 }
706
707 DLLLOCAL const cvar_map_t& getMap() const {
708 return cmap;
709 }
710};
711
712hashdecl ThreadLocalProgramData;
713
714class QoreProgramBlockParseOptionHelper {
715public:
716 DLLLOCAL QoreProgramBlockParseOptionHelper(int64 n_po);
717 DLLLOCAL ~QoreProgramBlockParseOptionHelper();
718
719protected:
720 int64 po;
721};
722
723class ProgramThreadCountContextHelper {
724public:
725 DLLLOCAL ProgramThreadCountContextHelper(ExceptionSink* xsink, QoreProgram* pgm, bool runtime);
726 DLLLOCAL ~ProgramThreadCountContextHelper();
727 static ThreadLocalProgramData* getContextFrame(int& frame, ExceptionSink* xsink);
728 DLLLOCAL bool isFirstThreadLocalProgramData(const ThreadLocalProgramData* tlpd) const;
729
730protected:
731 QoreProgram* old_pgm = nullptr;
732 ThreadLocalProgramData* old_tlpd = nullptr;
733 ProgramThreadCountContextHelper* old_ctx = nullptr;
734 // frame count of tlpd when context is started
735 int save_frameCount = 0;
736 int old_frameCount = 0;
737 bool restore = false;
738 bool init_tlpd = false;
739};
740
741class ProgramRuntimeParseContextHelper {
742protected:
743 QoreProgram* old_pgm;
744 bool restore;
745
746public:
747 DLLLOCAL ProgramRuntimeParseContextHelper(ExceptionSink* xsink, QoreProgram* pgm);
748 DLLLOCAL ~ProgramRuntimeParseContextHelper();
749};
750
751// ensures the program is locked for parsing and that thread-local data is available for execution at parse commit time
752class ProgramRuntimeParseCommitContextHelper {
753protected:
754 QoreProgram* old_pgm;
755 ThreadLocalProgramData* old_tlpd;
756 bool restore;
757
758public:
759 DLLLOCAL ProgramRuntimeParseCommitContextHelper(ExceptionSink* xsink, QoreProgram* pgm);
760 DLLLOCAL ~ProgramRuntimeParseCommitContextHelper();
761};
762
763class ProgramRuntimeParseAccessHelper {
764public:
765 DLLLOCAL ProgramRuntimeParseAccessHelper(ExceptionSink* xsink, QoreProgram* pgm);
766 DLLLOCAL ~ProgramRuntimeParseAccessHelper();
767
768protected:
769 QoreProgram* old_pgm;
770 bool restore;
771};
772
773class RuntimeReferenceHelperBase {
774public:
775 DLLLOCAL RuntimeReferenceHelperBase(const lvalue_ref& r, ExceptionSink* n_xsink)
776 : ref(&r), pch(n_xsink, r.pgm, true), osh(r.self, r.cls) {
777 //printd(5, "RuntimeReferenceHelperBase::RuntimeReferenceHelperBase() this: %p vexp: %p %s %d\n", this,
778 // r.vexp, get_type_name(r.vexp), get_node_type(r.vexp));
779 if (thread_ref_set(&r)) {
780 ref = nullptr;
781 n_xsink->raiseException("CIRCULAR-REFERENCE-ERROR", "a circular lvalue reference was detected");
782 valid = false;
783 }
784 }
785
786 DLLLOCAL ~RuntimeReferenceHelperBase() {
787 if (ref)
788 thread_ref_remove(ref);
789 }
790
791 DLLLOCAL operator bool() const {
792 return valid;
793 }
794
795protected:
796 const lvalue_ref* ref;
797 ProgramThreadCountContextHelper pch;
798 ObjectSubstitutionHelper osh;
799 bool valid = true;
800};
801
802class RuntimeReferenceHelper : public RuntimeReferenceHelperBase {
803public:
804 DLLLOCAL RuntimeReferenceHelper(const ReferenceNode& r, ExceptionSink* n_xsink)
805 : RuntimeReferenceHelperBase(*lvalue_ref::get(&r), n_xsink) {
806 }
807
808 DLLLOCAL RuntimeReferenceHelper(const lvalue_ref& r, ExceptionSink* n_xsink)
809 : RuntimeReferenceHelperBase(r, n_xsink) {
810 }
811};
812
813class ArgvContextHelper {
814public:
815 DLLLOCAL ArgvContextHelper(QoreListNode* argv, ExceptionSink* n_xsink);
816 // calls deref(xsink) on list in destructor
817 DLLLOCAL ~ArgvContextHelper();
818
819private:
820 QoreListNode* old_argv;
821 ExceptionSink* xsink;
822};
823
824class SingleArgvContextHelper {
825public:
826 // any reference in val will be overtaken by the SingleArgvContextHelper object
827 DLLLOCAL SingleArgvContextHelper(QoreValue val, ExceptionSink* n_xsink);
828 // calls deref(xsink) on list in destructor
829 DLLLOCAL ~SingleArgvContextHelper();
830
831private:
832 QoreListNode* old_argv;
833 ExceptionSink* xsink;
834};
835
836class ImplicitElementHelper {
837public:
838 DLLLOCAL ImplicitElementHelper(int n_element) : element(save_implicit_element(n_element)) {
839 }
840 DLLLOCAL ~ImplicitElementHelper() {
841 save_implicit_element(element);
842 }
843
844private:
845 int element;
846};
847
848class CodeContextHelper : public CodeContextHelperBase {
849public:
850 DLLLOCAL CodeContextHelper(ExceptionSink* xs, int t, const char* c, QoreObject* obj = nullptr,
851 const qore_class_private* cls = nullptr, bool ref_obj = true) :
852 CodeContextHelperBase(c, obj, cls, xs, ref_obj) {
853 }
854};
855
856DLLLOCAL void init_qore_threads();
857DLLLOCAL QoreNamespace* get_thread_ns(QoreNamespace& qorens);
858DLLLOCAL void delete_qore_threads();
859DLLLOCAL QoreListNode* get_thread_list();
860DLLLOCAL QoreHashNode* getAllCallStacks();
861DLLLOCAL QoreListNode* qore_get_thread_call_stack();
862
863#if defined(HAVE_PTHREAD_GET_STACKSIZE_NP) || (defined(QORE_HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE))
864#define QORE_HAVE_GET_STACK_SIZE
865#endif
866
867#if defined(QORE_HAVE_PTHREAD_SETNAME_NP_1) || defined(QORE_HAVE_PTHREAD_SETNAME_NP_2) || defined(QORE_HAVE_PTHREAD_SETNAME_NP_3) || defined(QORE_HAVE_PTHREAD_SET_NAME_NP)
868#if defined(HAVE_PTHREAD_GET_NAME_NP) || defined(HAVE_PTHREAD_GETNAME_NP)
869#define QORE_HAVE_THREAD_NAME
870#endif
871#endif
872
873class QorePThreadAttr {
874private:
875 pthread_attr_t attr;
876
877public:
878 DLLLOCAL QorePThreadAttr() {
879 pthread_attr_init(&attr);
880 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
881 }
882
883 DLLLOCAL ~QorePThreadAttr() {
884 //printd(2, "calling pthread_attr_destroy(%p)\n", &attr);
885 pthread_attr_destroy(&attr);
886 //printd(2, "returned from pthread_attr_destroy(%p)\n", &attr);
887 }
888
889#ifdef HAVE_PTHREAD_ATTR_GETSTACK
890 DLLLOCAL void getstack(void*& ptr, size_t& ssize) {
891 pthread_attr_getstack(&attr, &ptr, &ssize);
892 }
893#endif
894
895 DLLLOCAL size_t getstacksize() const {
896 size_t ssize;
897 pthread_attr_getstacksize(&attr, &ssize);
898 return ssize;
899 }
900
901 DLLLOCAL int setstacksize(size_t ssize) {
902 return pthread_attr_setstacksize(&attr, ssize);
903 }
904
905 DLLLOCAL pthread_attr_t* get_ptr() {
906 return &attr;
907 }
908
909#ifdef QORE_HAVE_GET_STACK_SIZE
910 DLLLOCAL static size_t getCurrentThreadStackSize() {
911#ifdef HAVE_PTHREAD_GET_STACKSIZE_NP
912 return pthread_get_stacksize_np(pthread_self());
913#else
914 pthread_attr_t attr;
915 if (pthread_getattr_np(pthread_self(), &attr)) {
916 return 0;
917 }
918 ON_BLOCK_EXIT(pthread_attr_destroy, &attr);
919 size_t size = 0;
920 if (pthread_attr_getstacksize(&attr, &size)) {
921 return 0;
922 }
923 return size;
924#endif
925 }
926#endif
927};
928
929DLLLOCAL extern QorePThreadAttr ta_default;
930
931#ifdef QORE_MANAGE_STACK
932DLLLOCAL int check_stack(ExceptionSink* xsink);
933#endif
934
935class ParseCodeInfoHelper {
936private:
937 const char* parse_code;
938 const QoreTypeInfo* returnTypeInfo;
939
940public:
941 DLLLOCAL ParseCodeInfoHelper(const char* n_parse_code, const QoreTypeInfo* n_returnTypeInfo) {
942 parseSetCodeInfo(n_parse_code, n_returnTypeInfo, parse_code, returnTypeInfo);
943 }
944
945 DLLLOCAL ~ParseCodeInfoHelper() {
946 parseRestoreCodeInfo(parse_code, returnTypeInfo);
947 }
948};
949
950class NamespaceParseContextHelper {
951private:
952 qore_ns_private* ns;
953 bool restore;
954
955public:
956 DLLLOCAL NamespaceParseContextHelper(qore_ns_private* n_ns) {
957 thread_set_ns(n_ns, ns);
958 restore = (ns != n_ns);
959 }
960
961 DLLLOCAL ~NamespaceParseContextHelper() {
962 if (restore) {
963 thread_set_ns(ns);
964 }
965 }
966};
967
968class OptionalNamespaceParseContextHelper {
969private:
970 qore_ns_private* ns;
971 bool restore;
972
973public:
974 DLLLOCAL OptionalNamespaceParseContextHelper(qore_ns_private* n_ns) {
975 if (n_ns) {
976 thread_set_ns(n_ns, ns);
977 restore = (ns != n_ns);
978 } else {
979 restore = false;
980 }
981 }
982
983 DLLLOCAL ~OptionalNamespaceParseContextHelper() {
984 if (restore) {
985 thread_set_ns(ns);
986 }
987 }
988};
989
990class QoreParseClassHelper {
991protected:
992 const qore_class_private* cls;
993 qore_ns_private* ns;
994 bool restore;
995
996public:
997 DLLLOCAL QoreParseClassHelper(QoreClass* new_cls, qore_ns_private* new_ns = nullptr);
998
999 DLLLOCAL ~QoreParseClassHelper();
1000};
1001
1002class ThreadData;
1003
1004class ThreadProgramData : public QoreReferenceCounter {
1005private:
1006 // for the set of QoreProgram objects we have local variables in
1007 typedef std::set<QoreProgram*> pgm_set_t;
1008 pgm_set_t pgm_set;
1009
1010 // lock for pgm_set data structure (which is accessed from multiple threads when QorePrograms deregister themselves)
1011 QoreThreadLock pslock;
1012
1013 ThreadData* td;
1014
1015 DLLLOCAL void ref() {
1016 ROreference();
1017 }
1018
1019 DLLLOCAL ~ThreadProgramData() {
1020 assert(pgm_set.empty());
1021 }
1022
1023public:
1024 DLLLOCAL ThreadProgramData(ThreadData* n_td) : td(n_td) {
1025 }
1026
1027 DLLLOCAL void delProgram(QoreProgram* pgm);
1028 DLLLOCAL bool saveProgram(bool runtime, ExceptionSink* xsink);
1029 DLLLOCAL void del(ExceptionSink* xsink);
1030
1031 DLLLOCAL void deref() {
1032 if (ROdereference())
1033 delete this;
1034 }
1035 DLLLOCAL int gettid();
1036};
1037
1038class ThreadFrameBoundaryHelper {
1039public:
1040 DLLLOCAL ThreadFrameBoundaryHelper(bool doit) : doit(doit) {
1041 if (doit) {
1042 //printd(5, "ThreadFrameBoundaryHelper::ThreadFrameBoundaryHelper: this:%p\n", this);
1043 thread_push_frame_boundary();
1044 }
1045 }
1046
1047 DLLLOCAL ~ThreadFrameBoundaryHelper() {
1048 if (doit) {
1049 //printd(5, "ThreadFrameBoundaryHelper::~ThreadFrameBoundaryHelper: this:%p\n", this);
1050 thread_pop_frame_boundary();
1051 }
1052 }
1053
1054private:
1055 bool doit;
1056};
1057
1058DLLLOCAL extern pthread_mutexattr_t ma_recursive;
1059DLLLOCAL extern QoreRWLock lck_debug_program;
1060
1061#ifdef QORE_HAVE_THREAD_NAME
1062DLLLOCAL void q_set_thread_name(const char* name);
1063DLLLOCAL void q_get_thread_name(QoreString& str);
1064#endif
1065
1067DLLLOCAL void checkpoint_stack_pos(const char*);
1068
1069#endif
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
DLLLOCAL qore_type_t getType() const
returns the data type
Definition: AbstractQoreNode.h:175
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
defines a Qore-language class
Definition: QoreClass.h:253
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:65
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:128
provides a simple POSIX-threads-based read-write lock
Definition: QoreRWLock.h:47
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
DLLEXPORT void ROreference() const
atomically increments the reference count
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Stack location element abstract class.
Definition: ExceptionSink.h:418
virtual DLLLOCAL QoreProgram * getProgram() const =0
returns the QoreProgram container
virtual DLLLOCAL const AbstractStatement * getStatement() const =0
returns the statement for the call for internal Qore code
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
parse type: reference to a lvalue expression
Definition: ReferenceNode.h:45
the root namespace of a QoreProgram object
Definition: QoreNamespace.h:397
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition: common.h:70
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
const qore_type_t NT_LIST
type value for QoreListNode
Definition: node_types.h:50
const qore_type_t NT_HASH
type value for QoreHashNode
Definition: node_types.h:51
const qore_type_t NT_NOTHING
type value for QoreNothingNode
Definition: node_types.h:42
const qore_type_t NT_OBJECT
type value for QoreObject
Definition: node_types.h:52
#define QORE_NUM_TYPES
number of types implemented in the Qore library
Definition: node_types.h:91
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values