Benefits of globalsymbol_reference

Aug 29, 2010 at 10:57am

Benefits of globalsymbol_reference

Dear Developers,

I’m a bit confused about the globalsymbol_reference() and globalsymbol_dereference() functions. What is the difference between using these funtions to access the s_thing of a symbol or just simply reading the actual content of the symbol I’m interested in? What are the benefits of using these functions?

Thanks,
Ádám

#52032
Aug 29, 2010 at 12:52pm
#186804
Aug 29, 2010 at 1:37pm

Great summary. Thanks.

#186805
Aug 30, 2010 at 5:30pm

Actually after reading again the article and reading again the relevant parts of the docs I’m confused again.

So here’s what I’d like to achieve: I’d like to use a shared structure in the memory that could be accessed by several different objects at the same time (not just instances of the same class, but objects implementing several classes — in other words, a shared buffer used by many different externals developed by myself) and which would send notifications to registered objects at certain moments. My original idea was that in the main() routine of each external I’d check for the s_thing of a given symbol and the first external that finds a null at that place would initialize the shared buffer (actually a C++ class with some methods that would trigger some events in certain moments).

Now I see that I have other two options as well and I can’t decide which way to choose.

On one hand I could create a NOBOX class for this shared buffer, then bind it to a symbol with globalsymbol_bind() and access it with the globalsymbol_reference() and globalsymbol_dereference() functions.

On the other hand I could also register my shared object using object_register() and attach my ‘client’ objects with object_attach(). In this case (if I understood well) I even don’t have to create a max-style ‘pseudo-class’ of NOBOX type but I could actually use my original C++ class and just register a pointer to an instance of that class.

Is there any particular reason why I should choose the first or the second solution?

And actually, is there anyone who knows what the object_register_unique() method does? It seems that it is not documented…

#186806
Sep 20, 2010 at 2:36pm

Dear Developers,

it seems there must be something I don’t understand here. My idea was that I’d create a max-class of CLASS_BOX type so that it could be instantiated as a box, like a [buffer~] or a [table] or a [coll]. Then I though the following: I’ll maintain a linked list of all the instances of the class that are referencing the same name, and I’d register one of the instances from this linked list to the symbol itself representing the shared name. To avoid problems which arise when the user creates or deletes ‘boxes’ representing instances of my class, I actually decided that the registered instance itself should not be accessible by the user, instead, it should be an instance created from within one of the boxed instances.

To let this happen, here’s what I though: the first time the user tries to bind my object to a given string (in other words, the first time the user creates a boxed instance of my object) the internal binding routine would create a new instance of my object in the background, register it with object_register() so that it could send notify messages to the clients of my object and bind this hidden instance to its name with globalsymbol_bind(). If the object was already registered (so if the user created more than one box with the same name) my internal binding routine would just append the current instance to the linked list (maintained by the instance that was already bound to the given name with globalsymbol_bind()).

The problem is that it seems that for some reason the binding wouldn’t happen. I have the following code:


class Foo {
public:
t_object o;
t_symbol * name;
Foo * next;
bool bind ( t_symbol * );
// Other declarations
}

bool Foo::bind ( t_symbol * newName ) {
Foo * newFoo;
Foo * registeredFoo;
t_atom newFooName;

unbind ( );
name = newName;
if ( name != gensym ( "" ) ) {
if ( name->s_thing && ob_sym ( name ) != gensym ( "foo" ) ) {
name = gensym ( "" );
return false;
}
if ( ! name->s_thing ) {
atom_setsym ( & newFooName, gensym ( "" ) );
newFoo = ( Foo * ) object_new_typed ( CLASS_BOX, gensym ( "foo" ), 1, & newFooName );
registeredFoo = ( Foo * ) object_register ( gensym ( "namespace" ), name, newFoo );
if ( newFoo != registeredFoo ) { // As documentation says, in some cases Max might duplicate the object to register.
object_free ( newFoo ); // In these cases, we just need the registered object.
}
globalsymbol_bind ( ( t_object * ) registeredFoo, name->s_name, 0 ); // Binding object to symbol.
object_notify ( this, gensym ( "created" ), name ); // Notifying previously registered clients.
}
registeredFoo = ( Foo * ) name->s_thing;
next = registeredFoo->next; // Inserting object into the linked list.
registeredFoo->next = this;
}
return true;

}

// Other routines

This code will crash Max. After doing some tests, it seems that although globalsymbol_bind() gets called, the s_thing of my name variable remains NULL.

Is there anyone who could give me a hand with this?

Thank you,
Ádám

#186807
Sep 20, 2010 at 2:39pm

Now I see that the forum engine removed all whitespace from my code. I try to post it again:


class Foo {
public:
t_object o;
t_symbol * name;
Foo * next;
bool bind ( t_symbol * );
// Other declarations
};

bool Foo::bind ( t_symbol * newName ) {
Foo * newFoo;
Foo * registeredFoo;
t_atom newFooName;

unbind ( );
name = newName;
if ( name != gensym ( "" ) ) {
if ( name->s_thing && ob_sym ( name ) != gensym ( "foo" ) ) {
name = gensym ( "" );
return false;
}
if ( ! name->s_thing ) {
atom_setsym ( & newFooName, gensym ( "" ) );
newFoo = ( Foo * ) object_new_typed ( CLASS_BOX, gensym ( "foo" ), 1, & newFooName );
registeredFoo = ( Foo * ) object_register ( gensym ( "namespace" ), name, newFoo );
if ( newFoo != registeredFoo ) { // As documentation says, in some cases Max might duplicate the object to register.
object_free ( newFoo ); // In these cases, we just need the registered object.
}
globalsymbol_bind ( ( t_object * ) registeredFoo, name->s_name, 0 ); // Binding object to symbol.
object_notify ( this, gensym ( "created" ), name ); // Notifying previously registered clients.
}
registeredFoo = ( Foo * ) name->s_thing;
next = registeredFoo->next; // Inserting object into the linked list.
registeredFoo->next = this;
}
return true;

}

// Other routines

Hope this time works.

#186808
Sep 21, 2010 at 3:04pm

The best way to post code is to put it between ‘pre’ tags. The ‘code’ tag is not very useful because of the whitespace collapsing as you noted.

Cheers

#186810
Sep 21, 2010 at 3:29pm

Thanks for the tip. Here’s the code again:

class Foo {
public:
   t_object o;
   t_symbol * name;
   Foo * next;
   bool bind ( t_symbol * );
   // Other declarations
};

bool Foo::bind ( t_symbol * newName ) {
   Foo * newFoo;
   Foo * registeredFoo;
   t_atom newFooName;

   unbind ( );
   name = newName;
   if ( name != gensym ( "" ) ) {
      if ( name->s_thing && ob_sym ( name ) != gensym ( "foo" ) ) {
         name = gensym ( "" );
         return false;
      }
      if ( ! name->s_thing ) {
         atom_setsym ( & newFooName, gensym ( "" ) );
         newFoo = ( Foo * ) object_new_typed ( CLASS_BOX, gensym ( "foo" ), 1, & newFooName );
         registeredFoo = ( Foo * ) object_register ( gensym ( "namespace" ), name, newFoo );
         if ( newFoo != registeredFoo ) { // As documentation says, in some cases Max might duplicate the object to register.
            object_free ( newFoo ); // In these cases, we just need the registered object.
         }
         globalsymbol_bind ( ( t_object * ) registeredFoo, name->s_name, 0 ); // Binding object to symbol.
         object_notify ( this, gensym ( "created" ), name ); // Notifying previously registered clients.
      }
      registeredFoo = ( Foo * ) name->s_thing;
      next = registeredFoo->next; // Inserting object into the linked list.
      registeredFoo->next = this;
   }
   return true;

}

// Other routines
#186811

You must be logged in to reply to this topic.