On 17/01/2008, craigdo at ee.washington.edu <craigdo at ee.washington.edu> wrote:
>
> Okay, since nobody wants any preliminaries, I'll just present a framework
> approach to the current problem.
>
> First, at the client level, you would see something like the following in
> simple.cc:
>
> //
> // inherit from the basic wireless cluster framework that does the
> // grunt work (technically, implements the frozen spots). We're
> // going to override the pieces of the framework that we want to
> // modify. Here, we want to control how the net device is put
> // together and what applications are run on the nodes.
> //
> class MyWirelessClusterFramework : public WirelessClusterFramework
> {
> public:
> MyWirelessClusterFramework ();
> virtual ~MyWirelessClusterFramework ();
>
> protected:
> virtual Ptr<NetDevice> CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch);
> virtual void CreateApplications (Ptr<Node> n);
> }
>
> //
> // Here's the method that's used to create the net devices. Using
> // inversion of control, it's brought up from the "bowels of the system"
> // into the client space so we can control what happens directly.
> //
> // This is the case where Mathieu wanted to create another kind of rate
> // control object that took different construction parameters.
> //
> // Using this approach, they're right here in front of the client's face
> // to change however she wants. There would be a default implementation
> // of this method that would use the default rate control object so if
> // you don't want to change that, you don't have to re-implement this
> // method.
> //
> Ptr<NetDevice>
> MyWirelessClusterFramework::CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch)
> {
> Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice> (n);
>
> Ptr<CraigsWierdRateControl> rate =
> CreateObject<CraigsWierdRateControl> (param1, param2, param3);
>
> nd->SetRateControl (rate);
>
> return nd;
> }
>
> //
> // Here's the method that's used to create the applications. Using
> // inversion of control, it's brought up from the "bowels of the system"
> // into the client space so we can control what happens directly.
> //
> // The default method would create no applications or possibly if you
> // almost always want something there, it could create it by default.
> // You could add to the default set here as well (as is illustrated)
> //
> void
> MyWirelessClusterFramework::CreateApplications (Ptr<Node> n)
> {
> WirelessClusterFramework::CreateApplications (n);
> Ptr<OnOffApplication> app = CreateObject<OnOffApplication> (n);
> return;
> }
>
> //
> // Now the client uses the framework simply by asking it to Build some
> // number of nodes. She gets back a TopologySet that includes a channel
> // and contains all of the nodes "connected" to the channel.
> //
> int
> main (int argc, char *argv[])
> {
> MyWirelessClusterFramework fw;
> Ptr<TopologySet> topo = fw.Build (100);
> //
> // Run IP address assigner, router, etc.
> //
> Simulator::Run ();
> Simulator::Destroy ();
> }
>
> Now the framework code is implemented in some other file somewhere. I
> would
> expect that there are a number of frameworks for different basic
> topologies,
> but here's how they might look for this problem.
>
> There's a base class that has a frozen spot called Build that runs the for
>
> loop and has hot spots for the creation functions that will likely be
> changed ...
>
> class TopologyFramework : public Object
> {
> public:
> TopologyFramework ();
> virtual ~TopologyFramework ();
>
> Ptr<TopologySet> Build (unit32_t n); // frozen spot
>
> protected:
> virtual Ptr<Channel> CreateChannel (void) = 0;
> virtual Ptr<Node> CreateNode (void) = 0;
> virtual Ptr<NetDevice> CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch) =
> 0;
> virtual void CreateApplications (Ptr<Node> n) = 0;
> };
>
> The frozen spot code just creates a channel and connects up a bunch of
> nodes, net devices and applications. This code calls into the hot spots
> wich can be refined by a client to do the dirty work. Presumably this
> won't
> change (much).
>
> Ptr<TopologySet>
> TopologyFramework::Build (uint32_t n)
> {
> Ptr<TopologySet> topo = Create<TopologySet> ();
>
> Ptr<Channel> ch = CreateChannel ();
> topo->SetChannel (ch);
>
> for (uint32_t i = 0; i < n; ++i)
> {
> Ptr<Node> n = CreateNode ();
> Ptr<NetDevice> nd = CreateNetDevice (n, ch);
> CreateApplications (n);
> topo->AddNode (n);
> ch->AddNode (n);
> }
> }
>
> It's nice to have a default version that does useful work without having
> to
> override/redefine anything, so there should be another class that looks
> something like the following:
>
> This would create a generic wireless cluster with the standard rate
> control
> algorithm Mathieu spoke of.
>
> class WirelessClusterFramework : public TopologyFramework
> {
> public:
> WirelessClusterFramework ();
> virtual ~VirtualClusterFramework ();
>
> protected:
> virtual Ptr<Channel> CreateChannel (void);
> virtual Ptr<Node> CreateNode (void);
> virtual Ptr<NetDevice> CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch);
> virtual Ptr<NetDevice> CreateApplications (Ptr<Node> n);
> };
>
> Ptr<Channel>
> WirelessClusterFramework::CreateChannel (void)
> {
> return Create<WifiChannel>;
> }
>
> Ptr<Node>
> WirelessClusterFramework::CreateNode (void)
> {
> Ptr<Node> n = CreateObject<Node>;
> n->AddIpStack ();
> n->AddUdpStack ();
> n->AddTcpStack ();
> }
>
> Ptr<NetDevice>
> WirelessClusterFramework::CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch)
> {
> Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice> (n);
> Ptr<RateControl> rate = CreateObject<RateControl> ();
>
> nd->SetRateControl (rate);
>
> return nd;
> }
>
> So, there is really no need to implement any Parameters plumbing through
> the
> system if we just take to heart what Mathieu said about exposing the
> control
> flow to the user.
>
> I think this is quite easy to understand and is more flexible than trying
> to
> plumb Parameters down into the system. Like Mathieu said, expose the area
> on which you want to tweak directly to the user, don't force him to try
> and
> execute his wishes by "remote control" by describing it via data.
>
> Thoughts?
Honestly I don't see the point od TopologyFramework::Build (uint32_t n).
It's not like a for-loop is _that_ complex, even in C++. And I think
TopologyFramework::Build just obscures the simple for loop. And if you
start making examples with TopologyFramework::Build then some people will
think that TopologyFramework::Build does some kind of special magic to make
it happen and will forever be afraid to do a simple for loop.
I like the idea of container/group much better; at least a container does
something useful: keep a list of nodes. I don't think inversion of control
is beneficial in this case because it only automates a simple for loop. And
if a new API is not beneficial it ends up being harmful because you have to
learn it anyway.
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert