Archivi per la categoria erlang

Giochini in Erlang

24-12-2010 19:41:36 CET Postato in: erlang, post a caso | Commenta

Esempio rubato spudoratamente da OpenDLM:

-module(dig_test).
-export([run_test/0]).
-export([init/0]).

-spec(run_test() -> pid()).

run_test() ->
    spawn(?MODULE, init, []).

-spec(init() -> none()).

init() ->
    TWFG = digraph:new(),
    %% Simulate the same TWFG present in OpenDLM specs
    C1 = add_client(TWFG, c1),
    R1 = add_resource(TWFG, r1),
    C2 = add_client(TWFG, c2),
    R2 = add_resource(TWFG, r2),
    R3 = add_resource(TWFG, r3),
    C3 = add_client(TWFG, c3),
    digraph:add_edge(TWFG, C1, R1),
    digraph:add_edge(TWFG, R1, C2),
    digraph:add_edge(TWFG, C2, R2),
    digraph:add_edge(TWFG, C2, R3),
    digraph:add_edge(TWFG, R2, C3),
    digraph:add_edge(TWFG, R3, C1),
    detect_deadlock_for(TWFG, R1),
    digraph:delete(TWFG),
    exit(normal).

-spec(add_client(digraph(), atom()) -> digraph:vertex()).

add_client(WaitForGraph, ClientName) ->
    add_vertex(WaitForGraph, {client, ClientName}).

-spec(add_resource(digraph(), atom()) -> digraph:vertex()).

add_resource(WaitForGraph, ResourceName) ->
    add_vertex(WaitForGraph, {resource, ResourceName}).

-spec(add_vertex(digraph(), term()) -> digraph:vertex()).

add_vertex(WaitForGraph, Label) ->
    Vertex = digraph:add_vertex(WaitForGraph),
    digraph:add_vertex(WaitForGraph, Vertex, Label).

-spec(detect_deadlock_for(digraph(), digraph:vertex()) -> ok).

detect_deadlock_for(WaitForGraph, Vertex) ->
    case digraph:get_cycle(WaitForGraph, Vertex) of
        false ->
            io:format("No deadlocks detected for ~p~n", [vertex_name(WaitForGraph, Vertex)]);
        VList ->
            io:format("Deadlock detected between ~p~n", [vertices_names(WaitForGraph, VList)])
    end.

-spec(vertex_name(digraph(), digraph:vertex()) -> term()).

vertex_name(WaitForGraph, Vertex) ->
    {_, Name} = digraph:vertex(WaitForGraph, Vertex),
    Name.

-spec(vertices_names(digraph(), nil() | [digraph:vertex()]) -> nil() | [term()]).

vertices_names(WaitForGraph, VList) ->
    vertices_names(WaitForGraph, VList, []).

-spec(vertices_names(digraph(), nil() | [digraph:vertex()], nil() | [term()]) -> nil() | [term()]).

vertices_names(_WaitForGraph, [], Acc) ->
    lists:reverse(Acc);
vertices_names(WaitForGraph, [Vertex|Tail], Acc) ->
    vertices_names(WaitForGraph, Tail, [vertex_name(WaitForGraph, Vertex)|Acc]).

(se vi state chiedendo perché TWFG non varia, la risposta è che digraph usa ETS per mantenere lo stato del grafo).