1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
---|---|
2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
3 | |
4 | #include "snap_id_pool.h" |
5 | |
6 | #include <base/system.h> |
7 | |
8 | CSnapIdPool::CSnapIdPool() |
9 | { |
10 | Reset(); |
11 | } |
12 | |
13 | void CSnapIdPool::Reset() |
14 | { |
15 | for(int i = 0; i < MAX_IDS; i++) |
16 | { |
17 | m_aIds[i].m_Next = i + 1; |
18 | m_aIds[i].m_State = ID_FREE; |
19 | } |
20 | |
21 | m_aIds[MAX_IDS - 1].m_Next = -1; |
22 | m_FirstFree = 0; |
23 | m_FirstTimed = -1; |
24 | m_LastTimed = -1; |
25 | m_Usage = 0; |
26 | m_InUsage = 0; |
27 | } |
28 | |
29 | void CSnapIdPool::RemoveFirstTimeout() |
30 | { |
31 | int NextTimed = m_aIds[m_FirstTimed].m_Next; |
32 | |
33 | // add it to the free list |
34 | m_aIds[m_FirstTimed].m_Next = m_FirstFree; |
35 | m_aIds[m_FirstTimed].m_State = ID_FREE; |
36 | m_FirstFree = m_FirstTimed; |
37 | |
38 | // remove it from the timed list |
39 | m_FirstTimed = NextTimed; |
40 | if(m_FirstTimed == -1) |
41 | m_LastTimed = -1; |
42 | |
43 | m_Usage--; |
44 | } |
45 | |
46 | int CSnapIdPool::NewId() |
47 | { |
48 | int64_t Now = time_get(); |
49 | |
50 | // process timed ids |
51 | while(m_FirstTimed != -1 && m_aIds[m_FirstTimed].m_Timeout < Now) |
52 | RemoveFirstTimeout(); |
53 | |
54 | int Id = m_FirstFree; |
55 | if(Id == -1) |
56 | { |
57 | dbg_msg(sys: "server", fmt: "invalid id"); |
58 | return Id; |
59 | } |
60 | m_FirstFree = m_aIds[m_FirstFree].m_Next; |
61 | m_aIds[Id].m_State = ID_ALLOCATED; |
62 | m_Usage++; |
63 | m_InUsage++; |
64 | return Id; |
65 | } |
66 | |
67 | void CSnapIdPool::TimeoutIds() |
68 | { |
69 | // process timed ids |
70 | while(m_FirstTimed != -1) |
71 | RemoveFirstTimeout(); |
72 | } |
73 | |
74 | void CSnapIdPool::FreeId(int Id) |
75 | { |
76 | if(Id < 0) |
77 | return; |
78 | dbg_assert((size_t)Id < std::size(m_aIds), "id is out of range"); |
79 | dbg_assert(m_aIds[Id].m_State == ID_ALLOCATED, "id is not allocated"); |
80 | |
81 | m_InUsage--; |
82 | m_aIds[Id].m_State = ID_TIMED; |
83 | m_aIds[Id].m_Timeout = time_get() + time_freq() * 5; |
84 | m_aIds[Id].m_Next = -1; |
85 | |
86 | if(m_LastTimed != -1) |
87 | { |
88 | m_aIds[m_LastTimed].m_Next = Id; |
89 | m_LastTimed = Id; |
90 | } |
91 | else |
92 | { |
93 | m_FirstTimed = Id; |
94 | m_LastTimed = Id; |
95 | } |
96 | } |
97 |