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