Куча говна / Говнокод #28000 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
%% Note: set and unset are not thread-safe.
-spec set(key(), value()) -> ok.
set(Key, Value) ->
    case ets:lookup(?status_tab, Key) of
        [{_, {set, _OldValue}}] ->
            ets:insert(?status_tab, {Key, {set, Value}});
        [{_, {unset, Pid}}] ->
            MRef = monitor(process, Pid),
            Pid ! {set, Value},
            receive
                {'DOWN', MRef, _, _, _} -> ok
            end;
        [] ->
            case ets:insert_new(?status_tab, {Key, {set, Value}}) of
                true  ->
                    ok;
                false ->
                    set(Key, Value)
            end
    end,
    ok.

-spec unset(key()) -> ok.
unset(Key) ->
    case ets:lookup(?status_tab, Key) of
        [{_, {set, _OldValue}}] -> ets:delete(?status_tab, Key);
        _                       -> ok
    end,
    ok.

-spec read(key()) -> value().
read(Key) ->
    case read_or_wait(Key) of
        {set, Value} ->
            Value;
        {wait, MRef} ->
            receive
                {'DOWN', MRef, _, _, {cvar_set, Value}} ->
                    Value;
                {'DOWN', MRef, _, _, noproc} ->
                    read(Key)
            end
    end.

-spec read_or_wait(key()) -> {set, value()} | {wait, reference()}.
read_or_wait(Key) ->
    case ets:lookup(?status_tab, Key) of
        [] ->
            {Pid, MRef} = spawn_monitor(?MODULE, waker_entrypoint, [Key, self()]),
            receive
                {Pid, proceed} ->
                    {wait, MRef};
                {'DOWN', MRef, _, _, Reason} ->
                    cvar_retry = Reason,
                    read_or_wait(Key)
            end;
        [{_, {set, Val}}] ->
            {set, Val};
        [{_, {unset, Pid}}] ->
            {wait, monitor(process, Pid)}
    end.

-spec waker_entrypoint(key(), pid()) -> no_return().
waker_entrypoint(Key, Parent) ->
    case ets_insert_new({Key, {unset, self()}}) of
        false ->
            exit(cvar_retry);
        true ->
            Parent ! {self(), proceed},
            receive
                {set, Value} ->
                    ets_insert({Key, {set, Value}}),
                    exit({cvar_set, Value})
            end
    end.

Запостил: CHayT CHayT, (Updated )

Комментарии (23) RSS

  • > %% Note: set and unset are not thread-safe.
    Это пример, как "дизайнить код так, чтобы его юзеры навсегда забыли о thread safety"?
    Ответить
  • > erlang
    > not thread-safe

    Какой скилл, в языке где нет тредов )))

    Просто какое-то неатомарное взаимодействие с внешним миром и сообщения могут перемешаться?
    Ответить
    • Очевидный неатомарный апдейт глобалки же:
      case ets:lookup(?status_tab, Key) of
              [{_, {set, _OldValue}}] ->
                  ets:insert(?status_tab, {Key, {set, Value}});


      > Какой скилл, в языке где нет тредов )))

      Как это нет? Они просто называются ``процессами'', но суть не меняется.
      Ответить
    • >> not thread-safe

      > Какой скилл, в языке где нет тредов )))

      "not thread-safe" можно и в контроллерах сделать, даже если не делать никаких специальных "тредов" и "процессов", например если прерывание конкурирует за ресурс с обычным кодом или с другим прерыванием.
      Ответить
  • В комментах должен был быть вывод: на самом деле разрабу знать математику не надо, ибо попытка написать свою хеш-функцию ведет лишь к тому что ее взломают. А значит нужно использовать встроенные в язык программирования хеш-функции - для их встраивания знать математику не надо и они безопасны ровно настолько, насколько боги математики закладывали в них безопасность при разработке действительно стойких хеш-функций.
    Ответить

Добавить комментарий

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8