32#ifndef _QORE_QOREOBJECTINTERN_H
34#define _QORE_QOREOBJECTINTERN_H
36#include "qore/intern/VRMutex.h"
46#ifdef _QORE_CYCLE_CHECK
47#define QORE_DEBUG_OBJ_REFS 0
50#define QORE_DEBUG_OBJ_REFS 5
54#include "qore/intern/QoreClassIntern.h"
55#include "qore/intern/RSection.h"
56#include "qore/intern/RSet.h"
63#define QOA_PRIV_ERROR 1
64#define QOA_PUB_ERROR 2
70 DLLLOCAL
bool operator()(
char* s1,
char* s2)
const {
71 return memcmp(s1, s2, SH_SIZE) < 0;
76typedef std::map<char*, QoreHashNode*, lthash> cdmap_t;
96typedef std::pair<AbstractPrivateData*, bool> private_pair_t;
99typedef std::map<qore_classid_t, private_pair_t> keymap_t;
108 keymap_t::const_iterator i = keymap.find(key);
109 if (i == keymap.end())
117 DLLLOCAL
void addToString(
QoreString* str)
const {
118 for (keymap_t::const_iterator i = keymap.begin(), e = keymap.end(); i != e; ++i)
119 str->
sprintf(
"%d=<%p>, ", i->first, i->second.first);
123 for (keymap_t::const_iterator i = keymap.begin(), e = keymap.end(); i != e; ++i)
124 if (!i->second.second)
125 i->second.first->deref(xsink);
129 keymap_t::iterator i = keymap.find(key);
131 if (i == keymap.end() || i->second.second) {
143 keymap_t::iterator i = keymap.find(key);
145 if (i == keymap.end() || i->second.second) {
157 assert(keymap.find(key) == keymap.end());
159 keymap.insert(std::make_pair(key, std::make_pair(pd,
false)));
166 if (keymap.find(key) == keymap.end())
167 keymap.insert(std::make_pair(key, std::make_pair(pd,
true)));
173class qore_object_private :
public RObject {
178 KeyList* privateData =
nullptr;
182 cdmap_t* cdmap =
nullptr;
185 mutable unsigned obj_count = 0;
187 mutable VRMutex gate;
189 int scan_private_data = 0;
191 bool system_object, in_destructor;
192 bool recursive_ref_found;
198 DLLLOCAL ~qore_object_private();
200 DLLLOCAL
void incScanPrivateData();
201 DLLLOCAL
void decScanPrivateData();
212 merge(
reinterpret_cast<const QoreHashNode*
>(v), vl, sdh, xsink);
225 DLLLOCAL
int getLValue(
const char* key, LValueHelper& lvh,
const qore_class_private* class_ctx,
bool for_remove,
230 const qore_class_private* class_ctx = runtime_get_class();
231 if (class_ctx && !qore_class_private::runtimeCheckPrivateClassAccess(*theclass, class_ctx))
234 QoreAutoVarRWReadLocker al(rml);
236 if (status == OS_DELETED) {
237 makeAccessDeletedObjectException(xsink, theclass->
getName());
251 const qore_class_private* member_class_ctx =
nullptr;
252 if (!checkMemberAccessIntern(hi.getKey(),
false, class_ctx, member_class_ctx))
262 const qore_class_private* class_ctx = runtime_get_class();
263 if (class_ctx && !qore_class_private::runtimeCheckPrivateClassAccess(*theclass, class_ctx))
266 QoreAutoVarRWReadLocker al(rml);
268 if (status == OS_DELETED) {
269 makeAccessDeletedObjectException(xsink, theclass->
getName());
281 const qore_class_private* member_class_ctx =
nullptr;
282 if (!checkMemberAccessIntern(hi.getKey(),
false, class_ctx, member_class_ctx))
291 DLLLOCAL
int checkMemberAccessIntern(
const char* mem,
bool has_public_members,
292 const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx)
const {
293 assert(!member_class_ctx);
295 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
296 const QoreMemberInfo* info = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
298 return has_public_members ? QOA_PUB_ERROR : QOA_OK;
300 member_class_ctx = info->getClassContext(class_ctx);
301 return ((info->access > Public) && !class_ctx) ? QOA_PRIV_ERROR : QOA_OK;
305 DLLLOCAL
const QoreHashNode* getInternalData(
const qore_class_private* class_ctx)
const {
308 cdmap_t::const_iterator i = cdmap->find(class_ctx->getHash());
309 return i != cdmap->end() ? i->second :
nullptr;
313 DLLLOCAL
QoreHashNode* getInternalData(
const qore_class_private* class_ctx) {
316 cdmap_t::iterator i = cdmap->find(class_ctx->getHash());
317 return i != cdmap->end() ? i->second :
nullptr;
321 DLLLOCAL
QoreHashNode* getCreateInternalData(
const qore_class_private* class_ctx) {
323 cdmap_t::iterator i = cdmap->find(class_ctx->getHash());
324 if (i != cdmap->end())
330 cdmap->insert(cdmap_t::value_type(class_ctx->getHash(),
id));
335 DLLLOCAL
void copyInternalData(
const qore_object_private& old) {
341 for (
auto& i : *old.cdmap) {
342 cdmap->insert(cdmap_t::value_type(i.first, i.second->copy()));
348 DLLLOCAL
void setValueIntern(
const qore_class_private* class_ctx,
const char* key,
QoreValue val,
351 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
352 const qore_class_private*& member_class_ctx)
const;
354 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
355 const qore_class_private*& member_class_ctx,
ExceptionSink* xsink)
const {
356 int rc = checkMemberAccess(mem, class_ctx, member_class_ctx);
361 if (rc == QOA_PRIV_ERROR) {
362 doPrivateException(mem, xsink);
364 doPublicException(mem, xsink);
369 DLLLOCAL
int checkMemberAccessGetTypeInfo(
ExceptionSink* xsink,
const char* mem,
370 const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx,
371 const QoreTypeInfo*& typeInfo)
const {
372 assert(!member_class_ctx);
373 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
374 const QoreMemberInfo* mi = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
376 if (mi->access > Public && !class_ctx) {
377 doPrivateException(mem, xsink);
381 member_class_ctx = mi->getClassContext(class_ctx);
382 typeInfo = mi->getTypeInfo();
388 doPublicException(mem, xsink);
396 DLLLOCAL
QoreValue takeMember(LValueHelper& lvh,
const char* mem);
398 DLLLOCAL
void takeMembers(QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l);
407 printd(5,
"qore_object_private::cleanup() this: %p privateData: %p\n",
this, privateData);
410 privateData =
nullptr;
414 td->clear(xsink,
true);
418 for (
auto& i : *cdm) {
419 i.second->clear(xsink,
true);
420 i.second->deref(xsink);
428 printd(5,
"qore_object_private::obliterate() obj: %p class: %s %d->%d\n", obj, theclass->
getName(),
429 obj->references.load(), obj->references.load() - 1);
431#ifdef QORE_DEBUG_OBJ_REFS
432 printd(QORE_DEBUG_OBJ_REFS,
"qore_object_private::obliterate() obj: %p class: %s: references %d->%d\n", obj,
433 theclass->
getName(), obj->references.load(), obj->references.load() - 1);
438 if (--obj->references)
443 QoreSafeVarRWWriteLocker sl(rml);
445 if (in_destructor || status != OS_OK) {
446 printd(5,
"qore_object_private::obliterate() obj: %p data: %p in_destructor: %d status: %d\n", obj,
447 data, in_destructor, status);
455 printd(5,
"qore_object_private::obliterate() obj: %p class: %s\n", obj, theclass->
getName());
458 cdmap_t* cdm = cdmap;
463 removeInvalidateRSetIntern();
469 privateData->derefAll(xsink);
471 cleanup(xsink, td, cdm);
476 DLLLOCAL
void doPrivateException(
const char* mem,
ExceptionSink* xsink)
const {
477 xsink->
raiseException(
"PRIVATE-MEMBER",
"'%s' is a private member of class '%s'", mem, theclass->
getName());
480 DLLLOCAL
void doPublicException(
const char* mem,
ExceptionSink* xsink)
const {
481 xsink->
raiseException(
"INVALID-MEMBER",
"'%s' is not a registered member of class '%s'", mem,
485 DLLLOCAL
virtual const char* getName()
const {
489 DLLLOCAL
virtual void deleteObject() {
493 DLLLOCAL
virtual bool isValidImpl()
const {
494 if (status != OS_OK || in_destructor) {
495 printd(QRO_LVL,
"qore_object_intern::isValidImpl() this: %p cannot delete graph obj status: %d "
496 "in_destructor: %d\n",
this, status, in_destructor);
502 DLLLOCAL
virtual bool scanMembersIntern(RSetHelper& rsh,
QoreHashNode* odata);
504 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
507 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
508 assert(rml.hasRSectionLock());
509 printd(5,
"qore_object_private::needsScan() scan_count: %d scan_private_data: %d scan_now: %d\n",
510 getScanCount(), scan_private_data, scan_now);
513 if ((!getScanCount() && !scan_private_data) || status != OS_OK) {
520 if (!rrefs && scan_now) {
521 deferred_scan =
false;
529 deferred_scan =
true;
531 if (!rset && !scan_private_data) {
539 removeInvalidateRSetIntern();
553 privateData =
new KeyList;
555 printd(5,
"qore_object_private::setPrivate() this: %p 2:privateData: %p (%s) key: %d pd: %p\n",
this,
556 privateData, theclass->
getName(), key, pd);
557 privateData->insert(key, pd);
558 addVirtualPrivateData(key, pd);
565 QoreSafeVarRWWriteLocker sl(rml);
566 return privateData ? privateData->getAndRemovePtr(key) :
nullptr;
578 DLLLOCAL
QoreValue& getMemberValueRefForInitialization(
const char* member,
const qore_class_private* class_ctx);
588 DLLLOCAL
void incScanCount(
int dt) {
590 assert(obj_count || dt > 0);
596 DLLLOCAL
unsigned getScanCount()
const {
600 DLLLOCAL VRMutex* getGate()
const {
619 DLLLOCAL
void customRefIntern(
bool real);
626 DLLLOCAL
int startCall(
const char* mname,
ExceptionSink* xsink);
633 DLLLOCAL
void setRealReference();
636 DLLLOCAL
void unsetRealReference();
638 DLLLOCAL
const char* getClassName()
const {
645 return obj.priv->evalBuiltinMethodWithPrivateData(method, meth, args, rtflags, xsink);
648 DLLLOCAL
static qore_object_private* get(
QoreObject& obj) {
652 DLLLOCAL
static const qore_object_private* get(
const QoreObject& obj) {
657 bool check_access =
true) {
658 return obj.priv->takeMember(xsink, mem, check_access);
661 DLLLOCAL
static QoreValue takeMember(
QoreObject& obj, LValueHelper& lvh,
const char* mem) {
662 return obj.priv->takeMember(lvh, mem);
665 DLLLOCAL
static void takeMembers(
QoreObject& o, QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l) {
666 o.priv->takeMembers(rv, lvh, l);
669 DLLLOCAL
static int getLValue(
const QoreObject& obj,
const char* key, LValueHelper& lvh,
670 const qore_class_private* class_ctx,
bool for_remove,
ExceptionSink* xsink) {
671 return obj.priv->getLValue(key, lvh, class_ctx, for_remove, xsink);
675 return obj->priv->firstKey(xsink);
679 return obj->priv->lastKey(xsink);
682 DLLLOCAL
static unsigned getScanCount(
const QoreObject& o) {
683 return o.priv->getScanCount();
686 DLLLOCAL
static void incScanCount(
const QoreObject& o,
int dt) {
687 o.priv->incScanCount(dt);
691class qore_object_lock_handoff_helper {
693 qore_object_private* pobj;
697 DLLLOCAL qore_object_lock_handoff_helper(qore_object_private* n_pobj,
AutoVLock& n_vl) : pobj(n_pobj), vl(n_vl) {
699 assert(vl.
getRWL() == &pobj->rml);
714 DLLLOCAL ~qore_object_lock_handoff_helper() {
723 DLLLOCAL
void stayLocked() {
724 vl.
set(pobj->obj, &pobj->rml);
the base class for all data to be used as private data of Qore objects
Definition: AbstractPrivateData.h:44
DLLLOCAL void ref() const
increments the reference count of the object
Definition: AbstractPrivateData.h:51
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
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
AutoVLock is a container for safely managing global variable and object lock handovers,...
Definition: AutoVLock.h:80
DLLEXPORT void del()
manually releases the lock currently held
DLLLOCAL void clear()
leaves the lock locked and the object referenced and clears the object and lock pointers
DLLLOCAL QoreObject * getObject() const
gets the current object
DLLLOCAL void set(QoreVarRWLock *n_rwl)
sets the current lock
DLLLOCAL QoreVarRWLock * getRWL() const
gets the current read-write lock
constant iterator class for QoreHashNode, to be only created on the stack
Definition: QoreHashNode.h:590
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
defines a Qore-language class
Definition: QoreClass.h:253
DLLEXPORT bool hasPublicMembersInHierarchy() const
returns true if the class has any publicly-declared members
DLLEXPORT const char * getName() const
returns the class name
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
DLLEXPORT const char * getFirstKey() const
returns the cstring value of the first key in the hash
DLLEXPORT const char * getLastKey() const
returns the cstring value of the last key in the hash
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
a method in a QoreClass
Definition: QoreClass.h:139
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:128
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
DLLEXPORT int sprintf(const char *fmt,...)
this will concatentate a formatted string to the existing string according to the format string and t...
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
reverse constant iterator class for QoreHashNode, to be only created on the stack
Definition: QoreHashNode.h:667
Helps dereference values outside of locks.
Definition: QoreLibIntern.h:543
uint64_t q_rt_flags_t
runtime code execution flags
Definition: common.h:263
unsigned qore_classid_t
used for the unique class ID for QoreClass objects
Definition: common.h:79
const qore_type_t NT_HASH
type value for QoreHashNode
Definition: node_types.h:51
const qore_type_t NT_OBJECT
type value for QoreObject
Definition: node_types.h:52
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276