home
table of contents
Comp. Science
November 2003
email

A producer/consumer model in San

A while back James Rogers proposed a programming "contest" in the comp.programming newsgroup. In this constest people would code solutions to programming tasks in the language of their choice, the objective being to get a comparison of how tasks would be handled in different languages.

The first task was to effect a producer-buffer-consumer model. The task description was:

The first problem in this contest is a simple producer / consumer problem. To keep things simple there should be one producer and one consumer. The producer will communicate with the consumer using a fixed length shared buffer containing no more than three data elements. When the buffer is full the producer must suspend its operations. When the buffer is empty the consumer must suspend its operations.
There was further specifications about timing. An attempt to move an assembly from the producer to the buffer takes 1.0 seconds if successful and .75 seconds if it fails. An attempt to move an assembly from the buffer to the consumer takes .5 seconds if successful, and .45 seconds if it fails. Production starts at time t=0.0; consumption starts at time t=4.0; production stops at time t=19.0; and comsumption stops at time t=21.0.
Begin segment type=package label=producer/consumer
    begin init
        production | warehouse | consumer
        bufmax  =  3
        p-start =  0
        p-stop  = 19
        c-start =  4
        c-stop  = 21
        f-put   =   .75
        s-get   =  1.0
        f-get   =   .45
        s-get   =   .50
        end
        
    begin proc get-time
        msg to=scheduler, type=want-time, rsvp
        return rsvp.time
        end

    begin agent main
        msg to=scheduler, type=start-producer, time = p-start
        msg to=scheduler, type=start-consumer, time = c-start
        msg to=scheduler, type=stop-producer,  time = p-stop
        msg to=scheduler, type=stop-consumer,  time = c-stop

    begin agent production
        init id = 0
        begin on-msg
            id  += 1
            item = id
            print <get-time>: Produced item {item}
            emit0-word item
            end
        end
        
    begin agent warehouse
        begin on-$0-word
            begin loop until buffer$nrow lt? bufmax
                msg to=scheduler, type=delay, delay=f-put, rsvp
                print <get-time>: Warehouse is full
                end
            msg to=scheduler, type=delay, delay=s-put, rsvp
            print <get-time>: Item {item} added to warehouse
            append $0 to buffer[]
            end
        begin on-msg type=gimme
            begin loop until buffer$nrow gt? 0
                msg to=scheduler, type=delay, delay=f-get, rsvp
                print <get-time>: Warehouse is empty
                end
            msg to=consumer, type=delay, delay=s-get, rsvp
            buffer[] -> item, buffer[]
            print <get-time>: Shipping {item} to consumer
            emit0-word item
            end
        end warehouse
        
    begin agent consumer
        begin on-$0-word
            print <get-time>: consuming {$0}
            msg to=warehouse, type=gimme
            end
        end
        
    begin agent scheduler
        init clock = 0
         
        begin on-msg switch msg.type
            eq? want-time => reply time=clock
            eq? delay     => begin
                $insert id=msg.id, label=delay, time=(clock + msg.delay)
                $release
                end
            else => $insert msg.id {msg.type} msg.time
            end switch
           
        begin proc $insert
            args: id, label, time
            
            ev.id = id; ev.label = label; ev.time = time
            begin loop i from [$rfirst...$rlast] switch ev.time
                lt? $[i].time => $[i-1].[] <- $[i].[]
                else begin
                    $[i].[] <- ev.[]
                    escape
                    end
                end
            end proc
            
        begin proc $release
            $[].[] -> ev.[] $[].[]
            switch ev.type
                eq? delay          => reply id=ev.id
                eq? start-producer => begin
                    print <get-time>: Starting production
                    msg to=producer
                    end
                eq? start-consumer => begin
                    print <get-time>: Starting consumption
                    msg to=warehouse, type=gimme
                    end
                eq? stop-producer => begin
                    print <get-time>: Halting production
                    deactivate production
                    end
                eq? stop-consumer => begin
                    print <get-time>: Halting consumption
                    deactivate consumer
                    end
                end
            end
        end scheduler
    end producer/consumer


This page was last updated November 12, 2003.

home
table of contents
Comp. Science
November 2003
email