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
index 90b8793..2cfeacf 100644 (file)
@@ -1,52 +1,67 @@
 require 'simgrid_ruby'
-include MSG
 require 'thread'
 
-$DEBUG = true  # This is a Global Variable Useful for Debugging
+$DEBUG = false  # This is a Global Variable Useful for MSG::debugging
 
 ###########################################################################
 # Class Semaphore 
 ###########################################################################
-class Semaphore 
-  Thread.abort_on_exception = true
-  attr_accessor :permits
-  def initialize ( permits )
-       @permits = permits
+
+class Semaphore
+  def initialize(initvalue = 0)
+    @counter = initvalue
+    @waiting_list = []
   end
-   
 
-  def acquire(mutex,cv)
-    raise "Interrupted Thread " if (!Thread.current.alive?)
-    mutex.synchronize {
-      while @permits <= 0 
-        cv.wait(mutex)       
-      end
-    
-      @permits = @permits - 1
-      cv.signal    
-    }    
+  def acquire
+    MSG::debug("Acquire "+self.to_s)
+    Thread.critical = true
+    if (@counter -= 1) < 0
+      @waiting_list.push(Thread.current)
+      Thread.stop
+    end
+    self
+  ensure
+    Thread.critical = false
   end
-    
-  def release(mutex,cv)
-    mutex.synchronize{
-      @permits += 1
-      cv.signal
-    }
+
+  def release
+    MSG::debug("Release "+self.to_s)
+    Thread.critical = true
+    begin
+      if (@counter += 1) <= 0
+        t = @waiting_list.shift
+        t.wakeup if t
+        MSG::debug("Wakeup "+t.to_s)
+      else 
+        MSG::debug("Nobody to wakeup")
+      end
+    rescue ThreadError
+      retry
+    end
+    self
+  ensure
+    Thread.critical = false
   end
 end
 
 ########################################################################
-# Class RbProcess 
+# Class Process 
 ########################################################################
-class RbProcess < Thread 
+class MSG::Process < Thread 
   @@nextProcessId = 0
+
 # Attributes
-  attr_accessor :bind, :id, :properties, :name,
-      :pargs, :schedBegin, :schedEnd, :mutex, :cv
+  attr_reader :bind, :id            # Read only
+  attr_accessor :name, :properties, :pargs  # R/W
   
 # Initialize : Used from ApplicationHandler to fill it in
   def initialize(*args)
+    # FIXME: use only one variante (the one with 3 args) and kill the others
+    @schedBegin = Semaphore.new(0)
+    @schedEnd = Semaphore.new(0)    
+    @properties = Hash.new()
+    @id = @@nextProcessId++
     
     argc = args.size
 
@@ -56,16 +71,14 @@ class RbProcess < Thread
         @bind = 0
         @name = ""
         @pargs = Array.new()
-        init_var()
         start()
-        if $DEBUG
-               puts "Init Default Initializer...Nothing to do...Bye"
-        end  
+        MSG::debug "Initializer without any argument"
       }
        
     # 2 arguments: (HostName,Name) Or (Host , Name)
     elsif argc == 2   
       super(){
+        MSG::debug "Initilize with 2 args"
         type = args[0].type()
         if ( type.to_s == "String")
           host = Host.getByName(args[0])
@@ -83,19 +96,14 @@ class RbProcess < Thread
           puts @name
         end
         @pargs = Array.new()    # No Args[] Passed in Arguments
-        @@nextProcessId += 1
-        @id = @@nextProcessId
-        init_var()
         start()
         createProcess(self,host)
-             if $DEBUG
-               puts "Initilize with 2 args"
-        end
       }
        
     # 3 arguments: (hostName,Name,args[]) or (Host,Name,args[])
     elsif argc == 3  
       super(){
+       MSG::debug "Initilize with 3 args"
         type = args[0].type()
         if ( type.to_s == "String")
           host = Host.getByName(args[0])
@@ -113,110 +121,70 @@ class RbProcess < Thread
         type = args[2].type()
         raise "Third argument should be an Array" if type != "Array"
         @pargs = args[3]
-        @@nextProcessId +=1
-        @id = @@nextProcessId
-        init_var()
         createProcess(self,host)  
         
-      if $DEBUG
-       puts "Initilize with 3 args"
-      end
-      
-#       sleep #keep the thread running
           }
   else 
-    raise "Bad number of argument: Expecting either 1, 2 or 3, but got "+argc
+    raise "Bad number of argument: Expecting either 1, 2 or 3, but got "+argc.to_s
   end
     end
-
-  # Init_var Called By Initialize  
-  def init_var()  
-    @proprieties = Hash.new()
-    @mutex = Mutex.new
-    @cv = ConditionVariable.new
-    # Process Synchronization Tools
-    @schedBegin = Semaphore.new(0)
-    @schedEnd = Semaphore.new(0)    
-  end
   
-  #main
-  def msg_main(args)
-    # To Be Implemented within The Process...
-    # The Main Code of The Process to be Executed ...
+  # main
+  def main(args) 
+    # To be overriden by childs
+    raise("You must define a main() function in your process, containing the code of this process")
   end
      
-  # Start : To keep the Process Alive and waitin' via semaphore
+  # Start : To keep the process alive and waiting via semaphore
   def start()
-    @schedBegin.acquire(@mutex,@cv)
-    #execute The Main Code of The Process ( Example Master ; Slave ...)     
-    msg_main(@pargs)
-    processExit(self) #Exite the Native Process
-    @schedEnd.release(@mutex,@cv)
+    @schedBegin.acquire
+    # execute the main code of the process     
+    MSG::debug("Begin execution")
+    main(@pargs)
+    processExit(self) # Exit the Native Process
+    @schedEnd.release
   end
     
-#   NetxId
-  def nextId ()
-    @@nextProcessId +=1
-    return @@nextProcessId
-  end
-
-  if $DEBUG
-    #Process List
-    def processList()
-      Thread.list.each {|t| p t}
-    end
+  def processList() (KILLME?)
+    Thread.list.each {|t| p t}
   end
   
-  #Get Own ID
+  #Get Own ID (KILLME?)
   def getID()
     return @id
   end
   
-  # set Id
-  def setID(id)
-    @id = id
-  end
-  
-  #Get a Process ID
+  #Get a Process ID (KILLME?)
   def processID(process)
     return process.id
   end
   
-  #Get Own Name
+  #Get Own Name (KILLME?)
   def getName()
     return @name
   end
   
-  #Get a Process Name
-  def processName(process)
-    return process.name
-  end
-  
-  #Get Bind
+  #Get Bind (KILLME?)
   def getBind()
     return @bind
   end
   
-  #Get Binds
+  #Get Binds (KILLME?)
   def setBind(bind)
     @bind = bind
   end
     
-  def unschedule() 
-    
-    @schedEnd.release(@mutex,@cv)
-#     info("@schedEnd.release(@mutex,@cv)")
-    @schedBegin.acquire(@mutex,@cv)
-#     info("@schedBegin.acquire(@mutex,@cv)")
-     
+  def unschedule()
+    @schedEnd.release
+    @schedBegin.acquire
   end
   
   def schedule()
-    @schedBegin.release(@mutex,@cv)
-    @schedEnd.acquire(@mutex,@cv)
+    @schedBegin.release
+    @schedEnd.acquire
   end
   
-   #C Simualateur Process Equivalent  Management
+   #C Simualator Process Equivalent  Management
   # After Binding Ruby Process to C Process
   
 #   pause
@@ -242,172 +210,44 @@ class RbProcess < Thread
 # The Rest of Methods !!! To be Continued ...
 end
 
-########################################################################
-# Class ProcessFactory
-########################################################################
-
-class ProcessFactory 
-
-#     Attributes
-   attr_accessor :args, :proprieties, :hostName, :function
-#    Initlialize
-    def initialize()
-    
-    @args = Array.new
-    @proprieties = Hash.new
-    @hostName = nil
-    @function = nil
-    
-    end
-    
-#     setProcessIdentity
-    def setProcessIdentity(hostName,function)
-      @hostName = hostName
-      @function = function
-      
-      if !args.empty?
-       args.clear
-      end
-      
-      if !proprieties.empty?
-       proprieties.clear   
-      end
-    
-    end
-
-#     RegisterProcess  
-    def registerProcessArg(arg)
-      
-      @args.push(arg)
-      
-    end
-
-#     CreateProcess
-    def createProcess()
-      
-      process = rubyNewInstance(@function) # process = rubyNewInstanceArgs(@function,@args) #
-      size = @args.size
-      for i in 0..size-1
-       process.pargs.push(@args[i]) 
-      end
-      process.name = @function
-      process.id = process.nextId() # This increment Automaticaly  The Static ProcessNextId for The Class RbProces
-      host = RbHost.getByName(@hostName)
-      processCreate(process,host)
-      process.properties = @properties
-      @proprieties = Hash.new
-      
-    end
-    
-#     SetProperty
-    def setProperty(id,value)
-      @proprieties[id] = value
-    end
-end
-
 #########################################################################
 # Class ApplicationHandler
 #########################################################################
 class ApplicationHandler
-  @processFactory  
-#   Initialize
   def initialize()
-     #Nothing todo
-  end
-  
-    #  onStartDocument
-  def onStartDocument()
-    
-    @processFactory = ProcessFactory.new
-    if ($DEBUG)
-      puts "onStartDocument"
-    end
-      
+    @hostName = nil
+    @function = nil
   end
   
-#   onBeginProcess
   def onBeginProcess(hostName,function)
+    @args = Array.new
+    @properties = Hash.new
     
-    @processFactory.setProcessIdentity(hostName,function)
-    
-     if ($DEBUG)
-      puts "onBeginProcess"
-     end
-    
-  end
-
-#   onProperty
-    def onProperty(id,value)
-    
-    @processFactory.setProperty(id,value)
-    
-     if ($DEBUG)
-      puts "onProperty"
-     end
-    
-  end
-  
-#   RegisterProcessArg
-    def onProcessArg(arg)
-    
-    @processFactory.registerProcessArg(arg)
+    @hostName = hostName
+    @function = function
       
-      if ($DEBUG)
-      puts "onProcessArg"
-      end
-    
+    MSG::debug("onBeginProcess("+hostName+","+function+")")
   end
 
-#   OnEndProcess
-   def onEndProcess()
-   
-   @processFactory.createProcess()
-   
-   if ($DEBUG)
-      puts "onEndProcess"
-   end
-      
- end
-
- #  onEndDocument
-  def onEndDocument()  
-#    Erm... Actually nothing to do !!
-   
-   if($DEBUG)
-   puts "onEndDocument"
-   end
- end
- #  End Class
- end
-#########################
-# Class RbHost 
-#########################
-
-class RbHost < Host
-# Attributes
-  attr_accessor :bind, :data 
-  
-# Initialize
-  def initialize()
-    super()
-    @bind = 0
-    @data = nil
+  def onProperty(id,value)
+    @properties[id] = value
   end
   
-end
-
-#########################
-# Class RbTask 
-#########################
-class RbTask < Task  
-  attr_accessor :bind 
-  
-  def initialize(name,comp_size,comm_size)
-    super(name,comp_size,comm_size)
+  def onProcessArg(arg)
+    @args.push(arg)
   end
 
+  def onEndProcess()
+    # must be in C, called from a callback to the FlexML parser 
+    # newInstance must take args and hostname as argument to initialize everything, *and* bind it to C element
+    # Allows to mark all attributes of process (but properties) to read-only
+    process = MSG::rubyNewInstance(@function) 
+    process.pargs = @args
+    process.name = @function
+    host = MSG::Host.getByName(@hostName)
+    MSG::processCreate(process,host)
+    process.properties = @properties
+  end
 end
  
 #########################