예제 #1
0
파일: Grid.cpp 프로젝트: AMiller90/Homework
void Grid::PrintChildren(int NumofNode)
{
	node* ptr = ReturnNode(NumofNode);

	if (ptr != NULL)
	{
		cout << "Node = " << ptr->NumofNode << endl;

		ptr->Left == NULL ?
		cout << "Left Child = Null\n":
		cout << "Left Child = " << ptr->Left->NumofNode << endl;

		ptr->Right == NULL ?
			cout << "Right Child = Null\n" :
			cout << "Right Child = " << ptr->Right->NumofNode << endl;
	}
	else
	{
		cout << "Node is not in the tree\n";
	}
}
예제 #2
0
int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
{
	for(;;)
	{
		switch( detectState )
		{
		case clearCounters_init:
			detectState = clearCounters_loop;
		break;

		case clearCounters_loop:
		{
			// Decrease reference counter for all objects removed from the map
			asSMapNode<void*, asSIntTypePair> *cursor = 0;
			gcMap.MoveFirst(&cursor);
			if( cursor )
			{
				void *obj = gcMap.GetKey(cursor);
				asSIntTypePair it = gcMap.GetValue(cursor);

				engine->CallObjectMethod(obj, it.type->beh.release);

				ReturnNode(gcMap.Remove(cursor));

				return 1;
			}

			detectState = buildMap_init;
		}
		break;

		case buildMap_init:
			detectIdx = 0;
			detectState = buildMap_loop;
		break;

		case buildMap_loop:
		{
			// Build a map of objects that will be checked, the map will
			// hold the object pointer as key, and the gcCount and the
			// object's type as value. As objects are added to the map the
			// gcFlag must be set in the objects, so we can be verify if
			// the object is accessed during the GC cycle.

			// If an object is removed from the gcObjects list during the
			// iteration of this step, it is possible that an object won't
			// be used during the analyzing for cyclic references. This
			// isn't a problem, as the next time the GC cycle starts the
			// object will be verified.
			if( detectIdx < gcOldObjects.GetLength() )
			{
				// Add the gc count for this object
				asSObjTypePair gcObj = GetOldObjectAtIdx(detectIdx);
	
				int refCount = 0;
				if( gcObj.type->beh.gcGetRefCount )
					refCount = engine->CallObjectMethodRetInt(gcObj.obj, gcObj.type->beh.gcGetRefCount);

				if( refCount > 1 )
				{
					asSIntTypePair it = {refCount-1, gcObj.type};

					gcMap.Insert(GetNode(gcObj.obj, it));

					// Increment the object's reference counter when putting it in the map
					engine->CallObjectMethod(gcObj.obj, gcObj.type->beh.addref);

					// Mark the object so that we can
					// see if it has changed since read
					engine->CallObjectMethod(gcObj.obj, gcObj.type->beh.gcSetFlag);
				}

				detectIdx++; 

				// Let the application work a little
				return 1;
			}
			else
				detectState = countReferences_init;
		}
		break;

		case countReferences_init:
		{
			gcMap.MoveFirst(&gcMapCursor);
			detectState = countReferences_loop;
		}
		break;

		case countReferences_loop:
		{
			// Call EnumReferences on all objects in the map to count the number
			// of references reachable from between objects in the map. If all
			// references for an object in the map is reachable from other objects
			// in the map, then we know that no outside references are held for
			// this object, thus it is a potential dead object in a circular reference.

			// If the gcFlag is cleared for an object we consider the object alive
			// and referenced from outside the GC, thus we don't enumerate its references.

			// Any new objects created after this step in the GC cycle won't be
			// in the map, and is thus automatically considered alive.
			if( gcMapCursor )
			{
				void *obj = gcMap.GetKey(gcMapCursor);
				asCObjectType *type = gcMap.GetValue(gcMapCursor).type;
				gcMap.MoveNext(&gcMapCursor, gcMapCursor);

				if( engine->CallObjectMethodRetBool(obj, type->beh.gcGetFlag) )
				{
					engine->CallObjectMethod(obj, engine, type->beh.gcEnumReferences);
				}

				// Allow the application to work a little
				return 1;
			}
			else
				detectState = detectGarbage_init;
		}
		break;

		case detectGarbage_init:
		{
			gcMap.MoveFirst(&gcMapCursor);
			liveObjects.SetLength(0);
			detectState = detectGarbage_loop1;
		}
		break;

		case detectGarbage_loop1:
		{
			// All objects that are known not to be dead must be removed from the map,
			// along with all objects they reference. What remains in the map after
			// this pass is sure to be dead objects in circular references.

			// An object is considered alive if its gcFlag is cleared, or all the
			// references were not found in the map.

			// Add all alive objects from the map to the liveObjects array
			if( gcMapCursor )
			{
				asSMapNode<void*, asSIntTypePair> *cursor = gcMapCursor;
				gcMap.MoveNext(&gcMapCursor, gcMapCursor);

				void *obj = gcMap.GetKey(cursor);
				asSIntTypePair it = gcMap.GetValue(cursor);

				bool gcFlag = engine->CallObjectMethodRetBool(obj, it.type->beh.gcGetFlag);
				if( !gcFlag || it.i > 0 )
				{
					liveObjects.PushLast(obj);
				}

				// Allow the application to work a little
				return 1;
			}
			else
				detectState = detectGarbage_loop2;
		}
		break;

		case detectGarbage_loop2:
		{
			// In this step we are actually removing the alive objects from the map.
			// As the object is removed, all the objects it references are added to the
			// liveObjects list, by calling EnumReferences. Only objects still in the map
			// will be added to the liveObjects list.
			if( liveObjects.GetLength() )
			{
				void *gcObj = liveObjects.PopLast();
				asCObjectType *type = 0;

				// Remove the object from the map to mark it as alive
				asSMapNode<void*, asSIntTypePair> *cursor = 0;
				if( gcMap.MoveTo(&cursor, gcObj) )
				{
					type = gcMap.GetValue(cursor).type;
					ReturnNode(gcMap.Remove(cursor));

					// We need to decrease the reference count again as we remove the object from the map
					engine->CallObjectMethod(gcObj, type->beh.release);

					// Enumerate all the object's references so that they too can be marked as alive
					engine->CallObjectMethod(gcObj, engine, type->beh.gcEnumReferences);
				}

				// Allow the application to work a little
				return 1;
			}
			else
				detectState = verifyUnmarked_init;
		}
		break;

		case verifyUnmarked_init:
			gcMap.MoveFirst(&gcMapCursor);
			detectState = verifyUnmarked_loop;
			break;

		case verifyUnmarked_loop:
		{
			// In this step we must make sure that none of the objects still in the map
			// has been touched by the application. If they have then we must run the
			// detectGarbage loop once more.
			if( gcMapCursor )
			{
				void *gcObj = gcMap.GetKey(gcMapCursor);
				asCObjectType *type = gcMap.GetValue(gcMapCursor).type;

				bool gcFlag = engine->CallObjectMethodRetBool(gcObj, type->beh.gcGetFlag);
				if( !gcFlag )
				{
					// The unmarked object was touched, rerun the detectGarbage loop
					detectState = detectGarbage_init;
				}
				else
					gcMap.MoveNext(&gcMapCursor, gcMapCursor);

				// Allow the application to work a little
				return 1;
			}
			else
			{
				// No unmarked object was touched, we can now be sure
				// that objects that have gcCount == 0 really is garbage
				detectState = breakCircles_init;
			}
		}
		break;

		case breakCircles_init:
		{
			gcMap.MoveFirst(&gcMapCursor);
			detectState = breakCircles_loop;
		}
		break;

		case breakCircles_loop:
		case breakCircles_haveGarbage:
		{
			// All objects in the map are now known to be dead objects
			// kept alive through circular references. To be able to free
			// these objects we need to force the breaking of the circle
			// by having the objects release their references.
			if( gcMapCursor )
			{
				numDetected++;
				void *gcObj = gcMap.GetKey(gcMapCursor);
				asCObjectType *type = gcMap.GetValue(gcMapCursor).type;
				engine->CallObjectMethod(gcObj, engine, type->beh.gcReleaseAllReferences);

				gcMap.MoveNext(&gcMapCursor, gcMapCursor);

				detectState = breakCircles_haveGarbage;

				// Allow the application to work a little
				return 1;
			}
			else
			{
				// If no garbage was detected we can finish now
				if( detectState != breakCircles_haveGarbage )
				{
					// Restart the GC
					detectState = clearCounters_init;
					return 0;
				}
				else
				{
					// Restart the GC
					detectState = clearCounters_init;
					return 1;
				}
			}
		}
		} // switch
	}

	// Shouldn't reach this point
	UNREACHABLE_RETURN;
}