I want my external to behave in a [grab]-like fashion
- that is, I want it to send a value to an arbitrary object connected to one of its outlets, have that object perform its calculation upon the value and be able to retrieve the result from its outlet – that is, to prevent the outlet from sending out the result, intercepting it from within my calling method instead…
Maybe the answer is obvious, or maybe it’s not but it lies somewhere in the sdk, but I can’t find it… can anyone point me into the right direction?
Thank you very much!
There isn’t anything the SDK to demonstrate how the grab object works. Maybe you could share a little more about your project? Some context might be helpful in offering different ways of thinking about the solution(s).
Oh, I see…
In fact, I am working upon a bundle of objects operating upon lists, and I was fancying about implementing a sort of a lisp-like "mapcar" thing – where the lambda function would be an object box connected to an outlet.
Of course it’s a trivial thing to do in max, I was just thinking it would have been cool…
But any suggestion is welcome, anyway!
Sounds cool! The techniques of the grab object open up many cans of worms, and its some trouble from which I’m to save you :-). I was thinking of two things.
If you wanted to do this, you could have an additional inlet and outlet and then feed your values to the new outlet and receive the calculations at the new inlet. This is one additional patch cord in the patcher, but it preserves the normal flow of messages through patchers and would even allow users to chain several objects together instead of being restricted to a single object.
Another alternative, if you were creating your own objects for this purpose, is that you could send a message from the main object to the worker object and that message would have an argument that is the pointer value of the main object. Then, upon completion of its task, the worker object could communicate back to the main object by using a call to object_method() and the pointer it was passed.
Hope that all makes sense!
Yes, it definitely makes sense.
In fact, your first solution was my backup plan from the beginning, and I could smell that it was much more reasonable than a grab-like hack! I just have the feeling that thread-safety will require some special care…
The second solution is very cool, but I don’t want this mechanism to be limited to especially-made objects, so it’s not what I’m looking for.
Thank you for your help!
… and of course you made me utterly curious about the innards of grab!
No way to have a peek inside? ;)
i am not a C programmer, but if i wouwld have to guess, i would say it is not that
easy to implement the grabby thing.
it will probably require different methods for different target objects and is maybe
even runtime version dependent.
also, it may be, that the starship captains dont really want us to create externals
beside grab to brake the blackbox paradigm of maxmsp patching.
create two objects ?
a [master] who scans each time you create [slave] objects and those [slave] intercept and send back values to [master] ?
-> etc ….
[talkie] && [walkie] family !!!
@roman: i have the feeling that grab somehow tweaks the worker’s object "outlet" field, in the t_object structure. i’d guess it doesn’t require different methods for different objects – maybe it does for different outlet types – but i’m just taking a guess…
@pizza: your solution sounds interesting, but i don’t really get it – can you show me a somewhat more detailed scenario?
thank you guys!
Hello andrea agostini,
i don’t know lisp and "mapcar" function so i am not sure about what you want to do ;
my idea was that instead of grabing the object you could connect another object behind it who will send values (pointer … bind to … notify and co) to the master one ; a kind of mix between both suggestions from Timothy.
I can’t be more precise as i really don’t know how to do it !!!
I have to think about it a little bit more …
I did an external few weeks ago that scans patchers searching [jit.matrix] with special name, get a pointer to them, to change cells and so …
Like it, your [master] object can keep a list of all [slave] objects created (why not right to left order) to get what they have intercepted ?
Finally it should be just like an "automatic invisible custom send/receive process".
For fun i’ll make few test to show you "more detailed scenario" ;-)
here to show what i was speaking about ; that seems to work, even if i’m not sure at all that’s really safe ; is anybody can tell me if my [walkie]‘s : //walkie_int// is not too dangerous ; in case of yes (and i think it is) it should best to do as Timothy said …
if you were creating your own objects for this purpose, is that you could send a message from the main object to the worker object and that message would have an argument that is the pointer value of the main object. Then, upon completion of its task, the worker object could communicate back to the main object by using a call to object_method() and the pointer it was passed.
… to get values back from [talkie].
Anyway all that must be improved and HTH ;-)
Looks cool! I don’t actually think it will be my kind of solution, but I like the thing anyway – thank you!
About safety, I have two remarks:
- it works fine as long as everything is in the same thread. If there is some deferring/scheduling between [walkie] and [talkie], the result might not be consistent; but as far as I can see this should not cause more problems than this.
- I wonder if there is a thread-safety problem if a [talkie] is freed just before its "get" method is called (but after the "if" has been passed). Maybe a locking system should be implemented, to mutually exclude the "get" method call in [walkie] and the free method in [talkie]. But I’m not too sure about either the problem (shouldn’t it arise in one thousand other normal max situations? is there a locking mechanism in max to prevent such things?), or the solution (would a mutex in the free method actually prevent an undesired freeing?). – if you or some other max guru have an idea about this it would be of great interest to me; thread-safety is becoming a personal obsession…
for fun i do what i said in previous post here : + safe.
in this zip [walkie] send a pointer to [talkie], and [talkie] send values to [walkie] using object_method ( ) ; And even after deleted [walkie] (so [talkie]‘s pointer is bad) max doesn’t crash : max must be protected against bad call between objects …
most of time to test my external about thread safety problems i just make crazy huge patches with ten [metro 5] [uzi 100] connected to my external asking lots of stuff while i do the same thing in low_priority thread … click click click … and as i’m not an inside max guru i make test and test and test … brutalizing maxMSP and crash and crash and crash …
"I don’t actually think it will be my kind of solution", you are right ;-)