* Update mmanager to version from article part 5.
[matthijs/ABM2.git] / ABM2 / Engine / mmanager.cpp
1 #ifndef USING_ENGINUITY\r
2 #define USING_ENGINUITY\r
3 #endif\r
4 #include "engine.h"\r
5 \r
6 \r
7 IMMObject *IMMObject::liveObjects=0;\r
8 IMMObject *IMMObject::deadObjects=0;\r
9 std::list<IMMObject *> IMMObject::heapObjects;\r
10 unsigned long IMMObject::heapUsage=0;\r
11 \r
12 IMMObject::IMMObject()\r
13 {\r
14         nextObject=prevObject=0;\r
15         refCount=0;\r
16         std::list<IMMObject*>::iterator it=std::find(heapObjects.begin(),heapObjects.end(),this);\r
17         if(it==heapObjects.end())\r
18         {\r
19                 bIsStackAllocated=true;\r
20         }else{\r
21                 bIsStackAllocated=false;\r
22                 heapObjects.erase(it);\r
23         }\r
24         if(!bIsStackAllocated)\r
25         {\r
26                 //start on the deadObjects list\r
27                 nextObject=deadObjects;\r
28                 if(deadObjects)deadObjects->prevObject=this;\r
29                 deadObjects=this;\r
30         }\r
31 }\r
32 \r
33 IMMObject::~IMMObject()\r
34 {\r
35 \r
36 }\r
37 \r
38 void IMMObject::CollectGarbage()\r
39 {\r
40         while(deadObjects)\r
41         {\r
42                 IMMObject *nObj=deadObjects->nextObject;\r
43                 delete deadObjects;\r
44                 deadObjects=nObj;\r
45         }\r
46 }\r
47 \r
48 void IMMObject::AddRef()\r
49 {\r
50         refCount++;\r
51         if(!bIsStackAllocated&&(refCount==1))\r
52         {\r
53                 //move to the liveObjects list\r
54                 if(prevObject)prevObject->nextObject=nextObject;\r
55                 if(nextObject)nextObject->prevObject=prevObject;\r
56                 if(deadObjects==this)deadObjects=nextObject;\r
57                 prevObject=0;\r
58                 nextObject=liveObjects; if(liveObjects)liveObjects->prevObject=this;\r
59                 liveObjects=this;\r
60         }\r
61 }\r
62 \r
63 void IMMObject::Release()\r
64 {\r
65         refCount--; \r
66         if(!bIsStackAllocated&&(refCount<=0))\r
67         {\r
68                 //remove self from live list\r
69                 if(prevObject)prevObject->nextObject=nextObject;\r
70                 if(nextObject)nextObject->prevObject=prevObject;\r
71                 if(liveObjects==this)liveObjects=nextObject;\r
72                 prevObject=0;\r
73                 //add self to dead list\r
74                 nextObject=deadObjects;\r
75                 if(deadObjects)deadObjects->prevObject=this;\r
76                 deadObjects=this;\r
77                 \r
78         }\r
79 }\r
80 \r
81 void IMMObject::CollectRemainingObjects(bool bEmitWarnings)\r
82 {\r
83         CollectGarbage();\r
84         while(liveObjects)\r
85         {\r
86                 IMMObject *o=liveObjects->nextObject;\r
87                 if(bEmitWarnings)\r
88                 {\r
89                         //copy the object to a temporary buffer so that our '10 bytes' message doesn't\r
90                         //cause an access violation\r
91                         char szBuf[11]; memset(szBuf,0,11);\r
92                         memcpy(szBuf,liveObjects,min(liveObjects->size(),10));\r
93                         CLog::Get().Write(LOG_APP,IDS_UNRELEASED_OBJECT,liveObjects,liveObjects->size(),szBuf);\r
94                 }\r
95                 delete liveObjects;\r
96                 liveObjects=o;\r
97         }\r
98 }\r
99 \r
100 void* IMMObject::operator new(size_t objsize)\r
101 {\r
102         void *newObj=malloc(objsize);\r
103         heapUsage+=objsize;\r
104         heapObjects.push_back((IMMObject*)newObj);\r
105         ((IMMObject*)newObj)->heapAllocSize=objsize;\r
106         return newObj;\r
107 }\r
108 \r
109 void IMMObject::operator delete(void* obj)\r
110 {\r
111         if(!((IMMObject*)obj)->bIsStackAllocated)\r
112         {\r
113                 heapUsage-=((IMMObject*)obj)->heapAllocSize;\r
114                 free(obj);\r
115         }\r
116 }\r