Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
more pythonic example
[simgrid.git] / examples / python / actor-create / actor-create.py
1 # Copyright (c) 2006-2019. The SimGrid Team. All rights reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the license (GNU LGPL) which comes with this package.
5
6 # This example shows how to declare and start your actors.
7 #
8 # The first step is to declare the code of your actors (what they do exactly does not matter to this example) and then
9 # you ask SimGrid to start your actors. There is three ways of doing so:
10 # - Directly, by instantiating your actor as parameter to Actor::create()
11 # - By first registering your actors before instantiating it;
12 # - Through the deployment file.
13 #
14 # This example shows all these solutions, even if you obviously should use only one of these solutions to start your
15 # actors. The most advised solution is to use a deployment file, as it creates a clear separation between your
16 # application and the settings to test it. This is a better scientific methodology. Actually, starting an actor with
17 # Actor.create() is mostly useful to start an actor from another actor.
18
19 import sys
20 from simgrid import *
21
22
23 def receiver(mailbox_name):
24     """
25     Our first class of actors is simply implemented with a function, that takes a single string as parameter.
26     Later, this actor class is instantiated within the simulation.
27     """
28     mailbox = Mailbox.by_name(mailbox_name)
29
30     this_actor.info(
31         "Hello s4u, I'm ready to get any message you'd want on {:s}".format(mailbox.name))
32
33     msg1 = mailbox.get()
34     msg2 = mailbox.get()
35     msg3 = mailbox.get()
36     this_actor.info(
37         "I received '{:s}', '{:s}' and '{:s}'".format(msg1, msg2, msg3))
38     this_actor.info("I'm done. See you.")
39
40
41 def forwarder(*args):
42     """Our second class of actors is also a function"""
43     if len(args) < 2:
44         raise AssertionError(
45             "Actor forwarder requires 2 parameters, but got only {:d}".format(len(args)))
46     mb_in = Mailbox.by_name(args[0])
47     mb_out = Mailbox.by_name(args[1])
48
49     msg = mb_in.get()
50     this_actor.info("Forward '{:s}'.".format(msg))
51     mb_out.put(msg, len(msg))
52
53
54 class Sender:
55     """
56     Declares a third class of actors which sends a message to the mailbox 'mb42'.
57     The sent message is what was passed as parameter on creation (or 'GaBuZoMeu' by default)
58
59     Later, this actor class is instantiated twice in the simulation.
60     """
61
62     def __init__(self, msg = "GaBuZoMeu", mbox = "mb42"):
63         self.msg = msg
64         self.mbox = mbox
65
66     def __call__(self):
67         this_actor.info("Hello s4u, I have something to send")
68         mailbox = Mailbox.by_name(self.mbox)
69
70         mailbox.put(self.msg, len(self.msg))
71         this_actor.info("I'm done. See you.")
72
73
74 if __name__ == '__main__':
75     """Here comes the main function of your program"""
76
77     # When your program starts, you have to first start a new simulation engine, as follows
78     e = Engine(sys.argv)
79
80     # Then you should load a platform file, describing your simulated platform
81     e.load_platform("../../platforms/small_platform.xml")
82
83     # And now you have to ask SimGrid to actually start your actors.
84     #
85     # The easiest way to do so is to implement the behavior of your actor in a single function,
86     # as we do here for the receiver actors. This function can take any kind of parameters, as
87     # long as the last parameters of Actor::create() match what your function expects.
88     Actor.create("receiver", Host.by_name("Fafard"), receiver, "mb42")
89
90     # If your actor is getting more complex, you probably want to implement it as a class instead,
91     # as we do here for the sender actors. The main behavior goes into operator()() of the class.
92     #
93     # You can then directly start your actor, as follows:
94     Actor.create("sender1", Host.by_name("Tremblay"), Sender())
95     # If you want to pass parameters to your class, that's very easy: just use your constructors
96     Actor.create("sender2", Host.by_name("Jupiter"), Sender("GloubiBoulga"))
97
98     # But starting actors directly is considered as a bad experimental habit, since it ties the code
99     # you want to test with the experimental scenario. Starting your actors from an external deployment
100     # file in XML ensures that you can test your code in several scenarios without changing the code itself.
101     #
102     # For that, you first need to register your function or your actor as follows.
103     e.register_actor("sender", Sender)
104     e.register_actor("forwarder", forwarder)
105     # Once actors and functions are registered, just load the deployment file
106     e.load_deployment("actor-create_d.xml")
107
108     # Once every actors are started in the engine, the simulation can start
109     e.run()
110
111     # Once the simulation is done, the program is ended