message sent to an external is sent to several external of the same class

Aug 14, 2013 at 7:02am

message sent to an external is sent to several external of the same class

Hi,

I’m trying to use an custom external in a patcher, it’s in c++. You can send it some messages. It sort of works. Now if i create another object box ; invoke the same custome external class ; and send a message to the fisrt created one, the new one will receive those messages.

So, how is it possible ? At which level could those messages interfere ? Is there a set of “good practice rules” to avoid this, ie naming differently variables and messages to the max object ? or is that a problem related to c/c++ ?

sorry if i’m not clear… i’m uneasy with the vocabulary to use here

#258871
Aug 14, 2013 at 7:22am

Hi,

I guess you’re a bit too generic here. Did you write the external? If yes, could you provide a MWE reproducing your bug?

If it’s a third-party code (and you can’t ask the developer), then it might be trickier. As a first guess, I’d search the code for any global variables that might be accessed by multiple instances simultaneously and check whether there was any interference there. If not, I’d check if the object gets registered to any notifications and I would try to examine the exact notifications to which the object is attached to. If none of this works, I’d crack my head against a wall in the hope that something useful comes to my mind…

HTH,
Ádám

#258873
Aug 14, 2013 at 8:19am

Hi,

Thanks, i’ll crack my head against a wall right now ! ;)
I didn’t do it myself, it’s part of an internship i’m doing, so i have access to the source code, it’s a bit big, providing a MWE without the entire thing might be difficult (i’d prefer to avoid that, because i’m not sure i’m allowed to now, and several things need improvement). I think there are global variables, should be a lot of them. I thought… i thought even something global would stay “inside” its instance, not interfere…

And it seems solved ! At least better ! Indeed it was a global variable, ie declared outside of any function, inside a .cpp file, and once i declared in the “protected” part of the file’s header (related .h file) ; it doesn’t interfere anymore. So thanks a lot.
But… Is there a sort of general rule ? How can you be sure that a variable is declared inside an instance ? how does Max behave in regard to private/public/protected and namespace ?…. so many mysteries !

anyway thanks a lot. sorry for that “sorcerer’s apprentice” workflow…

#258879
Aug 14, 2013 at 9:21am

Hi,

“You can send it some messages. It sort of works. Now if i create another object box ; invoke the same custome external class ; and send a message to the fisrt created one, the new one will receive those messages.”

So strange! A global instance of a custom class somewhere?

“How does Max behave in regard to private/public/protected and namespace ?”

Max behaves nothing about that, because Max do not see any line of code. The things that Max can see is a bundle (dynamic library) with a function ‘main’ as an entry point. So all your job is to make something valuable, compile it, and produce something that can work inside this box. Of course it is a bit more complex ; you can interact with Max by calling API functions (outlet and a lot more) and Max interacts with your external by the class methods you define in your ‘main’ function. But that’s all.

“Is there a sort of general rule ?”

1. Everything global in your code is shared by all the ‘instances’ of your object (and that implies to care a bit more about multithreading).

2. Everything static in a compilation unit is local to that compilation unit { but } { and } it is shared also by all the ‘instances’ of your object.

3. If you want something { own by }{ local to } an instance you need to include his declaration in your object structure (and allocated the related memory in your ‘new’ method if it needs to).

4. You can mix all that and make complex scenarios (with C++ for instance in the scope) ; but at the end you can reduce the situation to that three cases.

Thanks to correct me if i’m wrong!
Thanks folks to append your knowledge as it remains lot of dark zones for me also ;-)

#258887
Aug 14, 2013 at 12:18pm

Hi,

indeed, the point of having global variables is that, once Max loads the bundle containing your external’s code, the variable would be alive until Max unloads the bundle (which at the moment may only happen when Max quits). This means that every instance of your object will “see” that variable. Moreover, even if you delete every instance of your object from your patcher, the global variable would still be there, so if you instantiate a new instance at some later point, it would still “see” the global variable with its lastly set value.

This can be useful if your external accesses a shared resource (eg. a network port), where you’d need to keep track of the state of the resource regardless of your actual instances. However, I usually stay away from global variables as long as I can, since (to my taste) they don’t fit quite nicely into the OO idea.

The description that Nicolas gave about the visibility of different stuff is pretty nice; I would only add that, in C++, you also have the option of declaring namespaces (indeed a very helpful concept), so you can isolate things also by declaring them within a custom namespace.

Cheers,
Ádám

#258899
Aug 14, 2013 at 2:17pm

Thanks for

1. Everything global in your code is shared by all the ‘instances’ of your object (and that implies to care a bit more about multithreading).

2. Everything static in a compilation unit is local to that compilation unit { but } { and } it is shared also by all the ‘instances’ of your object.

3. If you want something { own by }{ local to } an instance you need to include his declaration in your object structure (and allocated the related memory in your ‘new’ method if it needs to).

4. You can mix all that and make complex scenarios (with C++ for instance in the scope) ; but at the end you can reduce the situation to that three cases.

and

indeed, the point of having global variables is that, once Max loads the bundle containing your external’s code, the variable would be alive until Max unloads the bundle (which at the moment may only happen when Max quits). This means that every instance of your object will “see” that variable. Moreover, even if you delete every instance of your object from your patcher, the global variable would still be there, so if you instantiate a new instance at some later point, it would still “see” the global variable with its lastly set value.

, things become clearer now. The culprit seemed to be that unprotected variable. I was wondering though, if that behaviour of global variables exist outside of Max – explaining : if i open twice the same application, which code contains some global variables, will they share said variables ?

Thanks again for your invaluable help !

#258906
Aug 14, 2013 at 3:21pm

if i open twice the same application, which code contains some global variables, will they share said variables ?

No, they won’t. They are separate applications, having their own allocated memory blocks. What you need to understand here is that the bundle is loaded only once by Max. In this context, you may think of the bundle as an “application within the application”. When you launch Max, it will not load any bundles (besides some system ones). Now, when you instantiate an object the first time, Max will load the bundle containing that object. From this point, the bundle resides in the memory as long as Max is running; therefore, all global variables, function tables etc. will remain in the memory. When Max loads the bundle, it will call the entry point of the bundle (which is the main() function). Therefore, this function will execute only once, at bundle-loading time, and is independent of any instance of your object. Then, each time when you instantiate a new instance of your object (including the very first time when you load it), Max will call the object initialisation function, which returns a pointer to your newly instantiated object. When you delete the object, Max will free this pointer; however, anything that is not related to that particular instance (eg. global variables, function tables etc) will stay in the memory of the Max application. But remember, this has nothing to do with an instance of any other running application (eg. if you run two instances of Max, they will operate with separated memory blocks, so a bundle loaded into one instance of Max will not “see” the one loaded by the “other Max”). Let me know if this is not clear at all…

Hope this helps,
Ádám

#258913
Aug 15, 2013 at 3:51am

This is very clear and helps a lot ! Thanks.

#258954
Aug 15, 2013 at 6:14am

Hi,

And that’s not specific to Max/MSP.

(Shortest version)

1. Each new application you launch on your computer has his own private adress space (that contains the code to execute, global data to that app, the heap, the stack).
2. If anything in the code tries to get something { outside off } { unmap in } that adress space, it crashes -Segmentation Fault- (for instance accessing NULL pointers).
3. As far as i understand a Mac OS bundle launched is included in the launcher adress space (but that’s something i should investigate a bit more).

#258971
Aug 16, 2013 at 5:49am

Oh, ok. I understand everything now ! (kidding ;) )

#259065
Aug 16, 2013 at 7:39am

Hi,

(Longer version)

About that subject i found all that blog interesting ( http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory ) that’s mainly for GNU/Linux but it seems to be more or less the same on Mac OS X.

#259076

You must be logged in to reply to this topic.