public variables amongst multiple mxj objects


    Apr 12 2007 | 11:50 pm
    Dear List,
    This might just be a pretty dumb question, but nevertheless I don't know how to answer it:
    I'd like to send arrays of values generated in one mxj object to several other mxj objects at audio rate. It would be very nice if these other mxj objects could just retreive the values of the arrays without using any signal cords.
    This should be possible and I've tried to do this in several ways but have failed miserably. Where, when and how exactly should I declare such arrays?
    Thanks in advance! - Tarik

    • Apr 13 2007 | 12:49 am
      You can share data between mxj instances by using a static instance of an object that they all reference. You have to be careful during development though because this stuff can get confusing with the way classloading is done. Basically you need to make sure that all instances of your mxj objects point to the same version of compiled classes. Instances loading classes from successive compiles will have different static contexts. This is only a real pain when you are developing.
      With that in mind I would make your static object relatively simple. This is really crude and just some email coding but something along these lines could work.
      Dispatcher.java....
      public class Dispatcher { private Dispatcher _instance = null; public static getInstance() { if(_instance == null) _instance = new Dispatcher(); return _instance(); }
      private Dispatchable[] _dd; private int _num_dispatchable = 0; private static final int MAX_CLIENTS = 64;xs private Dispatcher() { _dd = new Dispatchable[MAX_CLIENTS];
      }
      public void addDispatchable(Dispatchable d) { _dd[_num_dispatchable++] = d; }
      public void broadcastMessage(Dispatchable from,Object message) { for(int i = 0; i < _num_dispatchable;i++) { Dispatchable d = _dd[i]; if(from.hashcode() != d.hashcode())//dont send to yourself d.receiveMessage(message); } }
      }
      ...Dispatchable.java public interface Dispatchable { public void receiveMessage(Object message); }
      public class mymaxobject extends MaxObject implements Dispatchable {
      public mymaxobject() { ... .. Dispatcher.getInstance().addDispatchable(this); }
      public void bang() { Dispatcher.broadcastMessage(this,"Hello");
      }
      public void receiveMessage(Object o) { String s = (String)o; System.out.println("recieved "+s); } }
      You could also use MaxContext to access other MXJ instances and come up with some framework using that after your patch has been loaded.
      topher
      On Apr 12, 2007, at 16:50 PM, Tarik wrote:
      > > Dear List, > > This might just be a pretty dumb question, but nevertheless I don't > know how to answer it: > > I'd like to send arrays of values generated in one mxj object to > several other mxj objects at audio rate. It would be very nice if > these other mxj objects could just retreive the values of the > arrays without using any signal cords. > > This should be possible and I've tried to do this in several ways > but have failed miserably. Where, when and how exactly should I > declare such arrays? > > Thanks in advance! - Tarik
    • Apr 13 2007 | 9:58 am
      topher lafata wrote: > Instances loading classes from successive compiles > will have different static contexts.
      Sweet - I hadn't realised that they'd *ever* have the same classloader. Has something changed, or have I been labouring under a long-term misunderstanding?
      > if(from.hashcode() != d.hashcode())//dont send to yourself
      Strictly speaking, shouldn't this be one of the few places to use objA==objB? hashcode(), like equals() is meant to demonstrate equivalence, not identity. Given that the default implementation just compares object references anyway, no biggy unless you roll your own equals(), meaning you should roll your own hashcode() too.
      -- Owen
    • Apr 13 2007 | 11:56 am
      Thanks a lot,
      I believe your answer will be very helpful for me... if only I were experienced enough in Java to actually understand it.
      I'm still studying your reply and believe that I will eventually find out what you're doing exactly. I've never used instances of classes in such an explicit way and I'm pretty new to this use of static variables, so for now it's all still a bit confusing to me.
      So if anyone feels the urge to give a very basic example of how to send just 1 variable from one mxj object (sendmxj for example) to another (receivemxj), I'd hopefully get a better grasp of what is actually going on here.
      - Tarik
    • Apr 13 2007 | 12:42 pm
      After some more studying I find the hardest thing to understand which objects and methods exactly should be static. In your rough sketch this got a bit mixed up, which results in the following problems:
      For the use of "Dispatcher.broadcastMessage(this,"Hello");" the function broadcastMessage needs to be static.
      However, when I make this function static, it can't use the "_num_dispatchable" variable. Unless of course, I make THAT static too, but then the variable necessarily loses it's whole purpose.
      Also, I don't understand what purpose the "Dispatchable" interface serves. Which parts of the code actually need this interface?
      ...yeah, the road to true wisdom is really long and hard for me. But I'll get there.
    • Apr 13 2007 | 1:36 pm
      Tarik wrote: > After some more studying I find the hardest thing to understand which > objects and methods exactly should be static. In your rough sketch > this got a bit mixed up, which results in the following problems:
      You need to get your head round static-ness. In order to do this, first make sure you're happy with the distinction between a class and an object (which is an *instance* of a class).
      A static method is the *same method* whatever instance of a class it's called on.
      > For the use of "Dispatcher.broadcastMessage(this,"Hello");" the > function broadcastMessage needs to be static.
      No it doesn't. Topher's code shows the standard way of ensuring that only a single instance of a class is ever created (within the same classloader).
      Key points: - Disptacher's constructor is private - as such, only code from within Disptacher can create an instance of it.
      - There is a static instance of Dispatcher, within the dispatcher class, meaning that this instance will be the same all across the current context.
      - The static getInstance() method manages access to that single instance, and its creation.
      So, what happens when a client calls getInstance() is that it is returned a copy of the *one and only* instance of Dispatcher within this classloader, guaranteeing that when it calls the (non-static) addDispatchable() method all clients are in fact being added to the same internal list of references.
      Likewise, broadcastMessage() works *within the single instance* of Dispatcher, so is non-static.
      > Also, I don't understand what purpose the "Dispatchable" interface > serves. Which parts of the code actually need this interface?
      Are you happy with what Interfaces are for?
      Interfaces, basically, represent a contract that says any class that implements InterfaceX will respond sensibly to any of the methods that InterfaceX declares.
      This is preferable to using inheritance of abstract methods in classes for a number of reasons, not least that Java only supports single-class inheritance (and we probably want our classes to inherit from MaxObject), but multiple interface implementation.
      So, by specifying an interface, Dispatchable says 'I don't care at all about what *type* of thing I'm being passed, just so long as it responds to this method'.
      So, any class that wants to register with the Dispatcher (and thus be able to be sent, and receive, messages) needs to implement Dispatchable.
      Hope this helps,
      I'll post a really, really, simple example in a while if you're still stuck.
      -- Owen
    • Apr 13 2007 | 2:44 pm
      > >> if(from.hashcode() != d.hashcode())//dont send to yourself > > Strictly speaking, shouldn't this be one of the few places to use > objA==objB? hashcode(), like equals() is meant to demonstrate > equivalence, not identity. Given that the default implementation > just compares object references anyway, no biggy unless you roll > your own equals(), meaning you should roll your own hashcode() too. >
      I believe that objA==objB just compares hashcodes so it should be the result! t
    • Apr 13 2007 | 3:04 pm
      A really big heap of thanks goes your way, guys!
      I not only solved my problem but also learned a great deal about Java in a very short time. Btw, "Dispatcher.broadcastMessage(this,"Hello");" DOES imply a static broadcastMessage function, "Dispatcher.getInstance.broadcastMessage(this,"Hello");" however does not. But it's thanks to your help that I figured out what was wrong here.
      Thanks again, and for others who want to use the code, here it is, fully functional:
      =========================================================
      Dispatcher.java:
      import com.cycling74.max.*;
      public class Dispatcher { private static Dispatcher _instance = null; public static Dispatcher getInstance() { if(_instance == null) {_instance = new Dispatcher();} return _instance; }
      private Dispatchable[] _dd; private int _num_dispatchable = 0; private static final int MAX_CLIENTS = 64;
      private Dispatcher() { _dd = new Dispatchable[MAX_CLIENTS]; }
      public void addDispatchable(Dispatchable d) { _dd[_num_dispatchable++] = d; }
      public void broadcastMessage(Dispatchable from,Object message) { for(int i = 0; i < _num_dispatchable;i++) { Dispatchable d = _dd[i]; if(from.hashCode() != d.hashCode())//dont send to yourself {d.receiveMessage(message);} } } }
      ========================================================
      Dispatchable.java:
      import com.cycling74.max.*;
      public interface Dispatchable { public void receiveMessage(Object message); }
      ========================================================
      mymaxobject.java:
      import com.cycling74.max.*;
      public class mymaxobject extends MaxObject implements Dispatchable { public mymaxobject() { // Write whatever you want here...
      // ...and this is the bit that adds this object // to the _dd array in Dispatcher
      Dispatcher.getInstance().addDispatchable(this);
      }
      public void bang() { Dispatcher.getInstance().broadcastMessage(this,"Hello"); }
      public void receiveMessage(Object o) { String s = (String)o; System.out.println("recieved "+s); } }
      ==============================================================
      And then just make two "mxj mymaxobject" objects, bang one of them and see what comes out of the other.
    • Apr 13 2007 | 3:32 pm
      topher lafata wrote: > I believe that objA==objB just compares hashcodes so it should be the > result!
      I think you have that the wrong way round - if that were true, it wouldn't make sense. == compares references, not internal data.
      Consider that:
      (new Integer(3) == new Integer (3)) = false;
      although (as you'd expect)
      (new Integer(3).hashCode() == new Integer (3).hashCode()) = true;
      (Parenthetically, it's confusing that:
      (("foo" == "foo") = true
      because of cunning java String trickery, but
      (new String("foo") == new String("foo")) = false;
      as expected.)
      In classes that inherit their equals() and hashCode() behaviour from java.lang.Object, equals() and hashCode() just check the references.
      If what you mean to do is check reference equality you should use ==, as any class that has properly overridden equals() and hashCode() will break.
      -- Owen
    • Apr 13 2007 | 3:37 pm
      Owen Green wrote:
      > any class that has properly overridden equals() and hashCode() will break...
      ...with hashCode based checks.
      Dunno why I stopped mid-sentence, must be my child-of-the-80s attention span :)
      -- Owen
    • Apr 13 2007 | 8:47 pm
      On 13 Apr 2007, at 16:32, Owen Green wrote:
      > (Parenthetically, it's confusing that: > > (("foo" == "foo") = true
      Confusing and (as far as I can tell) incorrect: I'm looking at section 15.21.3 of the Third Edition of the Java Language Specification, and Strings are regarded as object references. A string literal is a still a reference to a String (Sec. 4.3.3).
      -- N.
      Nick Rothwell / Cassiel.com Limited www.cassiel.com www.myspace.com/cassieldotcom www.loadbang.net
    • Apr 13 2007 | 9:02 pm
    • Apr 13 2007 | 9:38 pm
      On 13 Apr 2007, at 22:02, Ritchie Argue wrote:
      > True they are still references, but in the case of a string > literal, they are references to a constant pool that only contains > one instance of each literal, in this case "foo".
      Oh, gawd... you're right. And the interning/pooling even extends to constant-folding. Well, well ... learn something new every day...
      (Of course, I had to write a little program to test it out. For the record, this is the first time I've ever used "mxj quickie".)
      -- N.
      Nick Rothwell / Cassiel.com Limited www.cassiel.com www.myspace.com/cassieldotcom www.loadbang.net
    • Apr 14 2007 | 12:40 am
      thanks owen for pointing all this stuff out. it definitely makes sense. i wouldn't want to be responsible for purveying incorrect knowledge! t
      On Apr 13, 2007, at 08:37 AM, Owen Green wrote:
      > Owen Green wrote: > >> any class that has properly overridden equals() and hashCode() >> will break... > > ...with hashCode based checks. > > Dunno why I stopped mid-sentence, must be my child-of-the-80s > attention span :) > > -- > Owen > >