Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef GNASH_GC_H
00021 #define GNASH_GC_H
00022
00023 #include <list>
00024 #include <map>
00025 #include <string>
00026
00027 #ifndef NDEBUG
00028 # include <boost/thread.hpp>
00029 #endif
00030
00031 #include "dsodefs.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifdef GNASH_GC_DEBUG
00043 # include "log.h"
00044 # include "utility.h"
00045 # include <typeinfo>
00046 #endif
00047
00048 #include <cassert>
00049
00050
00051 namespace gnash {
00052
00053 class GC;
00054
00056
00062 class GcRoot
00063 {
00064
00065 public:
00066
00068
00075 virtual void markReachableResources() const=0;
00076
00077 virtual ~GcRoot() {}
00078 };
00079
00081
00084 class GcResource
00085 {
00086
00087 public:
00088
00089 friend class GC;
00090
00092
00096 GcResource();
00097
00101
00105 void setReachable() const
00106 {
00107
00108 if ( _reachable )
00109 {
00110 #if GNASH_GC_DEBUG > 2
00111 log_debug(_("Instance %p of class %s already reachable, setReachable doing nothing"),
00112 (void*)this, typeName(*this));
00113 #endif
00114 return;
00115 }
00116
00117 #if GNASH_GC_DEBUG > 2
00118 log_debug(_("Instance %p of class %s set to reachable, scanning reachable resources from it"),
00119 (void*)this, typeid(*this).name());
00120 #endif
00121
00122 _reachable = true;
00123 markReachableResources();
00124 }
00125
00127 bool isReachable() const { return _reachable; }
00128
00130 void clearReachable() const { _reachable = false; }
00131
00132 protected:
00133
00135
00148 virtual void markReachableResources() const
00149 {
00150 assert(_reachable);
00151 #if GNASH_GC_DEBUG > 1
00152 log_debug(_("Class %s didn't override the markReachableResources() method"), typeid(*this).name());
00153 #endif
00154 }
00155
00157
00161 virtual ~GcResource()
00162 {
00163 }
00164
00165 private:
00166
00167 mutable bool _reachable;
00168
00169 };
00170
00172
00185 class DSOEXPORT GC
00186 {
00187
00188 public:
00189
00191
00192 static GC& init(GcRoot& r);
00193
00196
00199 static void cleanup();
00200
00202
00206 static GC& get() {
00207 return *_singleton;
00208 }
00209
00211
00227 void addCollectable(const GcResource* item)
00228 {
00229 #ifndef NDEBUG
00230 boost::thread self;
00231 assert(self == mainThread);
00232 assert(item);
00233 assert(! item->isReachable());
00234
00235
00236 #endif
00237
00238 _resList.push_back(item); ++_resListSize;
00239 #if GNASH_GC_DEBUG > 1
00240 log_debug(_("GC: collectable %p added, num collectables: %d"), item, _resListSize);
00241 #endif
00242 }
00243
00245 void fuzzyCollect()
00246 {
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 if ( _resListSize < _lastResCount + maxNewCollectablesCount )
00277 {
00278 #if GNASH_GC_DEBUG > 1
00279 log_debug(_("GC: collection cycle skipped - %d/%d new resources allocated since last run (from %d to %d)"), _resListSize-_lastResCount, maxNewCollectablesCount, _lastResCount, _resListSize);
00280 #endif // GNASH_GC_DEBUG
00281 return;
00282 }
00283
00284 runCycle();
00285 }
00286
00288
00291 void runCycle();
00292
00293 typedef std::map<std::string, unsigned int> CollectablesCount;
00294
00296 void countCollectables(CollectablesCount& count) const;
00297
00298 private:
00299
00302 static unsigned int maxNewCollectablesCount;
00303
00305 GC(GcRoot& root)
00306 :
00307 _resListSize(0),
00308 _root(root),
00309 _lastResCount(0)
00310 #ifdef GNASH_GC_DEBUG
00311 , _collectorRuns(0)
00312 #endif
00313 {
00314 #ifdef GNASH_GC_DEBUG
00315 log_debug(_("GC %p created"), (void*)this);
00316 #endif
00317 }
00318
00320 ~GC();
00321
00323 typedef std::list<const GcResource *> ResList;
00324
00326 void markReachable()
00327 {
00328 #if GNASH_GC_DEBUG > 2
00329 log_debug(_("GC %p: MARK SCAN"), (void*)this);
00330 #endif
00331 _root.markReachableResources();
00332 }
00333
00335
00338 size_t cleanUnreachable();
00339
00341 ResList _resList;
00342
00343
00344
00345
00346
00347 ResList::size_type _resListSize;
00348
00349 GcRoot& _root;
00350
00351 static GC* _singleton;
00352
00353 #ifndef NDEBUG
00354
00355
00356
00357 boost::thread mainThread;
00358 #endif
00359
00362 ResList::size_type _lastResCount;
00363
00364 #ifdef GNASH_GC_DEBUG
00365
00366 size_t _collectorRuns;
00367 #endif
00368 };
00369
00370
00371 inline GcResource::GcResource()
00372 :
00373 _reachable(false)
00374 {
00375 GC::get().addCollectable(this);
00376 }
00377
00378 }
00379
00380 #endif // GNASH_GC_H