[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

other CALL channel



Hi Thomas and Peter,

As we have seen, there are at least three ways to develop CALL channels.
Each implementation had its advantages and disadvantages. None of them did
satisfy me.

I had a few criteria in mind that should satisfy CALL channels before I
started over again to develop a CALL channel for a Button process.

1. CALL channels are higher level channels than the low-level channels. CALL
channels specify public methods for the client processes and methods for the
server processes. The read() and write() methods are too restrictive at this
higher level.
2. A CALL channel should extend or implement, (1) a Channel interface that
tells that the CALL channel is a channel, (2) a CallService interface that
specifies the methods for the client and (3) an AcceptService interface that
specifies the methods for the server.
3. A CALL channel is a design pattern of low-level channels. One should be
able to create its own CALL channel. Developing CALL channels must be easy.
I belief that editing low-level channels is too complex for the programmer
and low-level channels must be seen as primitive objects.
4. CALL channels must be thread-safe with using channels and without using
monitors.
5. The server process implements the methods that can be called by the
client. The CALL channel redirects these calls from the client(s) to the
server via low-level channels.
6. A CALL channel should support remote channels.

I took the java.awt.Button class to illustrate a CALL channel that would
satisfy the criteria. The code below does not show the button, but
illustrates the basic concept of this CALL channel. All source code is
included and the client and server codes are shown below.

The TestButtonCallChannel class starts a client process (ButtonClient) and a
server process (ButtonServer) in parallel. The server performs the active
button. ButtonCallChannel is the CALL channel between the client and server.

import csp.lang.*;
import csp.lang.Process;

public class TestButtonCallChannel  {
  public static void main(String[] args)  {
    ButtonCallChannel button = new ButtonCallChannel();
    Parallel par = new Parallel(new Process[]   {
      new ButtonClient(button),
      new ButtonServer(button)
    });

    par.run();
    }
}

The client process (ButtonClient) calls some methods from the CALL channel
as if the client calls the methods of the button.

import csp.lang.*;
import csp.lang.Process;
import java.awt.event.ActionListener;

public class ButtonClient implements Process
{
  ButtonCallService button;

  public ButtonClient(ButtonCallService callchannel)  {
    button = callchannel;
  }

  public void run()  {
    button.addNotify();
    java.lang.System.out.println("label = "+button.getLabel());
    button.setLabel("New Label");
    java.lang.System.out.println("label = "+button.getLabel());
  }
}


The server (ButtonServer) serves the calls from the client by accepting the
calls in it's own thread of control.

import csp.lang.*;
import csp.lang.Process;
import java.awt.event.ActionListener;

public class ButtonServer implements Process, ButtonCallService
// extends java.awt.Button
{
  ButtonAcceptService channel;
  String label = "Default Label";

  public ButtonServer(ButtonAcceptService chan)  {
    channel = chan;
  }

  public void run()
  {
    Alternative alt = new Alternative(new Guard((ChannelInput)channel));

    while(true)   {
      switch(alt.select())  {
        case 0:
          channel.accept(this);
          break;
        case 1:
          // other channels
          break;
      }
    }
  }

  public void addNotify()

    //super.addNotify();
    java.lang.System.out.println("performing addNotify()");
  }

  public String getLabel()

    //return super.getlabel();
    java.lang.System.out.println("performing getlabel()");
    return label;
  }

  public void setLabel(String label)

    //super.setLabel(label);
    this.label = label;
    java.lang.System.out.println("performing setLabel(\""+label+"\")");
  }

  public void setActionCommand(String command)

    //super.setActionCommand(command);
  }

  public String getActionCommand()

    // return super.getActionCommand();
    return null; // temporarily, enables compiling
  }

  public void addActionListener(ActionListener l)

    // super.addActionListsner l);
  }

  public void removeActionListener(ActionListener l)

    // super.removeActionListener(l);
  }
}

In this example you don't find channel reads and writes. The low-level reads
and writes are hidden inside the ButtonCallChannel. The accept() method
performs a call-back function to the server. This is a bit different than
Thomas's approach. Here, the methods can easily share the server's state
variables.

The result of this program is

performing addNotify()
performing getlabel()
label = Default Label
performing setLabel("New Label")
performing getlabel()
label = New Label

The CALL channel ButtonCallChannel can easily be extended as a remote
channel by plugging in two link drivers. For instance, the client process
and the server process can run on different computers and connected via the
Internet (CTJ rev. 14 contains a TCPIP link driver). The client and server
processes above do not have to be modified. This is not shown in this
example.

What do you think of this?

Gerald.

Attachment: ButtonCallChannel.zip
Description: Zip compressed data