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
8CSnapIdPool::CSnapIdPool()
9{
10 Reset();
11}
12
13void 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
29void 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
46int 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
67void CSnapIdPool::TimeoutIds()
68{
69 // process timed ids
70 while(m_FirstTimed != -1)
71 RemoveFirstTimeout();
72}
73
74void 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