4 Simple Component - Microprocesses with standard external interfaces

Exercise: Write a class called component that subclasses microprocess with the following...

Attributes:

  • self.boxes - this should be a dictionary of the following form:
    • { "inbox": [],"outbox": [] }
    Clearly this allows for more inboxes and outboxes, but at this stage we'll keep things simple.

Behaviour: (methods)

  • As before an __init__ for anything you need (eg attributes above :)
  • send(self, value, boxname)
    • This method takes the value and appends it to the end of the list associated with the boxname.
    • That is if I do:
      • self.send(value, boxname)
      Then given the suggested implementation of boxes above the following should be true afterwards:
        self.boxes[boxname][-1] == value
      ie the last value in the list associated with the boxname is the value we sent to that outbox. More explicitly, if the value of self.boxes was this beforehand:
        self.boxes == { "inbox" : [],
        "outbox" : ["hello", "world"] }
      And the following call had been made:
        self.send("gameover","outbox")
      The self.boxes would look like this afterwards:
        self.boxes == { "inbox" : [],
        "outbox" : ["hello", "world", "gameover"] }
  • recv(self, boxname)
    • This is the logical opposite of sending. Rather than appending a value at the end of the send queue, we take the first value in the queue.
    • Behaviourally, given a starting value of self.boxes:
      • self.boxes == { "inbox" : ["hello", "world", "gameover"],
        "outbox" : [] }
      Then I would expect the following behaviour code....
        print "GRABBING DATA", self.recv("inbox")
        print "GRABBING DATA", self.recv("inbox")
        print "GRABBING DATA", self.recv("inbox")
        print "GRABBING DATA", self.recv("inbox")
      ... to display the following sort of behaviour:
        GRABBING DATA hello
        GRABBING DATA world
        GRABBING DATA gameover
        GRABBING DATA
        Traceback (most recent call last):
        File "", line 1, in ?
        File "", line 7, in main
        File "", line 8, in recv
        IndexError: list index out of range
      The value of self.boxes should also change as follows after each call:
        self.boxes == { "inbox" : ["hello", "world", "gameover"], # At start
        "outbox" : [] }
        self.recv("inbox")
        self.boxes == { "inbox" : ["world", "gameover"],
        "outbox" : [] }
        self.recv("inbox")
        self.boxes == { "inbox" : [ "gameover"],
        "outbox" : [] }
        self.recv("inbox")
        self.boxes == { "inbox" : [],
        "outbox" : [] }
        self.recv("inbox")
        *** BANG*** (For the moment, we don't care what exception gets thrown)
  • dataReady(self, boxname)
    • This should return the length of the list associated with the boxname.

      For example, given:
      • self.boxes == { "inbox" : ["hello", "world", "gameover"],
        "control" : ["world", "gameover"],
        "feedback" : [],
        "outbox" : [] }
      The following behaviour is expected:
        print self.dataReady("inbox")
        -> displays 3

        print self.dataReady("control")
        -> displays 2

        print self.dataReady("feedback")
        -> displays 0

        print self.dataReady("somerandomname")
        -> causes a KeyError: somerandomname exception to be thrown

Answer HiddenShow Answer

Answer:

  • Select from the above tabs to show the answer!

Discussion:

Ok that's a fairly long description, but a fairly simple implementation. So what's this done? It's enabled us to send data to a running generator and receive data back. We're not worried what the generator is doing at any point in time, and so the communications between us and the generator (or between generators) is asynchronous.

An extension to the suggested __init__ is to do the following:

    class component(microprocess):
    Boxes = {
    "inbox" : "This is where we expect to receive messages",
    "outbox" : "This is where we send results/messages"
    }
    def __init__(self):
    super(simplecomponent, self).__init__()
    self.boxes = {}
    for box in self.Boxes:
    self.boxes[box] = list()

This small extension means that classes subclassing component can have a different set of inboxes and outboxes. For example:

    class spinnyThing(component):
    Boxes = {
    "inbox" : "As per default",
    "outbox" : "As per defaults",
    "rotation" : "Expect an integer between 0 and 359 (degrees)",
    }

That said, components by themselves are relatively boring. Unless we have some way of moving the data between generators we haven't gained anything (really) beyond the printer example above. So we need someone/something that can move data/messages from outboxes and deliver to inboxes...


Kamaelia is an open source project originated from and guided by BBC Research. For more information browse the site or get in contact.

This is an ongoing community based development site. As a result the contents of this page is the opinions of the contributors of the pages involved not the organisations involved. Specificially, this page may contain personal views which are not the views of the BBC. (the site is powered by a wiki engine)

(C) Copyright 2008 Kamaelia Contributors, including the British Broadcasting Corporation, All Rights Reserved.

This web site is powered by the same code created for the bicker manor project. For more details, contact Michael Sparks at BBC Research directly (cf contact)