table of contents
Comp. Science
November 2003

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
    begin proc get-time
        msg to=scheduler, type=want-time, rsvp
        return rsvp.time
    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
    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
            msg to=scheduler, type=delay, delay=s-put, rsvp
            print <get-time>: Item {item} added to warehouse
            append $0 to buffer[]
        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
            msg to=consumer, type=delay, delay=s-get, rsvp
            buffer[] -> item, buffer[]
            print <get-time>: Shipping {item} to consumer
            emit0-word item
        end warehouse
    begin agent consumer
        begin on-$0-word
            print <get-time>: consuming {$0}
            msg to=warehouse, type=gimme
    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)
            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.[]
            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
                eq? start-consumer => begin
                    print <get-time>: Starting consumption
                    msg to=warehouse, type=gimme
                eq? stop-producer => begin
                    print <get-time>: Halting production
                    deactivate production
                eq? stop-consumer => begin
                    print <get-time>: Halting consumption
                    deactivate consumer
        end scheduler
    end producer/consumer

This page was last updated November 12, 2003.

table of contents
Comp. Science
November 2003