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