Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Further cleanups of ruby, plus add FIXME in ruby and Java for the next cleanups
[simgrid.git] / src / bindings / ruby / simgrid.rb
1 require 'simgrid_ruby'
2 require 'thread'
3
4 $DEBUG = false  # This is a Global Variable Useful for MSG::debugging
5
6 ###########################################################################
7 # Class Semaphore 
8 ###########################################################################
9
10 class Semaphore
11   def initialize(initvalue = 0)
12     @counter = initvalue
13     @waiting_list = []
14   end
15
16   def acquire
17     MSG::debug("Acquire "+self.to_s)
18     Thread.critical = true
19     if (@counter -= 1) < 0
20       @waiting_list.push(Thread.current)
21       Thread.stop
22     end
23     self
24   ensure
25     Thread.critical = false
26   end
27
28   def release
29     MSG::debug("Release "+self.to_s)
30     Thread.critical = true
31     begin
32       if (@counter += 1) <= 0
33         t = @waiting_list.shift
34         t.wakeup if t
35         MSG::debug("Wakeup "+t.to_s)
36       else 
37         MSG::debug("Nobody to wakeup")
38       end
39     rescue ThreadError
40       retry
41     end
42     self
43   ensure
44     Thread.critical = false
45   end
46 end
47
48 ########################################################################
49 # Class Process 
50 ########################################################################
51 class MSG::Process < Thread 
52   @@nextProcessId = 0
53
54 # Attributes
55   attr_reader :bind, :id            # Read only
56   attr_accessor :name, :properties, :pargs  # R/W
57   
58 # Initialize : Used from ApplicationHandler to fill it in
59   def initialize(*args)
60     # FIXME: use only one variante (the one with 3 args) and kill the others
61     @schedBegin = Semaphore.new(0)
62     @schedEnd = Semaphore.new(0)    
63     @properties = Hash.new()
64     @id = @@nextProcessId++
65     
66     argc = args.size
67
68     if argc == 0 # Default initializer
69       super() {
70         @id = 0
71         @bind = 0
72         @name = ""
73         @pargs = Array.new()
74         start()
75         MSG::debug "Initializer without any argument"
76       }
77        
78     # 2 arguments: (HostName,Name) Or (Host , Name)
79     elsif argc == 2   
80       super(){
81         MSG::debug "Initilize with 2 args"
82         type = args[0].type()
83         if ( type.to_s == "String")
84           host = Host.getByName(args[0])
85         elsif ( type.to_s == "MSG::Host")
86           host = args[0]
87         else 
88           raise "first argument of type "+args[0].type().to_s+", but expecting either String or MSG::Host"
89         end
90         if $DEBUG
91           puts host
92         end
93         raise "Process name cannot be null" if args[1].empty?
94         @name = args[1] 
95         if $DEBUG
96           puts @name
97         end
98         @pargs = Array.new()    # No Args[] Passed in Arguments
99         start()
100         createProcess(self,host)
101       }
102        
103     # 3 arguments: (hostName,Name,args[]) or (Host,Name,args[])
104     elsif argc == 3  
105       super(){
106         MSG::debug "Initilize with 3 args"
107         type = args[0].type()
108         if ( type.to_s == "String")
109           host = Host.getByName(args[0])
110         elsif ( type.to_s == "MSG::Host")
111           host = args[0]
112         else 
113           raise "first argument of type "+args[0].type().to_s+", but expecting either String or MSG::Host"
114         end
115         if $DEBUG
116           puts host
117         end
118       
119         raise "Process name cannot be null" if args[1].empty?
120         @name = args[1]
121         type = args[2].type()
122         raise "Third argument should be an Array" if type != "Array"
123         @pargs = args[3]
124         createProcess(self,host)  
125         
126            }
127   else 
128     raise "Bad number of argument: Expecting either 1, 2 or 3, but got "+argc.to_s
129   end
130     end
131   
132   # main
133   def main(args) 
134     # To be overriden by childs
135     raise("You must define a main() function in your process, containing the code of this process")
136   end
137      
138   # Start : To keep the process alive and waiting via semaphore
139   def start()
140     @schedBegin.acquire
141     # execute the main code of the process     
142     MSG::debug("Begin execution")
143     main(@pargs)
144     processExit(self) # Exit the Native Process
145     @schedEnd.release
146   end
147     
148   def processList() (KILLME?)
149     Thread.list.each {|t| p t}
150   end
151   
152   #Get Own ID (KILLME?)
153   def getID()
154     return @id
155   end
156   
157   #Get a Process ID (KILLME?)
158   def processID(process)
159     return process.id
160   end
161   
162   #Get Own Name (KILLME?)
163   def getName()
164     return @name
165   end
166   
167   #Get Bind (KILLME?)
168   def getBind()
169     return @bind
170   end
171   
172   #Get Binds (KILLME?)
173   def setBind(bind)
174     @bind = bind
175   end
176     
177   def unschedule()
178     @schedEnd.release
179     @schedBegin.acquire
180   end
181   
182   def schedule()
183     @schedBegin.release
184     @schedEnd.acquire
185   end
186   
187    #C Simualator Process Equivalent  Management
188   # After Binding Ruby Process to C Process
189   
190 #   pause
191   def pause()
192     processSuspend(self)
193   end
194   
195 #   restart
196   def restart()
197     processResume(self)
198   end
199   
200 #   isSuspended
201   def isSuspended()
202     processIsSuspended(self)
203   end
204   
205 #   getHost
206   def getHost()
207     processGetHost(self)
208   end
209   
210 # The Rest of Methods !!! To be Continued ...
211 end
212
213 #########################################################################
214 # Class ApplicationHandler
215 #########################################################################
216 class ApplicationHandler
217   def initialize()
218     @hostName = nil
219     @function = nil
220   end
221   
222   def onBeginProcess(hostName,function)
223     @args = Array.new
224     @properties = Hash.new
225     
226     @hostName = hostName
227     @function = function
228       
229     MSG::debug("onBeginProcess("+hostName+","+function+")")
230   end
231
232   def onProperty(id,value)
233     @properties[id] = value
234   end
235   
236   def onProcessArg(arg)
237     @args.push(arg)
238   end
239
240   def onEndProcess()
241     # must be in C, called from a callback to the FlexML parser 
242     # newInstance must take args and hostname as argument to initialize everything, *and* bind it to C element
243     # Allows to mark all attributes of process (but properties) to read-only
244     process = MSG::rubyNewInstance(@function) 
245     process.pargs = @args
246     process.name = @function
247     host = MSG::Host.getByName(@hostName)
248     MSG::processCreate(process,host)
249     process.properties = @properties
250   end
251 end
252  
253 #########################
254 # Main chunck 
255 #########################
256 MSG.init(ARGV)