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;
76 typedef std::map<char*, QoreHashNode*, lthash> cdmap_t;
96 typedef std::pair<AbstractPrivateData*, bool> private_pair_t;
99 typedef 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)));
165 if (keymap.find(key) == keymap.end())
166 keymap.insert(std::make_pair(key, std::make_pair(pd,
true)));
172 class qore_object_private :
public RObject {
177 KeyList* privateData =
nullptr;
181 cdmap_t* cdmap =
nullptr;
184 mutable unsigned obj_count = 0;
186 mutable VRMutex gate;
188 int scan_private_data = 0;
190 bool system_object, in_destructor;
191 bool recursive_ref_found;
197 DLLLOCAL ~qore_object_private();
199 DLLLOCAL
void incScanPrivateData();
200 DLLLOCAL
void decScanPrivateData();
211 merge(
reinterpret_cast<const QoreHashNode*
>(v), vl, sdh, xsink);
224 DLLLOCAL
int getLValue(
const char* key, LValueHelper& lvh,
const qore_class_private* class_ctx,
bool for_remove,
ExceptionSink* xsink);
228 const qore_class_private* class_ctx = runtime_get_class();
229 if (class_ctx && !qore_class_private::runtimeCheckPrivateClassAccess(*theclass, class_ctx))
232 QoreAutoVarRWReadLocker al(rml);
234 if (status == OS_DELETED) {
235 makeAccessDeletedObjectException(xsink, theclass->
getName());
249 const qore_class_private* member_class_ctx =
nullptr;
250 if (!checkMemberAccessIntern(hi.getKey(),
false, class_ctx, member_class_ctx))
260 const qore_class_private* class_ctx = runtime_get_class();
261 if (class_ctx && !qore_class_private::runtimeCheckPrivateClassAccess(*theclass, class_ctx))
264 QoreAutoVarRWReadLocker al(rml);
266 if (status == OS_DELETED) {
267 makeAccessDeletedObjectException(xsink, theclass->
getName());
279 const qore_class_private* member_class_ctx =
nullptr;
280 if (!checkMemberAccessIntern(hi.getKey(),
false, class_ctx, member_class_ctx))
289 DLLLOCAL
int checkMemberAccessIntern(
const char* mem,
bool has_public_members,
const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx)
const {
290 assert(!member_class_ctx);
292 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
293 const QoreMemberInfo* info = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
295 return has_public_members ? QOA_PUB_ERROR : QOA_OK;
297 member_class_ctx = info->getClassContext(class_ctx);
298 return ((info->access > Public) && !class_ctx) ? QOA_PRIV_ERROR : QOA_OK;
302 DLLLOCAL
const QoreHashNode* getInternalData(
const qore_class_private* class_ctx)
const {
305 cdmap_t::const_iterator i = cdmap->find(class_ctx->getHash());
306 return i != cdmap->end() ? i->second :
nullptr;
310 DLLLOCAL
QoreHashNode* getInternalData(
const qore_class_private* class_ctx) {
313 cdmap_t::iterator i = cdmap->find(class_ctx->getHash());
314 return i != cdmap->end() ? i->second :
nullptr;
318 DLLLOCAL
QoreHashNode* getCreateInternalData(
const qore_class_private* class_ctx) {
320 cdmap_t::iterator i = cdmap->find(class_ctx->getHash());
321 if (i != cdmap->end())
327 cdmap->insert(cdmap_t::value_type(class_ctx->getHash(),
id));
332 DLLLOCAL
void copyInternalData(
const qore_object_private& old) {
338 for (
auto& i : *old.cdmap) {
339 cdmap->insert(cdmap_t::value_type(i.first, i.second->copy()));
345 DLLLOCAL
void setValueIntern(
const qore_class_private* class_ctx,
const char* key,
QoreValue val,
ExceptionSink* xsink);
347 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
348 const qore_class_private*& member_class_ctx)
const;
350 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
351 const qore_class_private*& member_class_ctx,
ExceptionSink* xsink)
const {
352 int rc = checkMemberAccess(mem, class_ctx, member_class_ctx);
357 if (rc == QOA_PRIV_ERROR) {
358 doPrivateException(mem, xsink);
360 doPublicException(mem, xsink);
365 DLLLOCAL
int checkMemberAccessGetTypeInfo(
ExceptionSink* xsink,
const char* mem,
const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx,
const QoreTypeInfo*& typeInfo)
const {
366 assert(!member_class_ctx);
367 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
368 const QoreMemberInfo* mi = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
370 if (mi->access > Public && !class_ctx) {
371 doPrivateException(mem, xsink);
375 member_class_ctx = mi->getClassContext(class_ctx);
376 typeInfo = mi->getTypeInfo();
382 doPublicException(mem, xsink);
390 DLLLOCAL
QoreValue takeMember(LValueHelper& lvh,
const char* mem);
392 DLLLOCAL
void takeMembers(QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l);
401 printd(5,
"qore_object_private::cleanup() this: %p privateData: %p\n",
this, privateData);
404 privateData =
nullptr;
408 td->clear(xsink,
true);
412 for (
auto& i : *cdm) {
413 i.second->clear(xsink,
true);
414 i.second->deref(xsink);
422 printd(5,
"qore_object_private::obliterate() obj: %p class: %s %d->%d\n", obj, theclass->
getName(), obj->references.load(), obj->references.load() - 1);
424 #ifdef QORE_DEBUG_OBJ_REFS
425 printd(QORE_DEBUG_OBJ_REFS,
"qore_object_private::obliterate() obj: %p class: %s: references %d->%d\n", obj, theclass->
getName(), obj->references.load(), obj->references.load() - 1);
430 if (--obj->references)
435 QoreSafeVarRWWriteLocker sl(rml);
437 if (in_destructor || status != OS_OK) {
438 printd(5,
"qore_object_private::obliterate() obj: %p data: %p in_destructor: %d status: %d\n", obj, data, in_destructor, status);
446 printd(5,
"qore_object_private::obliterate() obj: %p class: %s\n", obj, theclass->
getName());
449 cdmap_t* cdm = cdmap;
454 removeInvalidateRSetIntern();
460 privateData->derefAll(xsink);
462 cleanup(xsink, td, cdm);
467 DLLLOCAL
void doPrivateException(
const char* mem,
ExceptionSink* xsink)
const {
468 xsink->
raiseException(
"PRIVATE-MEMBER",
"'%s' is a private member of class '%s'", mem, theclass->
getName());
471 DLLLOCAL
void doPublicException(
const char* mem,
ExceptionSink* xsink)
const {
472 xsink->
raiseException(
"INVALID-MEMBER",
"'%s' is not a registered member of class '%s'", mem, theclass->
getName());
475 DLLLOCAL
virtual const char* getName()
const {
479 DLLLOCAL
virtual void deleteObject() {
483 DLLLOCAL
virtual bool isValidImpl()
const {
484 if (status != OS_OK || in_destructor) {
485 printd(QRO_LVL,
"qore_object_intern::isValidImpl() this: %p cannot delete graph obj status: %d in_destructor: %d\n",
this, status, in_destructor);
491 DLLLOCAL
virtual bool scanMembersIntern(RSetHelper& rsh,
QoreHashNode* odata);
493 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
496 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
497 assert(rml.hasRSectionLock());
498 printd(5,
"qore_object_private::needsScan() scan_count: %d scan_private_data: %d scan_now: %d\n",
499 getScanCount(), scan_private_data, scan_now);
502 if ((!getScanCount() && !scan_private_data) || status != OS_OK) {
509 if (!rrefs && scan_now) {
510 deferred_scan =
false;
518 deferred_scan =
true;
520 if (!rset && !scan_private_data) {
528 removeInvalidateRSetIntern();
542 privateData =
new KeyList;
544 printd(5,
"qore_object_private::setPrivate() this: %p 2:privateData: %p (%s) key: %d pd: %p\n",
this, privateData, theclass->
getName(), key, pd);
545 privateData->insert(key, pd);
546 addVirtualPrivateData(key, pd);
553 QoreSafeVarRWWriteLocker sl(rml);
554 return privateData ? privateData->getAndRemovePtr(key) :
nullptr;
564 DLLLOCAL
QoreValue& getMemberValueRefForInitialization(
const char* member,
const qore_class_private* class_ctx);
573 DLLLOCAL
void incScanCount(
int dt) {
575 assert(obj_count || dt > 0);
580 DLLLOCAL
unsigned getScanCount()
const {
584 DLLLOCAL VRMutex* getGate()
const {
602 DLLLOCAL
void customRefIntern(
bool real);
609 DLLLOCAL
int startCall(
const char* mname,
ExceptionSink* xsink);
616 DLLLOCAL
void setRealReference();
619 DLLLOCAL
void unsetRealReference();
621 DLLLOCAL
const char* getClassName()
const {
626 return obj.priv->evalBuiltinMethodWithPrivateData(method, meth, args, rtflags, xsink);
629 DLLLOCAL
static qore_object_private* get(
QoreObject& obj) {
633 DLLLOCAL
static const qore_object_private* get(
const QoreObject& obj) {
638 return obj.priv->takeMember(xsink, mem, check_access);
641 DLLLOCAL
static QoreValue takeMember(
QoreObject& obj, LValueHelper& lvh,
const char* mem) {
642 return obj.priv->takeMember(lvh, mem);
645 DLLLOCAL
static void takeMembers(
QoreObject& o, QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l) {
646 o.priv->takeMembers(rv, lvh, l);
649 DLLLOCAL
static int getLValue(
const QoreObject& obj,
const char* key, LValueHelper& lvh,
const qore_class_private* class_ctx,
bool for_remove,
ExceptionSink* xsink) {
650 return obj.priv->getLValue(key, lvh, class_ctx, for_remove, xsink);
654 return obj->priv->firstKey(xsink);
658 return obj->priv->lastKey(xsink);
661 DLLLOCAL
static unsigned getScanCount(
const QoreObject& o) {
662 return o.priv->getScanCount();
665 DLLLOCAL
static void incScanCount(
const QoreObject& o,
int dt) {
666 o.priv->incScanCount(dt);
670 class qore_object_lock_handoff_helper {
672 qore_object_private* pobj;
676 DLLLOCAL qore_object_lock_handoff_helper(qore_object_private* n_pobj,
AutoVLock& n_vl) : pobj(n_pobj), vl(n_vl) {
678 assert(vl.
getRWL() == &pobj->rml);
693 DLLLOCAL ~qore_object_lock_handoff_helper() {
702 DLLLOCAL
void stayLocked() {
703 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 QoreVarRWLock * getRWL() const
gets the current read-write lock
DLLLOCAL QoreObject * getObject() const
gets the current object
DLLLOCAL void set(QoreVarRWLock *n_rwl)
sets the current lock
constant iterator class for QoreHashNode, to be only created on the stack
Definition: QoreHashNode.h:577
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
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 * getLastKey() const
returns the cstring value of the last key in the hash
DLLEXPORT const char * getFirstKey() const
returns the cstring value of the first 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:135
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
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:654
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:275