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