|
1 | 1 | defmodule IEx.History do
|
| 2 | + @moduledoc false |
2 | 3 |
|
3 | 4 | def init do
|
4 |
| - Process.put :iex_history, :queue.new |
| 5 | + Process.put(:iex_history_start_counter, 1) |
| 6 | + Process.put(:iex_history_counter, 1) |
5 | 7 | end
|
6 | 8 |
|
7 | 9 | ### append ###
|
8 | 10 |
|
9 |
| - def append(entry) do |
10 |
| - history = Process.get(:iex_history) |
11 |
| - len = :queue.len(history) |
12 |
| - limit = IEx.Options.get(:history_size) |
13 |
| - |
14 |
| - new_history = |
15 |
| - :queue.in(entry, history) |
16 |
| - |> limit_history(len + 1, limit) |
17 |
| - Process.put(:iex_history, new_history) |
18 |
| - end |
| 11 | + def append(entry, counter) do |
| 12 | + Process.put({:iex_history, counter}, entry) |
| 13 | + Process.put(:iex_history_counter, counter+1) |
19 | 14 |
|
20 |
| - defp limit_history(_, _, 0) do |
21 |
| - :queue.new |
| 15 | + limit = IEx.Options.get(:history_size) |
| 16 | + start_counter = Process.get(:iex_history_start_counter) |
| 17 | + should_collect = limit_history(start_counter, counter, limit) |
| 18 | + if should_collect do |
| 19 | + IO.puts "...collecting garbage" |
| 20 | + :erlang.garbage_collect |
| 21 | + end |
22 | 22 | end
|
23 | 23 |
|
24 |
| - defp limit_history(queue, _, limit) when limit < 0 do |
25 |
| - queue |
| 24 | + defp limit_history(_, _, limit) when limit < 0 do |
| 25 | + false |
26 | 26 | end
|
27 | 27 |
|
28 |
| - defp limit_history(queue, len, limit) when len > limit do |
29 |
| - # FIXME: check if the result we're removing had any binaries in it and |
30 |
| - # garbage collect them |
31 |
| - limit_history(:queue.drop(queue), len-1, limit) |
| 28 | + defp limit_history(counter, max_counter, limit) when max_counter - counter < limit do |
| 29 | + Process.put(:iex_history_start_counter, counter) |
| 30 | + true |
32 | 31 | end
|
33 | 32 |
|
34 |
| - defp limit_history(queue, _, _) do |
35 |
| - queue |
| 33 | + defp limit_history(counter, max_counter, limit) do |
| 34 | + Process.delete({:iex_history, counter}) |
| 35 | + limit_history(counter+1, max_counter, limit) |
36 | 36 | end
|
37 | 37 |
|
38 | 38 | ### each ###
|
39 | 39 |
|
40 | 40 | def each(fun) do
|
41 |
| - history = Process.get(:iex_history) |
42 |
| - each(history, fun) |
| 41 | + each(Process.get(:iex_history_start_counter), |
| 42 | + Process.get(:iex_history_counter), |
| 43 | + fun) |
43 | 44 | end
|
44 | 45 |
|
45 |
| - defp each(queue, fun) do |
46 |
| - case :queue.out(queue) do |
47 |
| - { { :value, val }, tail } -> |
48 |
| - fun.(val) |
49 |
| - each(tail, fun) |
| 46 | + defp each(counter, max_counter, fun) when counter < max_counter do |
| 47 | + entry = Process.get({:iex_history, counter}) |
| 48 | + fun.(entry) |
| 49 | + each(counter+1, max_counter, fun) |
| 50 | + end |
50 | 51 |
|
51 |
| - { :empty, _ } -> :ok |
52 |
| - end |
| 52 | + defp each(_, _, _) do |
| 53 | + :ok |
53 | 54 | end
|
54 | 55 |
|
55 | 56 | ### nth ###
|
56 | 57 |
|
57 | 58 | def nth(n) do
|
58 |
| - history = Process.get(:iex_history) |
59 |
| - len = :queue.len(history) |
60 |
| - case n do |
61 |
| - n when n > 0 -> |
62 |
| - queue_nth(history, n - 1, len) |
| 59 | + entry = case n do |
| 60 | + n when n >= 0 -> |
| 61 | + Process.get({:iex_history, n}) |
63 | 62 | n when n < 0 ->
|
64 |
| - queue_nth_r(history, -n - 1, len) |
65 |
| - 0 -> |
66 |
| - raise ArgumentError[] |
| 63 | + counter = Process.get(:iex_history_counter) |
| 64 | + Process.get({:iex_history, counter + n}) |
67 | 65 | end
|
68 |
| - end |
69 |
| - |
70 |
| - defp queue_nth(_, _, 0) do |
71 |
| - raise_bounds |
72 |
| - end |
73 |
| - |
74 |
| - defp queue_nth(queue, 0, _) do |
75 |
| - { :value, value } = :queue.peek(queue) |
76 |
| - value |
77 |
| - end |
78 |
| - |
79 |
| - defp queue_nth(queue, n, len) when n > 0 do |
80 |
| - queue_nth(:queue.drop(queue), n-1, len-1) |
81 |
| - end |
82 |
| - |
83 |
| - defp queue_nth_r(_, _, 0) do |
84 |
| - raise_bounds |
85 |
| - end |
86 |
| - |
87 |
| - defp queue_nth_r(queue, 0, _) do |
88 |
| - { :value, value } = :queue.peek_r(queue) |
89 |
| - value |
90 |
| - end |
91 |
| - |
92 |
| - defp queue_nth_r(queue, n, len) when n > 0 do |
93 |
| - queue_nth_r(:queue.drop_r(queue), n-1, len-1) |
94 |
| - end |
95 |
| - |
96 |
| - defp raise_bounds do |
97 |
| - raise "Out of bounds" |
| 66 | + if nil?(entry) do |
| 67 | + raise "Out of bounds" |
| 68 | + end |
| 69 | + entry |
98 | 70 | end
|
99 | 71 | end
|
0 commit comments