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();
208 merge(*const_cast<QoreObject*>(reinterpret_cast<const QoreObject*>(v))->priv, vl, xsink);
210 merge(reinterpret_cast<const QoreHashNode*>(v), vl, xsink);
221 DLLLOCAL
int getLValue(
const char* key, LValueHelper& lvh,
const qore_class_private* class_ctx,
bool for_remove,
ExceptionSink* xsink);
225 const qore_class_private* class_ctx = runtime_get_class();
226 if (class_ctx && !qore_class_private::runtimeCheckPrivateClassAccess(*theclass, class_ctx))
229 QoreAutoVarRWReadLocker al(rml);
231 if (status == OS_DELETED) {
232 makeAccessDeletedObjectException(xsink, theclass->
getName());
246 const qore_class_private* member_class_ctx =
nullptr;
247 if (!checkMemberAccessIntern(hi.getKey(),
false, class_ctx, member_class_ctx))
257 const qore_class_private* class_ctx = runtime_get_class();
258 if (class_ctx && !qore_class_private::runtimeCheckPrivateClassAccess(*theclass, class_ctx))
261 QoreAutoVarRWReadLocker al(rml);
263 if (status == OS_DELETED) {
264 makeAccessDeletedObjectException(xsink, theclass->
getName());
276 const qore_class_private* member_class_ctx =
nullptr;
277 if (!checkMemberAccessIntern(hi.getKey(),
false, class_ctx, member_class_ctx))
286 DLLLOCAL
int checkMemberAccessIntern(
const char* mem,
bool has_public_members,
const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx)
const {
287 assert(!member_class_ctx);
289 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
290 const QoreMemberInfo* info = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
292 return has_public_members ? QOA_PUB_ERROR : QOA_OK;
294 member_class_ctx = info->getClassContext(class_ctx);
295 return ((info->access > Public) && !class_ctx) ? QOA_PRIV_ERROR : QOA_OK;
299 DLLLOCAL
const QoreHashNode* getInternalData(
const qore_class_private* class_ctx)
const {
302 cdmap_t::const_iterator i = cdmap->find(class_ctx->getHash());
303 return i != cdmap->end() ? i->second :
nullptr;
307 DLLLOCAL
QoreHashNode* getInternalData(
const qore_class_private* class_ctx) {
310 cdmap_t::iterator i = cdmap->find(class_ctx->getHash());
311 return i != cdmap->end() ? i->second :
nullptr;
315 DLLLOCAL
QoreHashNode* getCreateInternalData(
const qore_class_private* class_ctx) {
317 cdmap_t::iterator i = cdmap->find(class_ctx->getHash());
318 if (i != cdmap->end())
324 cdmap->insert(cdmap_t::value_type(class_ctx->getHash(), id));
329 DLLLOCAL
void copyInternalData(
const qore_object_private& old) {
335 for (
auto& i : *old.cdmap) {
336 cdmap->insert(cdmap_t::value_type(i.first, i.second->copy()));
342 DLLLOCAL
void setValueIntern(
const qore_class_private* class_ctx,
const char* key,
QoreValue val,
ExceptionSink* xsink);
344 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx)
const {
345 assert(!member_class_ctx);
347 const qore_class_private* theclass_priv = qore_class_private::get(*theclass);
348 const QoreMemberInfo* info = theclass_priv->runtimeGetMemberInfo(mem, class_ctx);
350 return theclass->runtimeHasPublicMembersInHierarchy() ? QOA_PUB_ERROR : QOA_OK;
352 member_class_ctx = info->getClassContext(class_ctx);
353 return ((info->access > Public) && !class_ctx) ? QOA_PRIV_ERROR : QOA_OK;
356 DLLLOCAL
int checkMemberAccess(
const char* mem,
const qore_class_private* class_ctx,
const qore_class_private*& member_class_ctx,
ExceptionSink* xsink)
const {
357 int rc = checkMemberAccess(mem, class_ctx, member_class_ctx);
362 if (rc == QOA_PRIV_ERROR) {
363 doPrivateException(mem, xsink);
366 doPublicException(mem, xsink);
371 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 {
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();
387 if (theclass->runtimeHasPublicMembersInHierarchy()) {
388 doPublicException(mem, xsink);
396 DLLLOCAL
QoreValue takeMember(LValueHelper& lvh,
const char* mem);
398 DLLLOCAL
void takeMembers(QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l);
404 printd(5,
"qore_object_private::doDeleteIntern() execing destructor() obj: %p\n", obj);
412 theclass->execDestructor(obj, xsink);
417 QoreAutoVarRWWriteLocker al(rml);
418 assert(status != OS_DELETED);
428 removeInvalidateRSetIntern();
431 cleanup(xsink, td, cdm);
438 printd(5,
"qore_object_private::cleanup() this: %p privateData: %p\n",
this, privateData);
441 privateData =
nullptr;
445 td->clear(xsink,
true);
449 for (
auto& i : *cdm) {
450 i.second->clear(xsink,
true);
451 i.second->deref(xsink);
459 printd(5,
"qore_object_private::obliterate() obj: %p class: %s %d->%d\n", obj, theclass->
getName(), obj->references.load(), obj->references.load() - 1);
461 #ifdef QORE_DEBUG_OBJ_REFS 462 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);
467 if (--obj->references)
472 QoreSafeVarRWWriteLocker sl(rml);
474 if (in_destructor || status != OS_OK) {
475 printd(5,
"qore_object_private::obliterate() obj: %p data: %p in_destructor: %d status: %d\n", obj, data, in_destructor, status);
483 printd(5,
"qore_object_private::obliterate() obj: %p class: %s\n", obj, theclass->
getName());
486 cdmap_t* cdm = cdmap;
491 removeInvalidateRSetIntern();
497 privateData->derefAll(xsink);
499 cleanup(xsink, td, cdm);
504 DLLLOCAL
void doPrivateException(
const char* mem,
ExceptionSink* xsink)
const {
505 xsink->
raiseException(
"PRIVATE-MEMBER",
"'%s' is a private member of class '%s'", mem, theclass->
getName());
508 DLLLOCAL
void doPublicException(
const char* mem,
ExceptionSink* xsink)
const {
509 xsink->
raiseException(
"INVALID-MEMBER",
"'%s' is not a registered member of class '%s'", mem, theclass->
getName());
512 DLLLOCAL
virtual const char* getName()
const {
516 DLLLOCAL
virtual void deleteObject() {
520 DLLLOCAL
virtual bool isValidImpl()
const {
521 if (status != OS_OK || in_destructor) {
522 printd(QRO_LVL,
"qore_object_intern::isValidImpl() this: %p cannot delete graph obj status: %d in_destructor: %d\n",
this, status, in_destructor);
528 DLLLOCAL
virtual bool scanMembersIntern(RSetHelper& rsh,
QoreHashNode* odata);
530 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
533 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
534 assert(rml.hasRSectionLock());
535 printd(5,
"qore_object_private::needsScan() scan_count: %d scan_private_data: %d scan_now: %d\n",
536 getScanCount(), scan_private_data, scan_now);
539 if ((!getScanCount() && !scan_private_data) || status != OS_OK) {
546 if (!rrefs && scan_now) {
547 deferred_scan =
false;
555 deferred_scan =
true;
557 if (!rset && !scan_private_data) {
565 removeInvalidateRSetIntern();
579 privateData =
new KeyList;
581 privateData->insert(key, pd);
582 addVirtualPrivateData(key, pd);
592 BCSMList* sml = qc->getBCSMList();
597 for (class_list_t::const_iterator i = sml->begin(), e = sml->end(); i != e; ++i) {
600 privateData->insertVirtual(i->first->getID(), apd);
605 QoreSafeVarRWWriteLocker sl(rml);
606 return privateData ? privateData->getAndRemovePtr(key) :
nullptr;
616 DLLLOCAL
QoreValue& getMemberValueRefForInitialization(
const char* member,
const qore_class_private* class_ctx);
625 DLLLOCAL
void incScanCount(
int dt) {
627 assert(obj_count || dt > 0);
632 DLLLOCAL
unsigned getScanCount()
const {
636 DLLLOCAL VRMutex* getGate()
const {
654 DLLLOCAL
void customRefIntern(
bool real);
661 DLLLOCAL
int startCall(
const char* mname,
ExceptionSink* xsink);
668 DLLLOCAL
void setRealReference();
671 DLLLOCAL
void unsetRealReference();
673 DLLLOCAL
const char* getClassName()
const {
678 return obj.priv->evalBuiltinMethodWithPrivateData(method, meth, args, rtflags, xsink);
681 DLLLOCAL
static qore_object_private*
get(
QoreObject& obj) {
685 DLLLOCAL
static const qore_object_private*
get(
const QoreObject& obj) {
690 return obj.priv->takeMember(xsink, mem, check_access);
693 DLLLOCAL
static QoreValue takeMember(
QoreObject& obj, LValueHelper& lvh,
const char* mem) {
694 return obj.priv->takeMember(lvh, mem);
697 DLLLOCAL
static void takeMembers(
QoreObject& o, QoreLValueGeneric& rv, LValueHelper& lvh,
const QoreListNode* l) {
698 o.priv->takeMembers(rv, lvh, l);
701 DLLLOCAL
static int getLValue(
const QoreObject& obj,
const char* key, LValueHelper& lvh,
const qore_class_private* class_ctx,
bool for_remove,
ExceptionSink* xsink) {
702 return obj.priv->getLValue(key, lvh, class_ctx, for_remove, xsink);
706 obj->priv->plusEquals(v, vl, xsink);
710 return obj->priv->firstKey(xsink);
714 return obj->priv->lastKey(xsink);
717 DLLLOCAL
static unsigned getScanCount(
const QoreObject& o) {
718 return o.priv->getScanCount();
721 DLLLOCAL
static void incScanCount(
const QoreObject& o,
int dt) {
722 o.priv->incScanCount(dt);
726 class qore_object_lock_handoff_helper {
728 qore_object_private* pobj;
732 DLLLOCAL qore_object_lock_handoff_helper(qore_object_private* n_pobj,
AutoVLock& n_vl) : pobj(n_pobj), vl(n_vl) {
734 assert(vl.
getRWL() == &pobj->rml);
749 DLLLOCAL ~qore_object_lock_handoff_helper() {
758 DLLLOCAL
void stayLocked() {
759 vl.
set(pobj->obj, &pobj->rml);
DLLEXPORT QoreClass * getClass(qore_classid_t cid) const
returns a pointer to the QoreClass object representing the class ID passed if it exists in the class ...
AutoVLock is a container for safely managing global variable and object lock handovers, required for functions accessing global variables and object data where locking is necessary.
Definition: AutoVLock.h:80
DLLLOCAL qore_type_t getType() const
returns the data type
Definition: AbstractQoreNode.h:172
This is the hash or associative list container type in Qore, dynamically allocated only...
Definition: QoreHashNode.h:50
the base class for all data to be used as private data of Qore objects
Definition: AbstractPrivateData.h:44
DLLEXPORT int sprintf(const char *fmt,...)
this will concatentate a formatted string to the existing string according to the format string and t...
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
const qore_type_t NT_OBJECT
type value for QoreObject
Definition: node_types.h:52
DLLEXPORT const char * getFirstKey() const
returns the cstring value of the first key in the hash
uint64_t q_rt_flags_t
runtime code execution flags
Definition: common.h:263
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
DLLEXPORT void del()
manually releases the lock currently held
DLLLOCAL void set(QoreVarRWLock *n_rwl)
sets the current lock
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack...
Definition: QoreThreadLock.h:128
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
defines a Qore-language class
Definition: QoreClass.h:239
const qore_type_t NT_HASH
type value for QoreHashNode
Definition: node_types.h:51
DLLLOCAL void clear()
leaves the lock locked and the object referenced and clears the object and lock pointers ...
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only ...
Definition: QoreProgram.h:126
the implementation of Qore's object data type, reference counted, dynamically-allocated only ...
Definition: QoreObject.h:61
DLLLOCAL QoreObject * getObject() const
gets the current object
unsigned qore_classid_t
used for the unique class ID for QoreClass objects
Definition: common.h:79
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
reverse constant iterator class for QoreHashNode, to be only created on the stack ...
Definition: QoreHashNode.h:640
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false, otherwise does nothing
DLLLOCAL void ref()
increments the reference count of the object
Definition: AbstractPrivateData.h:53
DLLEXPORT const char * getLastKey() const
returns the cstring value of the last key in the hash
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:563
a method in a QoreClass
Definition: QoreClass.h:125
DLLEXPORT const char * getName() const
returns the class name