与代理商合作

时间:2017-07-07 13:51:13

标签: concurrency eiffel agents

我正在尝试同时使用代理回调。不幸的是,无论我做什么,它总是似乎顺序而不是并行运行。 (没有代理人没有)

主要类( APPLICATION ):

class
    APPLICATION

inherit
    ARGUMENTS

create
    make

feature {NONE} -- Initialization

    make
            -- Run application.
        local
            a1 : separate PROCEDURE
            a2 : separate PROCEDURE
        do
            create my_counter.make (1, 100_000_000)
            create my_counter2.make (2, 100_000_000)

            launch_counter(my_counter)
            launch_counter(my_counter2)

        end

feature -- Launch

    launch_counter(c: separate COUNTER)
        do
            c.run (5, agent print_hello)
        end

    print_hello
        do
            print("Hello!%N")
        end

feature -- Access

    my_counter : separate COUNTER
    my_counter2 : separate COUNTER

end

计数器类:

class
    COUNTER

inherit
    EXECUTION_ENVIRONMENT


create
    make

feature -- Initilzation
    make (i: INTEGER; delay: INTEGER)
        do
            id := i
            delay_time := delay
        end

feature -- Stuff

    run (times: INTEGER; p: separate PROCEDURE)
    local
        c : INTEGER
    do
        from
            c := times
        until
            c = 0
        loop
            print("COUNTER: " + id.out)
            p.call
            sleep(delay_time)
            c := c - 1

        end

    end

feature {NONE} -- Access

    delay_time : INTEGER
    id: INTEGER

end

预期产出:

COUNTER: 1Hello!
COUNTER: 2Hello!
COUNTER: 1Hello!
etc.

实际输出:

COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!

我需要更改什么才能按预期运行?

1 个答案:

答案 0 :(得分:1)

代理对象在您的示例中保留对目标的引用,类型为APPLICAITON的根对象,因此对print_hello的所有调用都会同步。为避免这种情况,调用代理的对象应记录在COUNTER对象中并从那里使用。

这可以通过向类action添加属性COUNTER并更新其创建过程来实现

make (i: INTEGER; delay: INTEGER; a: separate PROCEDURE)
    do
        id := i
        delay_time := delay
        action := a
    end
...
action: separate PROCEDURE

然后p.call代替COUNTER.run,将使用以下代码(功能run不再有参数p):

        separate action as p do
            p.call
        end

现在p未锁定进入功能run,因此回调可以由不同的处理器交替执行。