Class: Garden

Inherits:
Object
  • Object
show all
Includes:
Toolshed
Defined in:
lib/garden.rb

Overview

These classes provides the garden part of the Gardener,Garden,Seed natural design patern

The Garden is where the thread concurency is implemented, offering itself as a thread queue manager, dispatching seeds from the Gardener to its Rows child class and back again. Since Ruby doesn’t implement Native Threads, and only Native Threads scales to multi-core execution, the way to implement concurent execution is through splitting the task at hand between multiple single threaded parallel executions. The Rows system does exactly that, using the Ruby fork function, then connecting the isolated running processes to the Garden, through a simple socket system provided by the Toolshed Module.

Author

lp ([email protected])

Copyright

2008 Louis-Philippe Perron - Released under the terms of the MIT license

:title:Garden

Defined Under Namespace

Classes: Rows

Constant Summary

Constants included from Toolshed

Toolshed::UDP_HOST

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Toolshed

available_port, block_size, block_size=, garden_port, garden_port=, socket_client_perm, #socket_client_perm_duplex, #socket_client_perm_send, socket_client_temp, #socket_client_temp, socket_server, #socket_server_recv, #socket_server_send

Constructor Details

#initializeGarden

The new class method initializes the Garden. As part of the Abundance lib, Garden is not initialized directly, but rather as a side effect of the Gardener’s initialization. Its instance resides in the @garden Gardener’s instance variable. Its real muscles are inaccessibles from instance method intervention, because of its nature as a forked Ruby process.

Example

garden = Garden.new


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/garden.rb', line 31

def initialize
  @pid = fork do
    @quit = false
    @harvest = []
    @rows_port = []
    @seeds = []; @sprouts = []; @crops = []; @id = 0
    @socket_server = Toolshed.socket_server(Toolshed::garden_port)
    @socket_client_temp = Toolshed.socket_client_temp
    loop do
      catch :fill_rows do
        loop do
          if ! @seeds.empty? && ! @rows_port.empty?
            seed = @seeds.shift
            @sprouts[seed[:id]] = seed
            row_port = @rows_port.shift
            socket_client_temp(:sprout,seed,row_port)
          elsif @quit && ! @rows_port.empty?
            seed = nil
            row_port = @rows_port.shift
            socket_client_temp(:quit,seed,row_port)
          else
            throw :fill_rows
          end               
        end
      end
      command, data, clientport, clientname, clientaddr = socket_server_recv
      case command
      when :seed 
        @id += 1; @seeds << {:id => @id , :seed => data}
        socket_server_send(command,@id,clientaddr,clientport)
      when :row
        if @quit
          command = :quit
          seed = nil
        elsif @seeds.empty?
          seed = nil
          @rows_port << data
        else
          seed = @seeds.shift
          @sprouts[seed[:id]] = seed
        end
        socket_server_send(command,seed,clientaddr,clientport)  
      when :crop 
        @sprouts[data[:id]] = nil
        @crops[data[:id]] = data; socket_server_send(command,true,clientaddr,clientport)
        socket_server_send(command,data, @harvest[data[:id]][:clientaddr], @harvest[data[:id]][:clientport]) if @harvest[data[:id]] 
      when :growth
        case data
        when :progress
          progress = sprintf( "%.2f", @crops.size.to_f / (@crops.size + @sprouts.compact.size + @seeds.size))
          socket_server_send(command,progress,clientaddr,clientport)
        when :seed
          socket_server_send(command,@seeds.size,clientaddr,clientport)
        when :sprout
          socket_server_send(command,@sprouts.compact.size,clientaddr,clientport)
        when :crop
          socket_server_send(command,@crops.size,clientaddr,clientport)
        else
          socket_server_send(command,false,clientaddr,clientport)
        end
      when :harvest
        case data
        when :all
          socket_server_send(command,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops},clientaddr,clientport)
        when :seed
          socket_server_send(command,@seeds,clientaddr,clientport)
        when :sprout
          socket_server_send(command,@sprouts.compact,clientaddr,clientport)
        when :crop
          socket_server_send(command,@crops,clientaddr,clientport)
        else
          if data.is_a? Integer
            if @crops[data]
              socket_server_send(command,@crops[data],clientaddr,clientport)
            else
              @harvest[data] = {:clientaddr => clientaddr, :clientport => clientport}
            end
          else
            socket_server_send(command,false,clientaddr,clientport)
          end
        end
      when :close
        if data[:level] == :garden
          @seeds_pid = data[:pid]
          @quit = true
          @mem_addr = clientaddr; @mem_port = clientport
        else
          @seeds_pid.delete(data[:pid].to_i)
          if @seeds_pid.empty?
            socket_server_send(:close,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops}, @mem_addr, @mem_port)
            exit
          end
        end
      else
        socket_server_send(command,false,clientaddr,clientport)
      end
    end
  end
  return pid
end

Instance Attribute Details

#pidObject (readonly)

Returns the value of attribute pid.



20
21
22
# File 'lib/garden.rb', line 20

def pid
  @pid
end

Instance Method Details

#rows(rows, init_timeout, grow_block) ⇒ Object

The rows method for the Garden instance allow instantiation of its child Rows. As part of the Abundance lib, Garden.rows is not invoked directly, but rather as a side effect of the Gardener’s initialization. Its in reality an indirect initializer for the Rows class.

Parameter

  • rows = garden rows number, the number of concurent threads

  • init_timeout = allow to pause execution to allow for larger garden rows to initialize

Example

rows = garden.rows(4,2) { grow_block }


143
144
145
# File 'lib/garden.rb', line 143

def rows(rows,init_timeout,grow_block)
  Rows.new(rows,init_timeout,grow_block)
end