Forums > Java

public variables amongst multiple mxj objects

April 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


April 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


April 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


April 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


April 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.


April 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


April 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


April 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.


April 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


April 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


April 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
http://www.cassiel.com
http://www.myspace.com/cassieldotcom
http://www.loadbang.net


April 13, 2007 | 9:02 pm


April 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
http://www.cassiel.com
http://www.myspace.com/cassieldotcom
http://www.loadbang.net


April 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
>
>


Viewing 14 posts - 1 through 14 (of 14 total)