File: Object.h

package info (click to toggle)
spring 106.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 55,260 kB
  • sloc: cpp: 543,946; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (136 lines) | stat: -rw-r--r-- 4,376 bytes parent folder | download | duplicates (3)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef OBJECT_H
#define OBJECT_H

#include <atomic>
#include <functional>
#include <vector>

#include "ObjectDependenceTypes.h"
#include "System/creg/creg_cond.h"
#include "System/UnorderedMap.hpp"

class CObject
{
public:
	CR_DECLARE(CObject)

	CObject();
	virtual ~CObject();

	/// Request to not inform this when obj dies
	virtual void DeleteDeathDependence(CObject* obj, DependenceType dep);
	/// Request to inform this when obj dies
	virtual void AddDeathDependence(CObject* obj, DependenceType dep);
	/// Called when an object died, that this is interested in
	/// Any derived implementations should *NOT* modify listening
	/// or listeners because we iterate over both within our dtor
	/// when calling this
	virtual void DependentDied(CObject* obj) {}

/*
	// Possible future replacement for dynamic_cast (10x faster)
	// Identifier bits for classes that have subclasses
	enum {WORLDOBJECT_BIT=8,SOLIDOBJECT_BIT,UNIT_BIT,BUILDING_BIT,MOVETYPE_BIT,AAIRMOVETYPE_BIT,
		COMMANDAI_BIT,EXPGENSPAWNABLE_BIT,PROJECTILE_BIT,SMOKEPROJECTILE_BIT,WEAPON_BIT};
	// Class hierarchy for the relevant classes
	enum {
		OBJECT=0,
			WORLDOBJECT=(1<<WORLDOBJECT_BIT),
				SOLIDOBJECT=(1<<SOLIDOBJECT_BIT)|WORLDOBJECT,
					FEATURE,
					UNIT=(1<<UNIT_BIT)|SOLIDOBJECT,
						BUILDER,TRANSPORTUNIT,
						BUILDING=(1<<BUILDING_BIT)|UNIT,
							FACTORY,EXTRACTORBUILDING,
			MOVETYPE=(1<<MOVETYPE_BIT),
				GROUNDMOVETYPE,
				AAIRMOVETYPE=(1<<AAIRMOVETYPE_BIT)|MOVETYPE,
					AIRMOVETYPE,
					TAAIRMOVETYPE,
			COMMANDAI=(1<<COMMANDAI_BIT),
				FACTORYCAI,MOBILECAI,
			EXPGENSPAWNABLE=(1<<EXPGENSPAWNABLE_BIT),
				PROJECTILE=(1<<PROJECTILE_BIT)|EXPGENSPAWNABLE,
					SHIELDPARTPROJECTILE,
					SMOKEPROJECTILE=(1<<SMOKEPROJECTILE_BIT)|PROJECTILE,
						GEOTHERMSMOKEPROJECTILE,
			WEAPON=(1<<WEAPON_BIT),
				DGUNWEAPON,BEAMLASER
	};
	// Must also set objType in the contstructors of all classes that need to use this feature
	unsigned objType;
#define INSTANCE_OF_SUBCLASS_OF(type,obj) ((obj->objType & kind) == kind) // exact class or any subclass of it
#define INSTANCE_OF(type,obj) (obj->objType == type) // exact class only, saves one instruction yay :)
*/

	std::int64_t GetSyncID() const { return sync_id; }

private:
	// Note, this has nothing to do with the UnitID, FeatureID, ...
	// Its only purpose is to make the sorting in TSyncSafeSet syncsafe
	std::int64_t sync_id;
	static std::atomic<std::int64_t> cur_sync_id;

public:
	typedef std::vector<CObject*> TSyncSafeSet;
	typedef std::vector<TSyncSafeSet> TDependenceMap;
	typedef std::function<bool(const CObject*, int*)> TObjFilterPred;

	bool detached;

protected:
	const TSyncSafeSet& GetListeners(const DependenceType dep) {
		const auto it = listenersDepTbl.find(dep);

		if (it == listenersDepTbl.end()) {
			listeners.emplace_back();
			listenersDepTbl[dep] = listeners.size() - 1;
			return (listeners.back());
		}

		return (listeners[it->second]);
	}
	const TSyncSafeSet& GetListening(const DependenceType dep) {
		const auto it = listeningDepTbl.find(dep);

		if (it == listeningDepTbl.end()) {
			listening.emplace_back();
			listeningDepTbl[dep] = listening.size() - 1;
			return (listening.back());
		}

		return (listening[it->second]);
	}

	const TDependenceMap& GetAllListeners() const { return listeners; }
	const TDependenceMap& GetAllListening() const { return listening; }

	template<size_t N> static void FilterDepObjects(
		const TDependenceMap& depObjects,
		const TObjFilterPred& filterPred,
		std::array<int, N>& objectIDs
	) {
		objectIDs[0] = 0;

		for (const auto& objs: depObjects) {
			for (const CObject* obj: objs) {
				objectIDs[0] += ((objectIDs[0] < (N - 1)) && filterPred(obj, &objectIDs[objectIDs[0] + 1]));
			}
		}
	}

	template<size_t N> void FilterListeners(const TObjFilterPred& fp, std::array<int, N>& ids) const { FilterDepObjects(listeners, fp, ids); }
	template<size_t N> void FilterListening(const TObjFilterPred& fp, std::array<int, N>& ids) const { FilterDepObjects(listening, fp, ids); }

protected:
	spring::unordered_map<int, size_t> listenersDepTbl; // maps dependence-type to index into listeners
	spring::unordered_map<int, size_t> listeningDepTbl; // maps dependence-type to index into listening

	TDependenceMap listeners;
	TDependenceMap listening;
};

#endif /* OBJECT_H */