object_post, object_error and object_warn without deferring

$Adam's icon

Hi all,

I realized that if I make a call to any of the above mentioned methods (or their versions without the object_ prefix) and then block the main thread, the message that I wanted to post will not show until the thread gets unblocked. My guess is that when we call these methods, the actual messages will be deferred to the end of the low-priority queue. My problem is that in my specific scenario, I'd like to warn the user that Max will hang for a while and he/she should be patient and wait. Is there a way to force these methods to post their contents just at the time when they are called, so that I could display my warning before Max hangs?

Thanks,
Ádám

Timothy Place's icon

You could post the message and then call the rest of your task in another method via defer_low().

Cheers,
Tim

$Adam's icon

Hi Tim,

thanks. This is indeed a solution, however, I'm not sure that this is a safe way to go in my specific case. The problem is that I need to display this warning in the object freeing function of an external, since the freeing routine takes a long time to execute and I don't want the users to panic during that time. So the question is: can I make a defer_low call in an object freeing routine? My guess is that I'm not allowed to do so, since the object structure would be freed at the time when the deferred method got called...

Thanks,
Ádám

Timothy Place's icon

Hi Ádám,

I did not realize this was a free method. So, yes, it will be a bit trickier. Just to brainstorm a couple of options, not really knowing what your code is doing...

One idea is that you could create a 'nobox' class, which is to say an object that is not instantiated in a box in Max. Then your class which is instantiated in Max will create a new instance of your nobox class internally (using object_new_typed() or one of its friends). When your object is freed you then defer the freeing of the internal nobox class.

Taken a step further, you could spawn a thread to call a cleanup method to release resources from your nobox class in the background. When it is done you could then free the nobox class. This might be massive overkill, but it does avoid pausing the normal execution of Max.

I hope this helps!
Tim

$Adam's icon

Hi Tim,

thanks for helping! To reveal the whole situation, this problem occurs with two of my networking objects which open TCP connections, namely, [sadam.tcpClient] and [sadam.tcpSender]. These objects create separate threads for managing the connections, which of course should be join-ed by the main thread before the objects themselves are being freed. The problem is that under some circumstances (for example, if I try to establish a TCP connection to my local router on a port not used by the router itself) some TCP servers will wait as much as 2-3 minutes before they drop a connection request, and during this time, the connect() method of my objects will hang. The same occurs if one is still sending some TCP packets to a remote address which has a slow download speed or a huge latency.

My original idea was that I should probably create a threadpool which would collect these hanging connections and install a quittask to properly end those hanging ones that are still alive at the time when Max quits. My only problem is that since these threads are sending stuff to the outlets of the original objects, I'll need to do the planning quite carefully in order to make sure that the outlets etc. actually do exist at the time when the threads are pretending to send data out of them. To make the scenario more complex, I just recently implemented a global outlet manager for outlet calls from custom-threads, which messes up this story even more.

So my question is: do you see any potential danger in implementing this functionality with a global threadpool which would kill itself as a quittask? (And which some sort of flag of the 'still-alive' boxed objects as well - just to avoid false outlet calls.)

I know that I could, as an alternative, force my threads to stop, but that's not very elegant...

Thanks for all the fish,
Ádám

$Adam's icon

Hi again,

I guess I'm on the way of fixing this. However, there's one more question: is it safe to assume that quittasks will run after every boxed object has been released? Or do I need to make a defer_low call to make this sure?

Thanks,
Ádám

Timothy Place's icon

Yes. quittasks are closed after all windows are closed and patchers are freed. You should *not* use defer_low() from a quittask, because the queue will not be serviced (and the scheduler no longer even exists) at this point.

Cheers,
Tim

$Adam's icon

Thanks a lot!
Cheers,
Ádám