On Friday 13 November 2009 04:36:56 Jim Burnes wrote:
> Good luck and let us know how it works.  It sounds like a good idea.  The
> objects encapsulate all their state, components press the button methods
> and events are pushed down the pipeline.

I've not had a chance for detailed comment, but two brief comments:
    * Yes, sending components through Axon/Kamaelia pipelines does already
       happen. (Indeed, we'll often send around ("inbox", component) pairs
       because that's defined as a service.

       Components that send components through inboxes include the TCP
       subsystem and pygame subsystem.

       Python-Axon pipelines are fully polymorphic, and as you suspected, fun.
       It's possible that typed inboxes may be useful though, but that's a
       different discussion.

    * If you pass in-active/passive objects - ie not components and not
      microprocesses - through the pipeline, because they don't have a local
      thread of control, this is generally thread safe.

      After all, when you put an object in an outbox, you no longer own it,
      and if you take something from an inbox you own it. This ensures the
      idea of single reader/single writer for any single piece of data, which
      eliminates whole classes of concurrency bugs. (You don't necessarily
      make a system much simpler, but you at least you know one sort of bug
      doesn't exist, and one that's normally awkward to sort out/find :-)

     BUT, if you put a component in the pipeline, you need to be careful.

     Specifically, this means a component is expecting a component on an
     inbox. In that case, your recipient component cannot know in advance
     whether the recipient is a generator-type component, threaded component,
     or similar. (eg a generator inside a threaded chassis, which has been
     proposed)

     This means the instant you start calling methods on components rather
     than sending them messages, you have to start thinking about thread
     safety. Now, if you're doing "read only", and not worried about the data
     going stale, that's one way of dealing with it. (I'm actually doing this
     in a project at the moment :-) that I can't really talk about
     publically )-:

     Picking a neutral example though if you had a component that kept track
     of a piece of information that changes often - such as directory size,
     the current time, how many users are connected, then that's probably OK.

     If you do need to change the component's state in some fashion though you
     have an issue. For example if you do this:
          somecomponent.somestore.append(something)

     And in its thread of control "somecomponent" does this in a loop: (say)
          self.somestore = []

     You have a clear issue depending on ordering of instructions.

     There are two ways round this:
         * Build something actor like based on threadsafe queues. This is what
            the scheduler does incidentally for handling .activate() calls in
            a threadsafe manner. ie accept the call, append the request to an
            inbound queue, and then inside the component's main thread service
            these calls there. (This cries out for decorator support :-)

         * The other is to use the STM code, which is probably far more better
           suited to this sort of task. http://www.kamaelia.org/STM describes
           it, but effectively you do this:

             1 Create an STM store.
             2 Allocate some names in it
             3 Grab a checkout containing those names/values
             4 Update the values in that checkout
             5 Check in/commit those values
             6 If you get a conflict, go back to 4

           ie the same as databases or version control (sans versions)

Bottom line really:
    * If possible send passive objects.

    * If sending components, ideally the safest way of dealing with them is to
       create a link to the component (using self.link) from a local outbox,
       send a message to it and get a message back. (by telling it where to
       respond to.)
       eg: (for one offs)
           somecomponent = self.recv("somebox")
           link = self.link((self,"adhoc"), (somecomponent, "inbox"))
           self.send( { "req" : "some request",
                            "callback" : (self, "someinbox") }, "adhoc")
           self.unlink(link)

       (Incidentally in Axon2 I'm planning on calling this "post" :-)

    * If that's inappropriate for whatever reason, you need to consider
       threadsafety, at that point, seriously consider using the STM code -
       it's what it's there for.

    * Finally, consider building something actor-like on top. Everyone who's
       built a mini-axon has actually built something actor-like, so this
       shouldn't be that bad, but there's no real direct support for ad-hoc
       actor like stuff as yet.

    * If you're merely reading values via a method call, that's fine.
      (Consider reading your balance at a cashpoint - that's generally OK :)
      However like the cashpoint analogy you have to assume that the value
      can change between you reading it and you using it. Using that value as
      the basis for an update is unsafe - for the reasons given in many many
      many books & talks on this :-)

[Incidentally Jim, I suspect you may be aware of these issues, but I'm also
  aware that the thread is archived, and may be read in future :-) ]

> I still think that you may need some sort of "bus" or "kernel" object for
> mailbox creation, but that may be a orthogonal issue. 

That's the purpose behind adaptive comms components really - since they can 
all create mailboxes.

Interestingly, whilst we don't do this in Kamaelia/Axon, MASCOT's equivalents 
to out inboxes/outboxes can exist independently of what we call components. 
It may be that upgrading inboxes/outboxes to fully fledged things may have 
some benefits.

For example, if I could send you a box that I allow you to share, it would 
provide an interesting means of creating a thread pool. (At present the way 
to do that really would be to send a Queue.Queue through a pipeline, and 
allow the recipients to all read from it, but that's a different 
conversation :-)

Regards,


Michael.
-- 
http://yeoldeclue.com/blog
http://twitter.com/kamaelian
http://www.kamaelia.org/Home

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"kamaelia" group.
To post to this group, send email to kamaelia@googlegroups.com
To unsubscribe from this group, send email to 
kamaelia+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/kamaelia?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to