File: SimObjectIDPool.cpp

package info (click to toggle)
spring 104.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 47,512 kB
  • sloc: cpp: 391,093; ansic: 79,943; python: 12,356; java: 12,201; awk: 5,889; sh: 1,826; xml: 655; makefile: 486; perl: 405; php: 211; objc: 194; sed: 2
file content (118 lines) | stat: -rw-r--r-- 3,364 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#include "SimObjectIDPool.h"
#include "GlobalSynced.h"
#include "Sim/Objects/SolidObject.h"
#include "System/creg/STL_Map.h"


CR_BIND(SimObjectIDPool, )
CR_REG_METADATA(SimObjectIDPool, (
	CR_MEMBER(liveIdentToIndexMap),
	CR_MEMBER(liveIndexToIdentMap),
	CR_MEMBER(tempIndexToIdentMap)
))

void SimObjectIDPool::Expand(unsigned int baseID, unsigned int numIDs) {
	// allocate new batch of (randomly shuffled) id's
	std::vector<int> newIDs(numIDs);

	for (unsigned int offsetID = 0; offsetID < numIDs; offsetID++) {
		newIDs[offsetID] = baseID + offsetID;
	}

	// randomize so that Lua widgets can not easily determine counts
	std::random_shuffle(newIDs.begin(), newIDs.end(), gsRNG);
	std::random_shuffle(newIDs.begin(), newIDs.end(), gsRNG);

	// NOTE:
	//   any randomization would be undone by a sorted std::container
	//   instead create a bi-directional mapping from indices to ID's
	//   (where the ID's are a random permutation of the index range)
	//   such that ID's can be assigned and returned to the pool with
	//   their original index
	//
	//     indexToIdentMap = {<0, 13>, < 1, 27>, < 2, 54>, < 3, 1>, ...}
	//     identToIndexMap = {<1,  3>, <13,  0>, <27,  1>, <54, 2>, ...}
	//
	//   (the ID --> index map is never changed at runtime!)
	for (unsigned int offsetID = 0; offsetID < numIDs; offsetID++) {
		liveIndexToIdentMap.insert(IDPair(baseID + offsetID, newIDs[offsetID]));
		liveIdentToIndexMap.insert(IDPair(newIDs[offsetID], baseID + offsetID));
	}
}



void SimObjectIDPool::AssignID(CSolidObject* object) {
	if (object->id < 0) {
		object->id = ExtractID();
	} else {
		ReserveID(object->id);
	}
}

unsigned int SimObjectIDPool::ExtractID() {
	// extract a random ID from the pool
	//
	// should be unreachable, UnitHandler
	// and FeatureHandler have safeguards
	assert(!IsEmpty());

	const IDMap::iterator it = liveIndexToIdentMap.begin();
	const unsigned int id = it->second;

	liveIndexToIdentMap.erase(it);

	if (IsEmpty()) {
		RecycleIDs();
	}

	return id;
}

void SimObjectIDPool::ReserveID(unsigned int id) {
	// reserve a chosen ID from the pool
	assert(HasID(id));
	assert(!IsEmpty());

	const IDMap::iterator it = liveIdentToIndexMap.find(id);
	const unsigned int idx = it->second;

	liveIndexToIdentMap.erase(idx);

	if (IsEmpty()) {
		RecycleIDs();
	}
}

void SimObjectIDPool::FreeID(unsigned int id, bool delayed) {
	// put an ID back into the pool either immediately
	// or after all remaining free ID's run out (which
	// is better iff the object count never gets close
	// to the maximum)
	assert(!HasID(id));

	if (delayed) {
		tempIndexToIdentMap.insert(IDPair(liveIdentToIndexMap[id], id));
	} else {
		liveIndexToIdentMap.insert(IDPair(liveIdentToIndexMap[id], id));
	}
}

void SimObjectIDPool::RecycleIDs() {
	// throw each ID recycled up until now back into the pool
	liveIndexToIdentMap.insert(tempIndexToIdentMap.begin(), tempIndexToIdentMap.end());
	tempIndexToIdentMap.clear();
}

bool SimObjectIDPool::HasID(unsigned int id) const {
	assert(liveIdentToIndexMap.find(id) != liveIdentToIndexMap.end());

	// check if given ID is available in this pool
	const IDMap::const_iterator it = liveIdentToIndexMap.find(id);
	const unsigned int idx = it->second;

	return (liveIndexToIdentMap.find(idx) != liveIndexToIdentMap.end());
}