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