Skip to content

Commit 3f116d0

Browse files
committed
refs #4909 improvied the weak assignment operator to create weak references to hashes and lists
1 parent d60d2cc commit 3f116d0

36 files changed

+1010
-413
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,8 @@ set(LIBQORE_CPP_SRC
507507
lib/ThreadClosureVariableStack.cpp
508508
lib/ThreadLocalVariableData.cpp
509509
lib/WeakReferenceNode.cpp
510+
lib/WeakListReferenceNode.cpp
511+
lib/WeakHashReferenceNode.cpp
510512
lib/QoreProgram.cpp
511513
lib/QoreProgramHelper.cpp
512514
lib/QoreNamespace.cpp

Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,8 @@ noinst_HEADERS = \
867867
include/qore/intern/QoreHashListIterator.h \
868868
include/qore/intern/QoreListHashIterator.h \
869869
include/qore/intern/WeakReferenceNode.h \
870+
include/qore/intern/WeakHashReferenceNode.h \
871+
include/qore/intern/WeakListReferenceNode.h \
870872
include/qore/intern/SingleValueIterator.h \
871873
include/qore/intern/RangeIterator.h \
872874
include/qore/intern/ThreadPool.h \

doxygen/lang/900_release_notes.dox.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@
102102
(<a href="https://github.com/qorelanguage/qore/issues/4825">issue 4825</a>)
103103
- fixed a bug where any additionalProperties would cause all properties to be accepted
104104
(<a href="https://github.com/qorelanguage/qore/issues/4823">issue 4823</a>)
105+
- improved the weak assignment operator to allow weak references to hashes and list containers
106+
(<a href="https://github.com/qorelanguage/qore/issues/4909">issue 4909</a>)
105107
- fixed a bug in deterministic garbage collection with class copy() methods
106108
(<a href="https://github.com/qorelanguage/qore/issues/4905">issue 4905</a>)
107109
- fixed a bug where %Qore would raise recusive constant exceptions when parsing in cases where values were not in

include/qore/QoreHashNode.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,18 @@ class QoreHashNode : public AbstractQoreNode {
389389

390390
static const qore_type_t TYPE = NT_HASH;
391391

392+
//! Increments the weak reference count for this object
393+
/** @since %Qore 2.0
394+
*/
395+
DLLEXPORT void weakRef();
396+
397+
//! Decrements the weak reference count for this object
398+
/** @return if \c true then the object was deleted
399+
400+
@since %Qore 2.0
401+
*/
402+
DLLEXPORT bool weakDeref();
403+
392404
//! initializes during parsing
393405
DLLLOCAL virtual int parseInit(QoreValue& val, QoreParseContext& parse_context);
394406

include/qore/QoreListNode.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,18 @@ class QoreListNode : public AbstractQoreNode {
412412
*/
413413
DLLEXPORT const QoreTypeInfo* getTypeInfo() const;
414414

415+
//! Increments the weak reference count for this object
416+
/** @since %Qore 2.0
417+
*/
418+
DLLEXPORT void weakRef();
419+
420+
//! Decrements the weak reference count for this object
421+
/** @return if \c true then the object was deleted
422+
423+
@since %Qore 2.0
424+
*/
425+
DLLEXPORT bool weakDeref();
426+
415427
// needed only while parsing
416428
//! this function is not exported in the qore library
417429
DLLLOCAL QoreListNode(bool i);

include/qore/QoreValue.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -643,28 +643,28 @@ class ValueEvalRefHolder : public ValueOptionalRefHolder {
643643

644644
//! creates the object with with no evaluation
645645
/** @since %Qore 0.8.13.1
646-
*/
646+
*/
647647
DLLEXPORT ValueEvalRefHolder(ExceptionSink* xs);
648648

649649
//! evaluates the argument, returns -1 for error, 0 = OK
650650
/** @since %Qore 0.8.13.1
651-
*/
651+
*/
652652
DLLEXPORT int eval(const AbstractQoreNode* exp);
653653

654654
//! evaluates the argument, returns -1 for error, 0 = OK
655655
/** @since %Qore 0.9
656-
*/
656+
*/
657657
DLLEXPORT int eval(const QoreValue exp);
658658

659659
protected:
660660
//! evaluates the argument, returns -1 for error, 0 = OK
661661
/** @since %Qore 0.8.13.1
662-
*/
662+
*/
663663
DLLLOCAL int evalIntern(const AbstractQoreNode* exp);
664664

665665
//! evaluates the argument, returns -1 for error, 0 = OK
666666
/** @since %Qore 0.9
667-
*/
667+
*/
668668
DLLLOCAL int evalIntern(const QoreValue& exp);
669669
};
670670

include/qore/intern/LocalVar.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "qore/intern/RSet.h"
4040
#include "qore/ReferenceNode.h"
4141
#include "qore/intern/WeakReferenceNode.h"
42+
#include "qore/intern/WeakHashReferenceNode.h"
43+
#include "qore/intern/WeakListReferenceNode.h"
4244

4345
#include <atomic>
4446

@@ -184,6 +186,16 @@ class LocalVarValue : public VarValueBase {
184186
return val.get<WeakReferenceNode>()->get();
185187
}
186188

189+
if (val.getType() == NT_WEAKREF_HASH) {
190+
needs_deref = false;
191+
return val.get<WeakHashReferenceNode>()->get();
192+
}
193+
194+
if (val.getType() == NT_WEAKREF_LIST) {
195+
needs_deref = false;
196+
return val.get<WeakListReferenceNode>()->get();
197+
}
198+
187199
return val.getReferencedValue(needs_deref);
188200
}
189201

@@ -202,6 +214,14 @@ class LocalVarValue : public VarValueBase {
202214
return val.get<WeakReferenceNode>()->get()->refSelf();
203215
}
204216

217+
if (val.getType() == NT_WEAKREF_HASH) {
218+
return val.get<WeakHashReferenceNode>()->get()->refSelf();
219+
}
220+
221+
if (val.getType() == NT_WEAKREF_LIST) {
222+
return val.get<WeakListReferenceNode>()->get()->refSelf();
223+
}
224+
205225
return val.getReferencedValue();
206226
}
207227
};
@@ -275,6 +295,16 @@ struct ClosureVarValue : public VarValueBase, public RObject {
275295
return val.get<WeakReferenceNode>()->get();
276296
}
277297

298+
if (val.getType() == NT_WEAKREF_HASH) {
299+
needs_deref = false;
300+
return val.get<WeakHashReferenceNode>()->get();
301+
}
302+
303+
if (val.getType() == NT_WEAKREF_LIST) {
304+
needs_deref = false;
305+
return val.get<WeakListReferenceNode>()->get();
306+
}
307+
278308
return val.getReferencedValue();
279309
}
280310

@@ -291,6 +321,14 @@ struct ClosureVarValue : public VarValueBase, public RObject {
291321
return val.get<WeakReferenceNode>()->get()->refSelf();
292322
}
293323

324+
if (val.getType() == NT_WEAKREF_HASH) {
325+
return val.get<WeakHashReferenceNode>()->get();
326+
}
327+
328+
if (val.getType() == NT_WEAKREF_LIST) {
329+
return val.get<WeakListReferenceNode>()->get();
330+
}
331+
294332
return val.getReferencedValue();
295333
}
296334

include/qore/intern/ParseNode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define _QORE_PARSENODE_H
3535

3636
#include "qore/intern/WeakReferenceNode.h"
37+
#include "qore/intern/WeakHashReferenceNode.h"
38+
#include "qore/intern/WeakListReferenceNode.h"
3739

3840
class ParseNode : public SimpleQoreNode {
3941
public:

include/qore/intern/QoreAssignmentOperatorNode.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
class QoreAssignmentOperatorNode : public QoreBinaryLValueOperatorNode {
3636
OP_COMMON
3737
public:
38-
DLLLOCAL QoreAssignmentOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : QoreBinaryLValueOperatorNode(loc, left, right) {
38+
DLLLOCAL QoreAssignmentOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) :
39+
QoreBinaryLValueOperatorNode(loc, left, right) {
3940
}
4041

4142
DLLLOCAL virtual QoreOperatorNode* copyBackground(ExceptionSink* xsink) const {

include/qore/intern/QoreHashNodeIntern.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,11 @@ class qore_hash_private {
124124
const TypedHashDecl* hashdecl = nullptr;
125125
const QoreTypeInfo* complexTypeInfo = nullptr;
126126
unsigned obj_count = 0;
127+
QoreReferenceCounter weakRefs;
127128
#ifdef DEBUG
128129
bool is_obj = false;
129130
#endif
131+
bool valid = true;
130132

131133
DLLLOCAL qore_hash_private() {
132134
}
@@ -137,6 +139,14 @@ class qore_hash_private {
137139
assert(member_list.empty());
138140
}
139141

142+
DLLLOCAL int checkValid(ExceptionSink* xsink) {
143+
if (!valid) {
144+
xsink->raiseException("HASH-ERROR", "Cannot modify a hash that has already gone out of scope");
145+
return -1;
146+
}
147+
return 0;
148+
}
149+
140150
DLLLOCAL QoreValue getKeyValueIntern(const char* key) const;
141151

142152
DLLLOCAL QoreValue getKeyValueExistence(const char* key, bool& exists, ExceptionSink* xsink) const;
@@ -478,6 +488,7 @@ class qore_hash_private {
478488
member_list.clear();
479489
hm.clear();
480490
obj_count = 0;
491+
valid = false;
481492
return true;
482493
}
483494

@@ -534,6 +545,17 @@ class qore_hash_private {
534545
return hashdecl;
535546
}
536547

548+
DLLLOCAL void weakRef() {
549+
weakRefs.ROreference();
550+
}
551+
552+
DLLLOCAL bool weakDeref() {
553+
if (weakRefs.ROdereference()) {
554+
return true;
555+
}
556+
return false;
557+
}
558+
537559
DLLLOCAL static QoreHashNode* getPlainHash(QoreHashNode* h) {
538560
if (!h->priv->hashdecl && !h->priv->complexTypeInfo)
539561
return h;

0 commit comments

Comments
 (0)