forked from spring/spring
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathObject.cpp
More file actions
120 lines (83 loc) · 3.29 KB
/
Object.cpp
File metadata and controls
120 lines (83 loc) · 3.29 KB
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
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "System/Object.h"
#include "System/ContainerUtil.h"
#include "System/creg/STL_Map.h"
#include "System/Log/ILog.h"
#include "System/Platform/CrashHandler.h"
CR_BIND(CObject, )
CR_REG_METADATA(CObject, (
CR_MEMBER(sync_id),
CR_MEMBER(detached),
CR_MEMBER(listening),
CR_MEMBER(listeners),
CR_MEMBER(listenersDepTbl),
CR_MEMBER(listeningDepTbl)
))
std::atomic<std::int64_t> CObject::cur_sync_id(0);
static bool VectorInsertSorted(std::vector<CObject*>& v, CObject* o)
{
return (spring::VectorInsertUniqueSorted(v, o, [](const CObject* a, const CObject* b) { return (a->GetSyncID() < b->GetSyncID()); }));
}
static bool VectorEraseSorted(std::vector<CObject*>& v, CObject* o)
{
return (spring::VectorEraseUniqueSorted(v, o, [](const CObject* a, const CObject* b) { return (a->GetSyncID() < b->GetSyncID()); }));
}
CObject::CObject() : detached(false)
{
// Note1: this static var is shared between all different types of classes synced & unsynced (CUnit, CFeature, CProjectile, ...)
// Still it doesn't break syncness even when synced objects have different sync_ids between clients as long as the sync_id is
// creation time dependent and monotonously increasing, so the _order_ remains between clients.
// Use atomic fetch-and-add, so threads don't read half written data nor write old (= smaller) numbers
sync_id = ++cur_sync_id;
assert((sync_id + 1) > sync_id); // check for overflow
}
CObject::~CObject()
{
assert(!detached);
detached = true;
for (const auto& p: listenersDepTbl) {
assert(p.first >= DEPENDENCE_ATTACKER && p.first < DEPENDENCE_COUNT);
assert(p.second < listeners.size());
for (CObject* obj: listeners[p.second]) {
obj->DependentDied(this);
const auto jt = obj->listeningDepTbl.find(p.first);
if (jt == obj->listeningDepTbl.end())
continue;
VectorEraseSorted(obj->listening[ jt->second ], this);
}
}
for (const auto& p: listeningDepTbl) {
assert(p.first >= DEPENDENCE_ATTACKER && p.first < DEPENDENCE_COUNT);
assert(p.second < listening.size());
for (CObject* obj: listening[p.second]) {
const auto jt = obj->listenersDepTbl.find(p.first);
if (jt == obj->listenersDepTbl.end())
continue;
VectorEraseSorted(obj->listeners[ jt->second ], this);
}
}
}
// NOTE:
// we can be listening to a single object from several different places
// objects are responsible for not adding the same dependence more than
// once, and preferably try to delete the dependence ASAP in order not
// to waste memory
void CObject::AddDeathDependence(CObject* obj, DependenceType dep)
{
assert(!detached && !obj->detached);
// check this explicitly
if (detached || obj->detached)
return;
VectorInsertSorted(const_cast<TSyncSafeSet&>( GetListening(dep)), obj);
VectorInsertSorted(const_cast<TSyncSafeSet&>(obj->GetListeners(dep)), this);
}
void CObject::DeleteDeathDependence(CObject* obj, DependenceType dep)
{
assert(!detached);
if (detached || obj->detached)
return;
const auto it = listeningDepTbl.find(dep);
const auto jt = obj->listenersDepTbl.find(dep);
if (it != listeningDepTbl.end()) VectorEraseSorted( listening[ it->second ], obj);
if (jt != obj->listenersDepTbl.end()) VectorEraseSorted(obj->listeners[ jt->second ], this);
}