getting all object that belong to one class


    Apr 24 2007 | 9:00 pm
    Hi there,
    I have an external called 'foo'.
    20 instances of 'foo' have been created in a Max patch.
    10 instances are in the main patch, the remaining 10 are in subpatchers
    at various depths.
    Now, I need all 20 instances of 'foo' to output certain information in
    response to a message that may be received in just ONE instance of any
    'foo' object.
    So, I am guessing I need a way to traverse all object instantiated that
    belong to the class 'foo'.
    I did check the SDK of course, but I could not find anything related to
    this.
    If someone could post an example or point me to some information about
    it, I would appreciate it.
    Thank you.
    - Luigi
    ------------------------------------------------------------
    THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
    ------------------------------------------------------------
    Do You Yahoo!?
    Tired of spam? Yahoo! Mail has the best spam protection around

    • Apr 24 2007 | 9:06 pm
      One way that doesn't involve any patcher traversal: maintain a global
      linked list of all instances of foo and iterate through it, sending
      each object the message.
      You could do it with patcher traversal, but it would be much more
      complicated.
      jb
      Am 24.04.2007 um 23:00 schrieb Luigi Castelli:
      > Hi there,
      >
      > I have an external called 'foo'.
      > 20 instances of 'foo' have been created in a Max patch.
      > 10 instances are in the main patch, the remaining 10 are in
      > subpatchers
      > at various depths.
      >
      > Now, I need all 20 instances of 'foo' to output certain information in
      > response to a message that may be received in just ONE instance of any
      > 'foo' object.
      >
      > So, I am guessing I need a way to traverse all object instantiated
      > that
      > belong to the class 'foo'.
      >
      > I did check the SDK of course, but I could not find anything
      > related to
      > this.
      >
      > If someone could post an example or point me to some information about
      > it, I would appreciate it.
      >
      > Thank you.
      >
      > - Luigi
      >
      >
      > ------------------------------------------------------------
      > THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT
      > AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY
      > UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS
      > PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE
      > SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF
      > THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      > ------------------------------------------------------------
      >
      >
      > Do You Yahoo!?
      > Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 24 2007 | 9:26 pm
      On 07-04-24, at 1400, Luigi Castelli wrote:
      > Hi there,
      >
      > I have an external called 'foo'.
      > 20 instances of 'foo' have been created in a Max patch.
      > 10 instances are in the main patch, the remaining 10 are in
      > subpatchers
      > at various depths.
      >
      > Now, I need all 20 instances of 'foo' to output certain information in
      > response to a message that may be received in just ONE instance of any
      > 'foo' object.
      >
      > So, I am guessing I need a way to traverse all object instantiated
      > that
      > belong to the class 'foo'.
      >
      > I did check the SDK of course, but I could not find anything
      > related to
      > this.
      >
      > If someone could post an example or point me to some information about
      > it, I would appreciate it.
      >
      I can't post a whole example, but the following method works for me:
      create a boxed object (foo)
      in the foo new routine, find or create a boxless object (foohelper)
      keep a pointer to foohelper in foo
      keep a linked list of boxed objects in foohelper
      each time you create or delete a foo, update the linked list in
      foohelper, and delete foohelper when all the foos are deleted (i.e.
      reference counting)
      keep global state in foohelper, and pass messages through as needed.
      This may be overly complicated for your needs, depending on the state
      that needs to be shared. In my case, I'm sharing a single network
      socket across a bunch of objects, so it has to live in its own
      object. You may be able to get away with a single global linked list
      that you manage in the foo new/free methods if you don't require that
      much sharing between your objects.
      here is some code to find/create a hidden object:
      t_symbol *hidden = gensym("foohidden");
      if (hidden != _sym_nothing && hidden->s_thing) {
      if (ob_messlist(hidden->s_thing) != foo_hidden_class->c_messlist) {
      error("name in use", 0);
      return NULL;
      } else {
      xx = (t_foo_hidden *)hidden->s_thing;
      }
      } else {
      xx = foo_hidden_new(hidden);
      hidden->s_thing = (t_object *)xx;
      }
      Essentially this looks up an object by name in the global max symbol
      table. If it doesn't exist, it creates a new one and associates it
      with that symbol.
      If you need more code snips or explanations, let me know.
      r.
    • Apr 25 2007 | 5:59 am
      Thank you Jeremy and Ritchie,
      I implemented your suggestion and it works like a charm.
      I don't need too much sharing between my objects so the simple global
      linked list solution is what I went for.
      Now I find myself iterating through the linked list a lot, so I was
      wondering if - for the sake of efficiency - there is any difference
      between these two constructs:
      for (p = head; p; p = p->next) {
      // do something
      }
      and
      p = head;
      while (p) {
      p = p->next;
      }
      ...or is there any reason why I should want one over the other ?
      Thanks guys.
      - Luigi
      --- Ritchie Argue wrote:
      > On 07-04-24, at 1400, Luigi Castelli wrote:
      > > Hi there,
      > >
      > > I have an external called 'foo'.
      > > 20 instances of 'foo' have been created in a Max patch.
      > > 10 instances are in the main patch, the remaining 10 are in
      > > subpatchers
      > > at various depths.
      > >
      > > Now, I need all 20 instances of 'foo' to output certain information
      > in
      > > response to a message that may be received in just ONE instance of
      > any
      > > 'foo' object.
      > >
      > > So, I am guessing I need a way to traverse all object instantiated
      >
      > > that
      > > belong to the class 'foo'.
      > >
      > > I did check the SDK of course, but I could not find anything
      > > related to
      > > this.
      > >
      > > If someone could post an example or point me to some information
      > about
      > > it, I would appreciate it.
      > >
      > I can't post a whole example, but the following method works for me:
      >
      > create a boxed object (foo)
      > in the foo new routine, find or create a boxless object (foohelper)
      > keep a pointer to foohelper in foo
      > keep a linked list of boxed objects in foohelper
      > each time you create or delete a foo, update the linked list in
      > foohelper, and delete foohelper when all the foos are deleted (i.e.
      > reference counting)
      > keep global state in foohelper, and pass messages through as needed.
      >
      > This may be overly complicated for your needs, depending on the state
      >
      > that needs to be shared. In my case, I'm sharing a single network
      > socket across a bunch of objects, so it has to live in its own
      > object. You may be able to get away with a single global linked list
      >
      > that you manage in the foo new/free methods if you don't require that
      >
      > much sharing between your objects.
      >
      > here is some code to find/create a hidden object:
      >
      > t_symbol *hidden = gensym("foohidden");
      >
      > if (hidden != _sym_nothing && hidden->s_thing) {
      > if (ob_messlist(hidden->s_thing) != foo_hidden_class->c_messlist) {
      > error("name in use", 0);
      > return NULL;
      > } else {
      > xx = (t_foo_hidden *)hidden->s_thing;
      > }
      > } else {
      > xx = foo_hidden_new(hidden);
      > hidden->s_thing = (t_object *)xx;
      > }
      >
      > Essentially this looks up an object by name in the global max symbol
      >
      > table. If it doesn't exist, it creates a new one and associates it
      > with that symbol.
      >
      > If you need more code snips or explanations, let me know.
      >
      > r.
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 25 2007 | 6:25 am
      On 07-04-24, at 2259, Luigi Castelli wrote:
      > Thank you Jeremy and Ritchie,
      >
      > I implemented your suggestion and it works like a charm.
      > I don't need too much sharing between my objects so the simple global
      > linked list solution is what I went for.
      >
      > Now I find myself iterating through the linked list a lot, so I was
      > wondering if - for the sake of efficiency - there is any difference
      > between these two constructs:
      >
      I would recommend (a) worrying about readability over efficiency, and
      to that end (b) looking at ext_linklist.h, and not do any of the low-
      level linklist stuff yourself.
      r.
    • Apr 25 2007 | 11:42 am
      On Apr 24, 2007, at 11:25 PM, Ritchie Argue wrote:
      > I would recommend (a) worrying about readability over efficiency,
      > and to that end (b) looking at ext_linklist.h, and not do any of
      > the low-level linklist stuff yourself.
      Not to mention thread safety. If your linked list may be modified in
      both the low priority and high priority threads, you'll need to use
      some kind of thread safe locks (see ext_systhread.h and online
      documentation about threads and locks like the following sample
      chapters from Modern Operating Systems: http://www.cs.vu.nl/~ast/
      books/mos2/samples.html
      The linklist calls take care of this for you. However, while they
      will work in a DSP perform method, you may not want to use these
      functions internal to a DSP perform method for performance reasons,
      in which case you might want to use some lighter weight means of
      achieving synchronization than OS supplied mutexes.
      Though, as *always*, optimize last, and even then use profiling tools
      and focus on code which is the bottle neck. Worrying about whether a
      while loop or a for loop is more efficient is typically the least
      efficient use of your mind. On OS X, Apple's Shark is a great
      profiling tool.
      -Joshua
    • Apr 25 2007 | 9:36 pm
      Quote: Luigi Castelli wrote on Wed, 25 April 2007 07:59
      ----------------------------------------------------
      > for (p = head; p; p = p->next) {
      > // do something
      > }
      >
      > and
      >
      > p = head;
      > while (p) {
      > p = p->next;
      > }
      >
      > ...or is there any reason why I should want one over the other ?
      ----------------------------------------------------
      According to the C-spec the two are identical. Two different ways of generating the same machine code. There is certainly no difference in efficiency.
      Either construct can be made thread-safe.
      The for-loop has a certain atomicity in its syntax that some people may prefer.
    • Apr 26 2007 | 12:51 am
      Hi guys,
      first of all, thanks Peter for your explanation.
      It seems from what Joshua and Ritchie are saying that I am better off
      using the ext_linklist.h API to manage my linked list. That way I don't
      have to worry about thread safety, and don't have to come up with my
      own linked list functions. Makes sense...
      Now, the reason why I didn't go with the ext_linklist.h API yet, is
      because I am not sure if it provides the low level functionality I
      need. To be more specific, in my code I am acually managing two linked
      lists.
      In various parts of the code I need to perform the following action:
      for (a = a_head; a; a = a->next) {
      for (b = b_head; b; b = b->next) {
      // do something
      }
      }
      Is nesting two linked list like that something possible with the
      ext_linklist.h API ?
      Or am I now better off implementing my own linked list functions and
      deal with all the thread issues of the case ?
      Thanks.
      - Luigi
      --- Peter Castine wrote:
      >
      > Quote: Luigi Castelli wrote on Wed, 25 April 2007 07:59
      > ----------------------------------------------------
      > > for (p = head; p; p = p->next) {
      > > // do something
      > > }
      > >
      > > and
      > >
      > > p = head;
      > > while (p) {
      > > p = p->next;
      > > }
      > >
      > > ...or is there any reason why I should want one over the other ?
      >
      > ----------------------------------------------------
      >
      > According to the C-spec the two are identical. Two different ways of
      > generating the same machine code. There is certainly no difference in
      > efficiency.
      >
      > Either construct can be made thread-safe.
      >
      > The for-loop has a certain atomicity in its syntax that some people
      > may prefer.
      > --
      > -------------- http://www.bek.no/~pcastine/Litter/
      > -------------
      > Peter Castine +--> Litter Power & Litter Bundle for
      > Jitter
      >
      > iCE: Sequencing, Recording & Interface Building for Max/MSP
      > Extremely cool http://www.dspaudio.com/
      >
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 26 2007 | 2:02 am
      On Apr 25, 2007, at 5:51 PM, Luigi Castelli wrote:
      > Is nesting two linked list like that something possible with the
      > ext_linklist.h API ?
      > Or am I now better off implementing my own linked list functions and
      > deal with all the thread issues of the case ?
      Do you mean a list of lists? Sure. the nodes of the list can be any
      object (or a pointer or integer masquerading as an object):
      t_linklist *mainlist = linklist_new();
      t_linklist *sublist = linklist_new();
      linklist_append(mainlist,(t_object *)sublist);
      You might find the methodall or funall routines useful for iteration.
      If you have a specific question, feel free to post it with relevant
      code.
      -Joshua
    • Apr 26 2007 | 2:39 am
      Thanks Joshua,
      will do...
      Just for my own curiosity, does the ext_linklist API implement singly
      linked or doubly linked lists under the hood ?
      - Luigi
      --- Joshua Kit Clayton wrote:
      >
      > On Apr 25, 2007, at 5:51 PM, Luigi Castelli wrote:
      >
      > > Is nesting two linked list like that something possible with the
      > > ext_linklist.h API ?
      > > Or am I now better off implementing my own linked list functions
      > and
      > > deal with all the thread issues of the case ?
      >
      > Do you mean a list of lists? Sure. the nodes of the list can be any
      > object (or a pointer or integer masquerading as an object):
      >
      > t_linklist *mainlist = linklist_new();
      > t_linklist *sublist = linklist_new();
      > linklist_append(mainlist,(t_object *)sublist);
      >
      > You might find the methodall or funall routines useful for iteration.
      >
      > If you have a specific question, feel free to post it with relevant
      > code.
      >
      > -Joshua
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 26 2007 | 10:31 am
      Joshua,
      upon more careful reading of your answer I am not entirely sure I can
      do what I want.
      I don't really mean a list of lists, but a way of nesting iterations
      of linked lists.
      here is a more specific example:
      how would you do the following with the ext_linklist.h API ?
      void myfunction (void)
      {
      t_myobject *obj = NULL;
      t_mydevice *dev = NULL;
      t_atom a[1];
      obj = myobject_list_head; // point to head of list 1
      while (obj) {
      outlet_anything(obj->out, _sym_clear, 0, 0L);
      dev = mydevice_list_head; // point to head of list 2
      while (dev) {
      atom_setsym(a, gensym(dev->name));
      outlet_anything(obj->out, _sym_append, 1, a);
      dev = dev->next;
      }
      obj = obj->next;
      }
      }
      If you can confirm to me that the above if possible with the
      ext_linklist.h API I will be happy to use it. Otherwise I am gonna have
      to find another solution.
      Thanks again.
      - Luigi
      --- Joshua Kit Clayton wrote:
      >
      > On Apr 25, 2007, at 5:51 PM, Luigi Castelli wrote:
      >
      > > Is nesting two linked list like that something possible with the
      > > ext_linklist.h API ?
      > > Or am I now better off implementing my own linked list functions
      > and
      > > deal with all the thread issues of the case ?
      >
      > Do you mean a list of lists? Sure. the nodes of the list can be any
      > object (or a pointer or integer masquerading as an object):
      >
      > t_linklist *mainlist = linklist_new();
      > t_linklist *sublist = linklist_new();
      > linklist_append(mainlist,(t_object *)sublist);
      >
      > You might find the methodall or funall routines useful for iteration.
      >
      > If you have a specific question, feel free to post it with relevant
      > code.
      >
      > -Joshua
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 26 2007 | 11:17 am
      um, why not do it the same way?
      t_linklist *objlist;
      t_linklist *devlist;
      // assuming that you've put some stuff in these lists
      long objsize, devsize;
      long i, j;
      objsize = linklist_getsize(objlist);
      devsize = linklist_devsize(devlist);
      for (i = 0; i < objsize; i++) {
      t_myobject *obj = linklist_getindex(objlist, i);
      for (j = 0; j < devsize; j++) {
      t_mydevice *dev = linklist_getindex(devlist, i);
      atom_setsym(a, gensym(dev->name));
      outlet_anything(obj->out, _sym_append, 1, a);
      }
      }
      This is just email-client code, not tested. You should but some error
      checking in, and ensure that you're using the t_linklists properly,
      but this is exactly what you've done.
      If you are putting your own objects (which you want to free yourself)
      into the linked lists, don't forget to use linklist_chuck(), instead
      of freeobject(mylinkedlist). linklist_chuck() frees the list without
      freeing the objects contained in it. freeobject() will free both the
      list, and all objects contained by it.
      jb
      Am 26.04.2007 um 12:31 schrieb Luigi Castelli:
      > Joshua,
      >
      > upon more careful reading of your answer I am not entirely sure I can
      > do what I want.
      > I don't really mean a list of lists, but a way of nesting iterations
      > of linked lists.
      >
      > here is a more specific example:
      >
      > how would you do the following with the ext_linklist.h API ?
      >
      > void myfunction (void)
      > {
      > t_myobject *obj = NULL;
      > t_mydevice *dev = NULL;
      > t_atom a[1];
      >
      > obj = myobject_list_head; // point to head of list 1
      > while (obj) {
      > outlet_anything(obj->out, _sym_clear, 0, 0L);
      > dev = mydevice_list_head; // point to head of list 2
      > while (dev) {
      > atom_setsym(a, gensym(dev->name));
      > outlet_anything(obj->out, _sym_append, 1, a);
      > dev = dev->next;
      > }
      > obj = obj->next;
      > }
      > }
      >
      > If you can confirm to me that the above if possible with the
      > ext_linklist.h API I will be happy to use it. Otherwise I am gonna
      > have
      > to find another solution.
      >
      > Thanks again.
      >
      > - Luigi
      >
      >
      >
      >
      >
      >
      > --- Joshua Kit Clayton wrote:
      >
      >>
      >> On Apr 25, 2007, at 5:51 PM, Luigi Castelli wrote:
      >>
      >>> Is nesting two linked list like that something possible with the
      >>> ext_linklist.h API ?
      >>> Or am I now better off implementing my own linked list functions
      >> and
      >>> deal with all the thread issues of the case ?
      >>
      >> Do you mean a list of lists? Sure. the nodes of the list can be any
      >> object (or a pointer or integer masquerading as an object):
      >>
      >> t_linklist *mainlist = linklist_new();
      >> t_linklist *sublist = linklist_new();
      >> linklist_append(mainlist,(t_object *)sublist);
      >>
      >> You might find the methodall or funall routines useful for iteration.
      >>
      >> If you have a specific question, feel free to post it with relevant
      >> code.
      >>
      >> -Joshua
      >>
      >
      >
      >
      > ------------------------------------------------------------
      > THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT
      > AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY
      > UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS
      > PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE
      > SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF
      > THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      > ------------------------------------------------------------
      >
      >
      > Do You Yahoo!?
      > Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 26 2007 | 5:44 pm
      of course....
      thanks Jeremy and sorry for the silly question. I wasn't thinking...
      Now - as far as thread safety goes - when I am traversing lists like in
      my (your) example, I don't need to use any locking mechanism such as
      critical regions or systhread calls, do I ?
      I understand everything regarding thread safety is already taken care
      for you by the ext_linklist API. Am I correct in making this assumption
      ?
      - Luigi
      --- Jeremy Bernstein wrote:
      > um, why not do it the same way?
      >
      > t_linklist *objlist;
      > t_linklist *devlist;
      >
      > // assuming that you've put some stuff in these lists
      >
      > long objsize, devsize;
      > long i, j;
      >
      > objsize = linklist_getsize(objlist);
      > devsize = linklist_devsize(devlist);
      >
      > for (i = 0; i < objsize; i++) {
      > t_myobject *obj = linklist_getindex(objlist, i);
      > for (j = 0; j < devsize; j++) {
      > t_mydevice *dev = linklist_getindex(devlist, i);
      >
      > atom_setsym(a, gensym(dev->name));
      > outlet_anything(obj->out, _sym_append, 1, a);
      > }
      > }
      >
      > This is just email-client code, not tested. You should but some error
      >
      > checking in, and ensure that you're using the t_linklists properly,
      > but this is exactly what you've done.
      >
      > If you are putting your own objects (which you want to free yourself)
      >
      > into the linked lists, don't forget to use linklist_chuck(), instead
      >
      > of freeobject(mylinkedlist). linklist_chuck() frees the list without
      >
      > freeing the objects contained in it. freeobject() will free both the
      >
      > list, and all objects contained by it.
      >
      > jb
      >
      > Am 26.04.2007 um 12:31 schrieb Luigi Castelli:
      >
      > > Joshua,
      > >
      > > upon more careful reading of your answer I am not entirely sure I
      > can
      > > do what I want.
      > > I don't really mean a list of lists, but a way of nesting
      > iterations
      > > of linked lists.
      > >
      > > here is a more specific example:
      > >
      > > how would you do the following with the ext_linklist.h API ?
      > >
      > > void myfunction (void)
      > > {
      > > t_myobject *obj = NULL;
      > > t_mydevice *dev = NULL;
      > > t_atom a[1];
      > >
      > > obj = myobject_list_head; // point to head of list 1
      > > while (obj) {
      > > outlet_anything(obj->out, _sym_clear, 0, 0L);
      > > dev = mydevice_list_head; // point to head of list 2
      > > while (dev) {
      > > atom_setsym(a, gensym(dev->name));
      > > outlet_anything(obj->out, _sym_append, 1, a);
      > > dev = dev->next;
      > > }
      > > obj = obj->next;
      > > }
      > > }
      > >
      > > If you can confirm to me that the above if possible with the
      > > ext_linklist.h API I will be happy to use it. Otherwise I am gonna
      >
      > > have
      > > to find another solution.
      > >
      > > Thanks again.
      > >
      > > - Luigi
      > >
      > >
      > >
      > >
      > >
      > >
      > > --- Joshua Kit Clayton wrote:
      > >
      > >>
      > >> On Apr 25, 2007, at 5:51 PM, Luigi Castelli wrote:
      > >>
      > >>> Is nesting two linked list like that something possible with the
      > >>> ext_linklist.h API ?
      > >>> Or am I now better off implementing my own linked list functions
      > >> and
      > >>> deal with all the thread issues of the case ?
      > >>
      > >> Do you mean a list of lists? Sure. the nodes of the list can be
      > any
      > >> object (or a pointer or integer masquerading as an object):
      > >>
      > >> t_linklist *mainlist = linklist_new();
      > >> t_linklist *sublist = linklist_new();
      > >> linklist_append(mainlist,(t_object *)sublist);
      > >>
      > >> You might find the methodall or funall routines useful for
      > iteration.
      > >>
      > >> If you have a specific question, feel free to post it with
      > relevant
      > >> code.
      > >>
      > >> -Joshua
      > >>
      > >
      > >
      > >
      > > ------------------------------------------------------------
      > > THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT
      > > AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY
      > > UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS
      > > PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE
      > > SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF
      >
      > > THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      > > ------------------------------------------------------------
      > >
      > >
      > > Do You Yahoo!?
      > > Tired of spam? Yahoo! Mail has the best spam protection around
      > > http://mail.yahoo.com
      >
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • Apr 26 2007 | 5:52 pm
      Correct.
      jb
      Am 26.04.2007 um 19:44 schrieb Luigi Castelli:
      > of course....
      >
      > thanks Jeremy and sorry for the silly question. I wasn't thinking...
      >
      > Now - as far as thread safety goes - when I am traversing lists
      > like in
      > my (your) example, I don't need to use any locking mechanism such as
      > critical regions or systhread calls, do I ?
      >
      > I understand everything regarding thread safety is already taken care
      > for you by the ext_linklist API. Am I correct in making this
      > assumption
      > ?
      >
      > - Luigi
    • Apr 26 2007 | 8:02 pm
      On Apr 26, 2007, at 10:44 AM, Luigi Castelli wrote:
      > Now - as far as thread safety goes - when I am traversing lists
      > like in
      > my (your) example, I don't need to use any locking mechanism such as
      > critical regions or systhread calls, do I ?
      I might regret this as it could serve to confuse the discussion
      rather than clarify, but let me actually qualify Jeremy's "correct"
      statement. There will be no linked list corruption, as these calls
      are threadsafe with respect to modifying the *data structure*.
      However, there *may* be some need for using some thread locking
      mechanism like mutexes if you need to have a compound logical
      operation complete without modification to the data structures being
      used.
      For example if you wanted to remove an item off of the tail of the
      list and put it at the head of the list, this is a compound logical
      operation made up of an element removal and insertion. While the
      removal and insertion are *each* threadsafe w/r/t the datastructure
      manipulation, there are situations where you would want to make sure
      this operation were completed before some other thread did something
      like sort the list, or free all members, or whatever. In these types
      of scenarios, you will need to implement whatever thread safety you
      need to protect the compound logical operation as a complete and
      uninterruptible "transaction".
      If you want to learn more about this sort of thing, I'll put another
      plug for Tanenbaum's "Modern Operating Systems", and suggest you
      perform some searches on terms like "thread safety compound
      transaction".
      -Joshua
    • Apr 27 2007 | 8:47 am
      Hi Joshua,
      thanks for the clarification. It makes perfect sense.
      All the actions I am performing with the linked list are:
      - create a list
      - add a node to the list
      - delete a node from the list
      - traverse the list
      - delete whole list
      So, I don't think I am performing any compound logical operation. The
      only actions that actually modify the list is adding a node or deleting
      a node, and - of course - disposing of the whole list. However I don't
      think these actions would fall under the compound operation category.
      Please correct me if I am wrong here...
      Could you please post a simple example of the ext_linklist API usage ?
      Let's say I have a struct declared as following:
      typedef struct _node {
      long *ptr;
      long a;
      long b;
      long c;
      } t_node;
      How would I create a list, append and remove nodes ?
      How would I traverse it ? How would I dispose the whole list ?
      I am also not sure what the t_llelem struct is for.
      And finally what's the difference between linklist_append and
      linklist_appendnode ?
      I think I am generally not clear about how I would go to use it.
      Thank you.
      - Luigi
      --- Joshua Kit Clayton wrote:
      >
      > On Apr 26, 2007, at 10:44 AM, Luigi Castelli wrote:
      >
      > > Now - as far as thread safety goes - when I am traversing lists
      > > like in
      > > my (your) example, I don't need to use any locking mechanism such
      > as
      > > critical regions or systhread calls, do I ?
      >
      > I might regret this as it could serve to confuse the discussion
      > rather than clarify, but let me actually qualify Jeremy's "correct"
      > statement. There will be no linked list corruption, as these calls
      > are threadsafe with respect to modifying the *data structure*.
      > However, there *may* be some need for using some thread locking
      > mechanism like mutexes if you need to have a compound logical
      > operation complete without modification to the data structures being
      >
      > used.
      >
      > For example if you wanted to remove an item off of the tail of the
      > list and put it at the head of the list, this is a compound logical
      > operation made up of an element removal and insertion. While the
      > removal and insertion are *each* threadsafe w/r/t the datastructure
      > manipulation, there are situations where you would want to make sure
      >
      > this operation were completed before some other thread did something
      >
      > like sort the list, or free all members, or whatever. In these types
      >
      > of scenarios, you will need to implement whatever thread safety you
      > need to protect the compound logical operation as a complete and
      > uninterruptible "transaction".
      >
      > If you want to learn more about this sort of thing, I'll put another
      >
      > plug for Tanenbaum's "Modern Operating Systems", and suggest you
      > perform some searches on terms like "thread safety compound
      > transaction".
      >
      > -Joshua
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • May 01 2007 | 12:09 am
      Hi guys,
      I would appreciate if someone could post a few usage examples of the
      ext_linklist.h API.
      I would love to see something basic like how to create a new list, add
      nodes, remove nodes, traverse list and delete list.
      Also, I am a little confused about the t_llelem type and difference
      between linklist_appendnode and linklist_append or between linklist_new
      and linklistelem_new...
      Thanks for any clarification.
      - Luigi
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • May 01 2007 | 2:32 am
      On Apr 30, 2007, at 5:09 PM, Luigi Castelli wrote:
      > I would appreciate if someone could post a few usage examples of the
      > ext_linklist.h API.
      >
      > I would love to see something basic like how to create a new list, add
      > nodes, remove nodes, traverse list and delete list.
      Not a lot of time for this sort of thing, but here's the basics from
      an email client (might be a few typos). The only real thing you need
      to pay attention to is if you're using objects (created with
      object_new()) or structs. If the latter you need to be responsible
      for freeing the structs yourself and using "chuck" calls to remove
      from list without calling freeobject().
      // make a list
      t_linklist *list = linklist_new();
      // add an object (or struct) to a list
      linklist_append(list,(t_object *)myobject);
      // remove object at index 0 from the list, freeing the object with
      freeobject() internally (not appropriate for structs)
      linklist_delete(list,0);
      // remove object or struct at index 0 from the list, without freeing
      the object or struct
      linklist_chuckindex(list,0);
      // retrieve an object or struct at index 0
      myobject = (t_myobject *) linklist_getindex(list,0);
      // call a method on all objects in list (not appropriate for structs)
      linklist_methodall(list,gensym("foo"));
      // call a function on all objects in list
      linklist_functionall(list,(method)myfunction,(void *)mydata);
      //free a list, freeing all objects (not appropriate for structs)
      linklist_free(list);
      //free a list, without freeing all objects or structs
      linklist_chuck(list);
      > Also, I am a little confused about the t_llelem type and difference
      > between linklist_appendnode and linklist_append or between
      > linklist_new
      > and linklistelem_new...
      You can safely ignore t_llelem and all "node" related calls which are
      for internal use only.
      -Joshua
    • May 01 2007 | 7:26 am
      Hi there,
      does anybody know if it's faster to compare strings with strings or
      symbols with symbols ?
      Example:
      -------------------
      char myString1[16];
      char myString2[16];
      myString1 = "maxmspjitter"
      myString2 = "maxmspjitter"
      if (strcmp(myString1, myString2) == 0) {
      // do something
      }
      -------------------
      or
      -------------------
      t_symbol *mySymbol1;
      t_symbol *myStmbol2;
      mySymbol1 = gensym("maxmspjitter");
      mySymbol2 = gensym("maxmspjitter");
      if (mySymbol1 == mySymbol2) {
      // do something
      }
      -------------------
      Thank you.
      - Luigi
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
    • May 01 2007 | 7:55 am
      Hi Luigi,
      comparing symbols is faster, as it's just comparing two pointers
      (which are simply integer numbers).
      strcmp involves comparing the bytes the string pointers point two,
      and some more logic too.
      all the best,
      Thomas
      Am 01.05.2007 um 09:26 schrieb Luigi Castelli:
      > Hi there,
      >
      > does anybody know if it's faster to compare strings with strings or
      > symbols with symbols ?
      >
      > Example:
      >
      > -------------------
      > char myString1[16];
      > char myString2[16];
      >
      > myString1 = "maxmspjitter"
      > myString2 = "maxmspjitter"
      >
      > if (strcmp(myString1, myString2) == 0) {
      > // do something
      > }
      > -------------------
      >
      > or
      >
      > -------------------
      > t_symbol *mySymbol1;
      > t_symbol *myStmbol2;
      >
      > mySymbol1 = gensym("maxmspjitter");
      > mySymbol2 = gensym("maxmspjitter");
      >
      > if (mySymbol1 == mySymbol2) {
      > // do something
      > }
      > -------------------
      >
      > Thank you.
      >
      > - Luigi
      >
      >
      > ------------------------------------------------------------
      > THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT
      > AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY
      > UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS
      > PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE
      > SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF
      > THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      > ------------------------------------------------------------
      >
      >
      > Do You Yahoo!?
      > Tired of spam? Yahoo! Mail has the best spam protection around
      > http://mail.yahoo.com
      >
      Thomas Grill
    • May 01 2007 | 7:58 am
      sorry, i forgot....
      what i wrote is only true if the gensym in your code is not taken
      into account.
      If your symbols are constant (have a known string content) you could
      cache them beforehand e.g. by storing the symbol pointer in a static
      variable.
      greetings,
      Thomas
      Am 01.05.2007 um 09:26 schrieb Luigi Castelli:
      > Hi there,
      >
      > does anybody know if it's faster to compare strings with strings or
      > symbols with symbols ?
      >
      > Example:
      >
      > -------------------
      > char myString1[16];
      > char myString2[16];
      >
      > myString1 = "maxmspjitter"
      > myString2 = "maxmspjitter"
      >
      > if (strcmp(myString1, myString2) == 0) {
      > // do something
      > }
      > -------------------
      >
      > or
      >
      > -------------------
      > t_symbol *mySymbol1;
      > t_symbol *myStmbol2;
      >
      > mySymbol1 = gensym("maxmspjitter");
      > mySymbol2 = gensym("maxmspjitter");
      >
      > if (mySymbol1 == mySymbol2) {
      > // do something
      > }
      > -------------------
      >
      > Thank you.
      >
      > - Luigi
      >
      >
      > ------------------------------------------------------------
      > THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT
      > AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY
      > UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS
      > PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE
      > SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF
      > THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      > ------------------------------------------------------------
      >
      >
      > Do You Yahoo!?
      > Tired of spam? Yahoo! Mail has the best spam protection around
      > http://mail.yahoo.com
      >
      Thomas Grill
    • May 01 2007 | 5:44 pm
      I think my thought process as to the trade off is: am I going to re-
      use the strings? If you think that you'll have a bunch of the same
      strings coming in, or you'll be comparing a bunch of inputs to a small
      number of cached strings, then by all means gensyms and use the string-
      table goodness built into max. If not, then you'll be wasting a bunch
      of space, as the gensym function probably keeps the strings around for
      the duration of the max process.
      _Mark
      On May 1, 2007, at 12:58 AM, Thomas Grill wrote:
      > sorry, i forgot....
      > what i wrote is only true if the gensym in your code is not taken
      > into account.
      > If your symbols are constant (have a known string content) you could
      > cache them beforehand e.g. by storing the symbol pointer in a static
      > variable.
      >
      > greetings,
      > Thomas
      >
      > Am 01.05.2007 um 09:26 schrieb Luigi Castelli:
      >
      >> Hi there,
      >>
      >> does anybody know if it's faster to compare strings with strings or
      >> symbols with symbols ?
      >>
      >> Example:
      >>
      >> -------------------
      >> char myString1[16];
      >> char myString2[16];
      >>
      >> myString1 = "maxmspjitter"
      >> myString2 = "maxmspjitter"
      >>
      >> if (strcmp(myString1, myString2) == 0) {
      >> // do something
      >> }
      >> -------------------
      >>
      >> or
      >>
      >> -------------------
      >> t_symbol *mySymbol1;
      >> t_symbol *myStmbol2;
      >>
      >> mySymbol1 = gensym("maxmspjitter");
      >> mySymbol2 = gensym("maxmspjitter");
      >>
      >> if (mySymbol1 == mySymbol2) {
      >> // do something
      >> }
      >> -------------------
      >>
      >> Thank you.
      >>
      >> - Luigi
      >>
      >>
      >> ------------------------------------------------------------
      >> THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT
      >> AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY
      >> UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS
      >> PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE
      >> SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF
      >> THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      >> ------------------------------------------------------------
      >>
      >>
      >> Do You Yahoo!?
      >> Tired of spam? Yahoo! Mail has the best spam protection around
      >> http://mail.yahoo.com
      >>
      >
      > Thomas Grill
      > http://grrrr.org
      >
      >
    • May 01 2007 | 6:10 pm
      On 1 May 2007, at 08:26, Luigi Castelli wrote:
      > t_symbol *mySymbol1;
      > t_symbol *myStmbol2;
      >
      > mySymbol1 = gensym("maxmspjitter");
      > mySymbol2 = gensym("maxmspjitter");
      In this case, you're not testing the comparison of symbol pointers
      (which should be very fast), but the speed of the hash function. I
      would certainly expect the hash to be slower than strcmp(), but that
      won't matter if the gensym() calls have been done already (such as by
      Max itself).
      -- N.
      Nick Rothwell / Cassiel.com Limited
      www.cassiel.com
      www.myspace.com/cassieldotcom
      www.loadbang.net
    • May 01 2007 | 6:36 pm
      Mark, Nick, Thomas,
      thanks for your replies guys...
      I am dealing with 4 pairs of strings. (8 strings in total)
      Each pair is made of two matching strings. (i.e. they are the same)
      I am calling gensym on all 4 pairs of strings at object creation time.
      (myobject_new method)
      After that I am not touching the strings or symbols any more.
      During runtime I need a function to compare every string/symbol with
      the other eight to find the matching pair. Some kind of 4x4 symbol
      matrix, basically.
      That's why I was wondering about speed and efficiency since the
      comparisons end up being many.
      It seems to understand from your posts that in this case the fastest
      way is to compare symbols - or symbol pointers to be more precise -
      instead of strings.
      Thanks for your help.
      - Luigi
      --- Nick Rothwell wrote:
      >
      > On 1 May 2007, at 08:26, Luigi Castelli wrote:
      >
      > > t_symbol *mySymbol1;
      > > t_symbol *myStmbol2;
      > >
      > > mySymbol1 = gensym("maxmspjitter");
      > > mySymbol2 = gensym("maxmspjitter");
      >
      > In this case, you're not testing the comparison of symbol pointers
      > (which should be very fast), but the speed of the hash function. I
      > would certainly expect the hash to be slower than strcmp(), but that
      >
      > won't matter if the gensym() calls have been done already (such as by
      >
      > Max itself).
      >
      > -- N.
      >
      >
      > Nick Rothwell / Cassiel.com Limited
      > www.cassiel.com
      > www.myspace.com/cassieldotcom
      > www.loadbang.net
      >
      >
      >
      >
      ------------------------------------------------------------
      THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
      ------------------------------------------------------------
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around