qt5 proxy model updating too soon before main model update is done - qt5

I have a setup with a main model (QStandardModel), a proxy model which changes the output of the DisplayRole, and a separate tableview displaying each model. Inside the main model data is a user role that stores a pointer to another QObject which is used by the proxy model to get the desired display value.
I'm running into problems when the object pointed to by that variable is deleted. I am handling deletion in the main model via the destroyed(QObject*) signal. Inside the slot, I search through the model looking for any items that are pointing to the object and delete the reference.
That part works fine on its own but I also have connected to the onDataChanged(...) signal of the proxy model, where I call resizeColumnsToContents() on the proxy model. This then calls the proxy's data() function. Here I check to see if the item has a pointer and, if it does, get some information from the object for display.
The result of all this becomes:
Object about to be deleted triggers destroyed(...) signal
Main model looks for any items using the deleted object and calls setData to remove the reference
Tableview catches onDataChanged signal for the proxy model and resizes columns
Proxy model's data(...) is called. It checks if the item in the main model has the object pointer and, if so, displays a value from the object. If not, it displays something else.
The problem is, at step 4 the item from the main model apparently still hasn't been deleted; the pointer address is still stored. The object the pointer was referencing, though, has been deleted by this point resulting in a segfault.
How can I fix my setup to make sure the main model is finished deleting pointer references before the proxy model tries to update?
Also, here is pseudo-code for the relevant sections:
// elsewhere
Object *someObject = new QObject();
QModelIndex index = mainModel->index(0,0);
mainModel->setData(index, someObject, ObjectPtrRole);
// do stuff
delete someObject; // Qt is actually doing this, I'm not doing it explicitly
// MainModel
void MainModel::onObjectDestroyed(QObject *obj)
{
// iterating over all model items
// if item has pointer to obj
item->setData(QVariant::fromValue(NULL), ObjectPtrRole));
}
// receives onDataChanged signal
void onProxyModelDataChanged(...)
{
ui->tblProxyView->reseizeColumnsToContents();
}
void ProxyModel::data(const QModelIndex &index, int role) const
{
QModelIndex srcIndex = mapToSource(index);
if(role == Qt::DisplayRole)
{
QVariant v = sourceModel()->data(srcIndex, ObjectPtrRole);
Object *ptr = qvariant_cast<Object*>(v);
if(ptr != NULL)
return ptr->getDisplayData();
else
return sourceModel->data(srcIndex, role);
}
}
The problem is ptr is not NULL, but the referenced object is deleted, at the time ProxyModel::data(...) is called so I end up with a segfault.

To avoid dangling pointer dereferences with instances of QObject, you can do one of two things:
Use object->deleteLater - the object will be deleted once the control returns to the event loop. Such functionality is also known as autorelease pools.
Use a QPointer. It will set itself to null upon deletion of the object, so you can check it before use.

Related

Save LinkedList to Parse Server

I'm trying to build a Single Linked List using Parse PFObjects. Each PFObject has a pointer to the next object in the list. I can pin them locally, but I'm having an issue when saving them to Parse Server.
The problem start here:
+ (BFTask *)_deepSaveAsyncChildrenOfObject:(id)object withCurrentUser:(PFUser *)currentUser sessionToken:(NSString *)sessionToken;
// This saves all of the objects and files reachable from the given object.
// It does its work in multiple waves, saving as many as possible in each wave.
// If there's ever an error, it just gives up, sets error, and returns NO;
When trying to save the first object in the list, it will access the child (next object) and try to save that one first. As the child (next object) has also a pointer to the next object in list, this will keep happening until the last object in the list.
This succeeds for small amount of objects (<200) but once we are handling linked list with large amounts of objects, there is a crash in here:
/**
Finds all of the objects that are reachable from child, including child itself,
and adds them to the given mutable array. It traverses arrays and json objects.
#param node An kind object to search for children.
#param dirtyChildren The array to collect the result into.
#param seen The set of all objects that have already been seen.
#param seenNew The set of new objects that have already been seen since the
last existing object.
*/
+ (BOOL)collectDirtyChildren:(id)node
children:(NSMutableSet *)dirtyChildren
files:(NSMutableSet *)dirtyFiles
seen:(NSSet *)seen
seenNew:(NSSet *)seenNew
currentUser:(PFUser *)currentUser
error:(NSError * __autoreleasing *)error
This method is called by deepSaveAsyncChildrenOfObject to build a NSSet of the children objects that must be saved too.
#synchronized ([object lock]) {
// Check for cycles of new objects. Any such cycle means it will be
// impossible to save this collection of objects, so throw an exception.
if (object.objectId) {
seenNew = [NSSet set];
} else {
if ([seenNew containsObject:object] && error) {
*error = [PFErrorUtilities errorWithCode:kPFErrorInvalidPointer
message:#"Found a circular dependency when saving."];
return NO;
}
// 🚨CRASH: Thread 160: EXC_BAD_ACCESS (code=2, address=0x70000fc80f38)
seenNew = [seenNew setByAddingObject:object];
}
// Check for cycles of any object. If this occurs, then there's no
// problem, but we shouldn't recurse any deeper, because it would be
// an infinite recursion.
if ([seen containsObject:object]) {
return YES;
}
seen = [seen setByAddingObject:object];
// Recurse into this object's children looking for dirty children.
// We only need to look at the child object's current estimated data,
// because that's the only data that might need to be saved now.
toSearch = [object._estimatedData.dictionaryRepresentation copy];
}
So, this could be avoided by saving the PFObjects without saving its children, is there any way to do this? Or is there any workaround to save linked lists to Parse Server, maybe by using Cloud Code, or modifying the data model?

How can one set up persistent collaborating objects in DigitalMicrograph via scripting?

I have come to really appreciate the benefits of using objects to deploy a given application within the DigitalMicrograph environment via the DMS language. The object-oriented approach opens the door to the use of reusable design patterns involving collaborating objects, e.g. Model-View-Controller (MVC). However, objects within DM seem to be highly volatile due to the use of automatic reference counting to manage their life cycles. In order for an MVC trio, or any other set of collaborating objects, to stay alive long enough to be useful, at least one of them must be rooted in a non-volatile object managed by the DM application. So far, the only such objects I have come across within DM are those based on the UIFrame class (i.e. modeless dialogs and UI palettes). For MVC implementations, this works out fine since it makes sense to implement the View as a UIFrame object. It's just a bit unconventional in that the View object becomes the root object that keeps the MVC trio alive and functioning. Normally it is the Controller object that is rooted in the application and manages the Model and View objects. But what about design patterns that do not involve UI? Is there any (acceptable) way to give a set of collaborating objects persistence without rooting them in a UIFrame object? Are there other application-rooted object types that can serve this purpose? I assume setting up a reference cycle would not be an acceptable approach due to the inevitable risk of memory leaks.
The third, and by far the best and cleanest solution is to launch your object as a 'listener' to some event. As you are looking for an object which should stay in scope as long as DigitalMicrograph is open, its possibly best to listen to the application itself. By listening for the "about_to_close" message you also get the ideal handle to properly release all resources before shutdown. The code is the following:
From my 3 answers this is the one I would use. (The others should just illustrate options.)
class MyPermanentObject
{
MyPermanentObject( object self ) { result("created MyPermanentObject :"+self.ScriptObjectGetID()+"\n");}
~MyPermanentObject( object self ) { result("killed MyPermanentObject :"+self.ScriptObjectGetID()+"\n");}
void DeInitialize( object self, number eventFlags, object appObj )
{
OKDialog( "The application is closing now. Deinitialize stuff properly!" );
}
}
{
object listener = Alloc( MyPermanentObject )
ApplicationAddEventListener( listener, "application_about_to_close:DeInitialize" )
}
I can think of various ways to get this persistence, but the one which jumped to mind first was to launch one object into a background thread, like in the example below. The actual background thread can check every so often if the object should still remain, and by sharing the object ID with the outside world, other objects (which don't have to be persistent) can access the "anchored" object.
A word of warning though: If you keep things in memory like this, you have to be careful when closing DigitalMicrograph. If the object hangs on to some items DM wants to destroy, you might see errors or crashes at the end.
// This is the object "anchored". It will remain in memory, because we launch it on a separate thread.
// On this thread, it loops until a variable is set to false (or until SHIFT is pressed)
Class IPersist : Thread
{
number keepme
IPersist( object self ) { result("created IPersist:"+self.ScriptObjectGetID()+"\n");}
~IPersist( object self ) { result("killed IPersist:"+self.ScriptObjectGetID()+"\n\n\n\n");}
void CallFromOutside( object self ) { Result( "\t IPersist can be used!\n" ); }
void StopFromOutside( object self ) { keepme = 0; }
void RunThread( object self )
{
keepme = 1
Result( "\t Called once at start.\n")
While( keepme && !ShiftDown() ) yield()
Result( "\t Finished.\n")
}
}
// Just and example class used to access the 'anchored' object
Class SomethingElse
{
number keepID
SomethingElse( object self ) { result("created SomethingElse:"+self.ScriptObjectGetID()+"\n");}
~SomethingElse( object self ) { result("killed SomethingElse:"+self.ScriptObjectGetID()+"\n");}
void SetKeepID( object self, number id ) { keepID = id; }
void CallOut( object self )
{
result( "SomethingElse object is accessing CallOut...\n" )
object p = GetScriptObjectFromID( keepID )
if ( p.ScriptObjectIsValid() )
{
p.CallFromOutside()
}
}
void CallStop( object self )
{
result( "SomethingElse object is accessing CallOut...\n" )
object p = GetScriptObjectFromID( keepID )
if ( p.ScriptObjectIsValid() )
{
p.StopFromOutside()
}
}
}
// Main script. Create object on separate thread. Then feed it's ID as "weak reference" into the second object.
{
object ob = Alloc(IPersist)
ob.StartThread()
object other = Alloc(SomethingElse)
other.SetKeepID( ob.ScriptObjectGetID() )
other.CallOut()
If ( TwoButtonDialog( "You can either stop IPerstis now, or by pressing SHIFT later.", "Stop now", "later" ) )
other.CallStop()
}
An alternative way would be to have two objects keep references of each other. This is a deadlock-situation one would normally rather avoid, but for the purpose of anchoring it works as well. No object can go out of scope until you release one on purpose.
Again, it is your responsibility to 'release' things when you want a proper shutdown of the system.
The code for the deadlock-situation is rather slim:
class SelfLock
{
object partner
SelfLock( object self ) { result("created SelfLock:"+self.ScriptObjectGetID()+"\n");}
~SelfLock( object self ) { result("killed SelfLock:"+self.ScriptObjectGetID()+"\n");}
void SetPartner(object self, object p) { partner = p; }
void ReleasePartner(object self) { partner = NULL; }
}
{
object p1 = Alloc(SelfLock)
object p2 = Alloc(SelfLock)
p1.SetPartner(p2)
p2.SetPartner(p1)
if ( TwoButtonDialog( "Release partner", "Yes", "No keep locked" ) )
p1.ReleasePartner()
}

Creating Lua globals in Objective C/C from userdata

I am working on a library to allow Lua (5.2) scripting of games in iOS 5.x. I have created a class and added bindings to allow it to be created and accessed form Lua. The C initializer method called from Lua is given below:
static int newGeminiObject(lua_State *L){
GeminiObject *go = [[GeminiObject alloc] initWithLuaState:L];
GeminiObject **lgo = (GeminiObject **)lua_newuserdata(L, sizeof(GeminiObject *));
*lgo = go;
luaL_getmetatable(L, GEMINI_OBJECT_LUA_KEY);
lua_setmetatable(L, -2);
lua_newtable(L);
lua_setuservalue(L, -2);
NSLog(#"New GeminiObject created");
// add this new object to the globall list of objects
[[Gemini shared].geminiObjects addObject:go];
return 1;
}
This assigns a metatable which is set up elsewhere to provide access to various methods. Additionally, it attaches a table as a uservalue to allow script code to assign attributes to the objects.
I can create these objects in Lua scripts with no problem:
require "gemini"
x = gemini.new()
x:addEventListener("touch", objectTouched)
Here objectTouched is a a Lua method defined elsewhere that handles a touch event. Here addEventListener binds it to touch events.
These objects work just fine. When I attempt to create one from C, however, I am running into problems. I can create the object, but trying to assign it to a global and then invoke it in a script fails.
The following C code runs
-(void) addRuntimeObject {
GeminiObject *rt = [[GeminiObject alloc] initWithLuaState:L];
GeminiObject **lruntime = (GeminiObject **)lua_newuserdata(L, sizeof(GeminiObject *));
*lruntime = rt;
// set the metatable - effectively declaring the type for this object
luaL_getmetatable(L, GEMINI_OBJECT_LUA_KEY);
lua_setmetatable(L, -2);
// add a table to hold anything the user wants to add
lua_newtable(L);
lua_setuservalue(L, -2);
// create an entry in the global table
lua_setglobal(L, "Runtime");
// empty the stack
lua_pop(L, lua_gettop(L));
}
This should define a global named "Runtime". Trying to access this variable from a script like this
Runtime:addEventListener("enterFrame", enterFrame)
Results in the following error:
attempt to index global 'Runtime' (a userdata value)
It is a userdata value, but this doesn't seem to matter when I create one in Lua directly. The metatable binding provides access to the methods and metamethods. Again, this works fine if the object is created from Lua, just not when it is created in C.
Any ideas as to what I'm doing wrong here, or what the correct way to make a global from userdata is?
EDIT
Based on comments below regarding confusion about GEMINI_OBJECT_LUA_KEY, I thought I would list the code that is actually used in the binding:
static const struct luaL_Reg geminiObjectLib_f [] = {
{"new", newGeminiObject},
{NULL, NULL}
};
static const struct luaL_Reg geminiObjectLib_m [] = {
{"addEventListener", addEventListener},
{"__gc", geminiObjectGC},
{"__index", l_irc_index},
{"__newindex", l_irc_newindex},
{NULL, NULL}
};
int luaopen_geminiObjectLib (lua_State *L){
// create the metatable and put it into the registry
luaL_newmetatable(L, GEMINI_OBJECT_LUA_KEY);
lua_pushvalue(L, -1); // duplicates the metatable
luaL_setfuncs(L, geminiObjectLib_m, 0);
// create a table/library to hold the functions
luaL_newlib(L, geminiObjectLib_f);
NSLog(#"gemini lib opened");
return 1;
}
This code registers the library of functions (not show here) that provide the methods and metamethods for the GeminiObjects. The call to luaL_newmetatable creates a new metatable and associates it in the registry with the key GEMINI_OBJECT_LUA_KEY. GEMINI_OBJECT_LUA_KEY is just a unique string defined in the header. luaL_setfuncs actually adds the function pointers to the metatable, making them available as methods of the objects.
In case anyone is still interested, I got the answer to my question from the kind folks on the Lua mailing list. The problem here is that the library binding function luaopen_geminiObjectLib is not called before my call to addRuntimeObject.
Since iOS does not support dynamic libraries, I had added my libraries in statically by adding pointers to them to the preloadedlibs array in linit.c of the Lua source. Unfortunately, libraries added this way are not loaded until require('libname') is executed in a Lua script. Since I was calling my addRuntimeObject method prior to executing the Lua script, the library was not yet loaded.
The solution is to add the pointer to luaopen_geminiObjectLib to the loadedlibs array in the same linit.c file. This causes the library to be loaded when Lua starts up with no need for scripts to require it.

What is the difference between ISession.SaveOrUpdateCopy() and ISession.Merge()?

In NHibernate 3.1, ISession.SaveOrUpdateCopy() has been marked as deprecated. The documentation suggests using Merge() instead. The documentation for each is as follows:
SaveOrUpdateCopy(object obj)
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with
the session, it will be loaded. Return the persistent instance. If the
given instance is unsaved or does not exist in the database, save it and
return it as a newly persistent instance. Otherwise, the given instance
does not become associated with the session.
Merge(object obj)
Copy the state of the given object onto the persistent object with the same
identifier. If there is no persistent instance currently associated with
the session, it will be loaded. Return the persistent instance. If the
given instance is unsaved, save a copy of and return it as a newly persistent
instance. The given instance does not become associated with the session.
This operation cascades to associated instances if the association is mapped
with cascade="merge".
The semantics of this method are defined by JSR-220.
They look nearly identical to me, but there are bound to be some subtleties involved. If so, what are they?
SaveOrUpdateCopy is now considered obsolete and thus Merge is meant to take over for it (hence its extreme similarity).
They are pretty much the same except I don't think those cascade options were available with SaveOrUpdateCopy. However, that point is moot as Merge should be method you use.
UPDATE: I went in to the source code of NHibernate just to make sure they are as similar as I was thinking and here is what I found.
Both Merge and SaveOrUpdateCopy have very similar implementations:
public object Merge(string entityName, object obj)
{
using (new SessionIdLoggingContext(SessionId))
{
return FireMerge(new MergeEvent(entityName, obj, this));
}
}
public object SaveOrUpdateCopy(object obj)
{
using (new SessionIdLoggingContext(SessionId))
{
return FireSaveOrUpdateCopy(new MergeEvent(null, obj, this));
}
}
Their FireXXXX methods are also very similar:
private object FireMerge(MergeEvent #event)
{
using (new SessionIdLoggingContext(SessionId))
{
CheckAndUpdateSessionStatus();
IMergeEventListener[] mergeEventListener = listeners.MergeEventListeners;
for (int i = 0; i < mergeEventListener.Length; i++)
{
mergeEventListener[i].OnMerge(#event);
}
return #event.Result;
}
}
private object FireSaveOrUpdateCopy(MergeEvent #event)
{
using (new SessionIdLoggingContext(SessionId))
{
CheckAndUpdateSessionStatus();
IMergeEventListener[] saveOrUpdateCopyEventListener = listeners.SaveOrUpdateCopyEventListeners;
for (int i = 0; i < saveOrUpdateCopyEventListener.Length; i++)
{
saveOrUpdateCopyEventListener[i].OnMerge(#event);
}
return #event.Result;
}
}
The methods are exactly the same except they draw on different event listener lists, but even the types of the lists (IMergeEventListener) are the same!
Looking at the listener lists, they are both initialized with a default listener. The default listener for the Merge listen handlers is of type DefaultMergeEventListener while the SaveOrUpdateCopy is DefaultSaveOrUpdateCopyEventListener. Thus, the difference between them is just the difference in these two implementations (that is if you keep the default listener, which is 99% of the time).
However, the real interesting fact IS the difference in implementation. If you look at DefaultSaveOrUpdateCopyEventListener you get this:
public class DefaultSaveOrUpdateCopyEventListener : DefaultMergeEventListener
{
protected override CascadingAction CascadeAction
{
get { return CascadingAction.SaveUpdateCopy; }
}
}
This means the default behavior for Merge and SaveOrUpdateCopy only differs in the cascading actions, everything else is exactly the same.

How can my app detect a change to another app's window?

In Cocoa on the Mac, I'd like to detect when a window belonging to another app is moved, resized, or repainted. How can I do this?
You would need to use the Accessibility APIs, which are plain-C, located inside the ApplicationServices framework. For instance:
First you create an application object:
AXUIElementRef app = AXUIElementCreateApplication( targetApplicationProcessID );
Then you get the window from this. You can request the window list and enumerate, or you can get the frontmost window (look in AXAttributeConstants.h for all the attribute names you'd use).
AXUIElementRef frontWindow = NULL;
AXError err = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, &frontWindow );
if ( err != kAXErrorSuccess )
// it failed -- maybe no main window (yet)
Now you can request notification via a C callback function when a property of this window changes. This is a four-step process:
First you need a callback function to receive the notifications:
void MyAXObserverCallback( AXObserverRef observer, AXUIElementRef element,
CFStringRef notificationName, void * contextData )
{
// handle the notification appropriately
// when using ObjC, your contextData might be an object, therefore you can do:
SomeObject * obj = (SomeObject *) contextData;
// now do something with obj
}
Next you need an AXObserverRef, which manages the callback routine. This requires the same process ID you used to create the 'app' element above:
AXObserverRef observer = NULL;
AXError err = AXObserverCreate( applicationProcessID, MyObserverCallback, &observer );
if ( err != kAXErrorSuccess )
// handle the error
Having got your observer, the next step is to request notification of certain things. See AXNotificationConstants.h for the full list, but for window changes you'll probably only need these two:
AXObserverAddNotification( observer, frontWindow, kAXMovedNotification, self );
AXObserverAddNotification( observer, frontWindow, kAXResizedNotification, self );
Note that the last parameter there is passing an assumed 'self' object as the contextData. This is not retained, so it's important to call AXObserverRemoveNotification when this object goes away.
Having got your observer and added notification requests, you now want to attach the observer to your runloop so you can be sent these notifications in an asynchronous manner (or indeed at all):
CFRunLoopAddSource( [[NSRunLoop currentRunLoop] getCFRunLoop],
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode );
AXUIElementRefs are CoreFoundation-style objects, so you need to use CFRelease() to dispose of them cleanly. For cleanliness here, for example, you would use CFRelease(app) once you've obtained the frontWindow element, since you'll no longer need the app.
A note about Garbage-Collection: To keep an AXUIElementRef as a member variable, declare it like so:
__strong AXUIElementRef frontWindow;
This instructs the garbage collector to keep track of this reference to it. When assigning it, for compatibility with GC and non-GC, use this:
frontWindow = (AXUIElementRef) CFMakeCollectable( CFRetain(theElement) );
Further research turned up "Quartz Display Services"
The interesting function for my needs is CGRegisterScreenRefreshCallback.