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