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, delete_blocker_run, 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,
const qore_class_private*& member_class_ctx)
const {
348 assert(!member_class_ctx);
350 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
351 const QoreMemberInfo* info = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
353 return theclass->runtimeHasPublicMembersInHierarchy() ? QOA_PUB_ERROR : QOA_OK;
355 member_class_ctx = info->getClassContext(class_ctx);
356 return ((info->access > Public) && !class_ctx) ? QOA_PRIV_ERROR : QOA_OK;
359 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx,
ExceptionSink* xsink)
const {
360 int rc = checkMemberAccess(mem, class_ctx, member_class_ctx);
365 if (rc == QOA_PRIV_ERROR) {
366 doPrivateException(mem, xsink);
368 doPublicException(mem, xsink);
373 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 {
374 assert(!member_class_ctx);
375 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
376 const QoreMemberInfo* mi = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
378 if (mi->access > Public && !class_ctx) {
379 doPrivateException(mem, xsink);
383 member_class_ctx = mi->getClassContext(class_ctx);
384 typeInfo = mi->getTypeInfo();
389 if (theclass->runtimeHasPublicMembersInHierarchy()) {
390 doPublicException(mem, xsink);
398 DLLLOCAL
QoreValue takeMember(LValueHelper& lvh,
const char* mem);
400 DLLLOCAL
void takeMembers(QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l);
406 printd(5,
"qore_object_private::doDeleteIntern() execing destructor() obj: %p\n", obj);
414 theclass->execDestructor(obj, xsink);
419 QoreAutoVarRWWriteLocker al(rml);
420 assert(status != OS_DELETED);
430 removeInvalidateRSetIntern();
433 cleanup(xsink, td, cdm);
440 printd(5,
"qore_object_private::cleanup() this: %p privateData: %p\n",
this, privateData);
443 privateData =
nullptr;
447 td->clear(xsink,
true);
451 for (
auto& i : *cdm) {
452 i.second->clear(xsink,
true);
453 i.second->deref(xsink);
461 printd(5,
"qore_object_private::obliterate() obj: %p class: %s %d->%d\n", obj, theclass->
getName(), obj->references.load(), obj->references.load() - 1);
463 #ifdef QORE_DEBUG_OBJ_REFS
464 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);
469 if (--obj->references)
474 QoreSafeVarRWWriteLocker sl(rml);
476 if (in_destructor || status != OS_OK) {
477 printd(5,
"qore_object_private::obliterate() obj: %p data: %p in_destructor: %d status: %d\n", obj, data, in_destructor, status);
485 printd(5,
"qore_object_private::obliterate() obj: %p class: %s\n", obj, theclass->
getName());
488 cdmap_t* cdm = cdmap;
493 removeInvalidateRSetIntern();
499 privateData->derefAll(xsink);
501 cleanup(xsink, td, cdm);
506 DLLLOCAL
void doPrivateException(
const char* mem,
ExceptionSink* xsink)
const {
507 xsink->
raiseException(
"PRIVATE-MEMBER",
"'%s' is a private member of class '%s'", mem, theclass->
getName());
510 DLLLOCAL
void doPublicException(
const char* mem,
ExceptionSink* xsink)
const {
511 xsink->
raiseException(
"INVALID-MEMBER",
"'%s' is not a registered member of class '%s'", mem, theclass->
getName());
514 DLLLOCAL
virtual const char* getName()
const {
518 DLLLOCAL
virtual void deleteObject() {
522 DLLLOCAL
virtual bool isValidImpl()
const {
523 if (status != OS_OK || in_destructor) {
524 printd(QRO_LVL,
"qore_object_intern::isValidImpl() this: %p cannot delete graph obj status: %d in_destructor: %d\n",
this, status, in_destructor);
530 DLLLOCAL
virtual bool scanMembersIntern(RSetHelper& rsh,
QoreHashNode* odata);
532 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
535 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
536 assert(rml.hasRSectionLock());
537 printd(5,
"qore_object_private::needsScan() scan_count: %d scan_private_data: %d scan_now: %d\n",
538 getScanCount(), scan_private_data, scan_now);
541 if ((!getScanCount() && !scan_private_data) || status != OS_OK) {
548 if (!rrefs && scan_now) {
549 deferred_scan =
false;
557 deferred_scan =
true;
559 if (!rset && !scan_private_data) {
567 removeInvalidateRSetIntern();
581 privateData =
new KeyList;
583 printd(5,
"qore_object_private::setPrivate() this: %p 2:privateData: %p (%s) key: %d pd: %p\n",
this, privateData, theclass->
getName(), key, pd);
584 privateData->insert(key, pd);
585 addVirtualPrivateData(key, pd);
595 BCSMList* sml = qc->getBCSMList();
600 for (class_list_t::const_iterator i = sml->begin(), e = sml->end(); i != e; ++i) {
603 privateData->insertVirtual(i->first->getID(), apd);
608 QoreSafeVarRWWriteLocker sl(rml);
609 return privateData ? privateData->getAndRemovePtr(key) :
nullptr;
619 DLLLOCAL
QoreValue& getMemberValueRefForInitialization(
const char* member,
const qore_class_private* class_ctx);
628 DLLLOCAL
void incScanCount(
int dt) {
630 assert(obj_count || dt > 0);
635 DLLLOCAL
unsigned getScanCount()
const {
639 DLLLOCAL VRMutex* getGate()
const {
657 DLLLOCAL
void customRefIntern(
bool real);
664 DLLLOCAL
int startCall(
const char* mname,
ExceptionSink* xsink);
671 DLLLOCAL
void setRealReference();
674 DLLLOCAL
void unsetRealReference();
676 DLLLOCAL
const char* getClassName()
const {
681 return obj.priv->evalBuiltinMethodWithPrivateData(method, meth, args, rtflags, xsink);
684 DLLLOCAL
static qore_object_private* get(
QoreObject& obj) {
688 DLLLOCAL
static const qore_object_private* get(
const QoreObject& obj) {
693 return obj.priv->takeMember(xsink, mem, check_access);
696 DLLLOCAL
static QoreValue takeMember(
QoreObject& obj, LValueHelper& lvh,
const char* mem) {
697 return obj.priv->takeMember(lvh, mem);
700 DLLLOCAL
static void takeMembers(
QoreObject& o, QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l) {
701 o.priv->takeMembers(rv, lvh, l);
704 DLLLOCAL
static int getLValue(
const QoreObject& obj,
const char* key, LValueHelper& lvh,
const qore_class_private* class_ctx,
bool for_remove,
ExceptionSink* xsink) {
705 return obj.priv->getLValue(key, lvh, class_ctx, for_remove, xsink);
709 return obj->priv->firstKey(xsink);
713 return obj->priv->lastKey(xsink);
716 DLLLOCAL
static unsigned getScanCount(
const QoreObject& o) {
717 return o.priv->getScanCount();
720 DLLLOCAL
static void incScanCount(
const QoreObject& o,
int dt) {
721 o.priv->incScanCount(dt);
725 class qore_object_lock_handoff_helper {
727 qore_object_private* pobj;
731 DLLLOCAL qore_object_lock_handoff_helper(qore_object_private* n_pobj,
AutoVLock& n_vl) : pobj(n_pobj), vl(n_vl) {
733 assert(vl.
getRWL() == &pobj->rml);
748 DLLLOCAL ~qore_object_lock_handoff_helper() {
757 DLLLOCAL
void stayLocked() {
758 vl.
set(pobj->obj, &pobj->rml);