Пример #1
0
 Graph Generator::Generate(list<int> parameter)
 {
     if(MinParamCount > 0 && (((int)parameter.size()) < MinParamCount))
     {
         stringstream exception;
         exception << "generator requires at least " << MinParamCount << " parameters";
         throw exception.str().c_str();
     }
     if(MaxParamCount >= 0 && (((int)parameter.size()) > MaxParamCount))
     {
         stringstream exception;
         exception << "generator allows at most " << MaxParamCount << " parameters";
         throw exception.str().c_str();
     }
     return DoGenerate(parameter);
 }
Пример #2
0
void cChunkGenerator::Execute(void)
{
	// To be able to display performance information, the generator counts the chunks generated.
	// When the queue gets empty, the count is reset, so that waiting for the queue is not counted into the total time.
	int NumChunksGenerated = 0;  // Number of chunks generated since the queue was last empty
	clock_t GenerationStart = clock();  // Clock tick when the queue started to fill
	clock_t LastReportTick = clock();  // Clock tick of the last report made (so that performance isn't reported too often)

	while (!m_ShouldTerminate)
	{
		cCSLock Lock(m_CS);
		while (m_Queue.empty())
		{
			if ((NumChunksGenerated > 16) && (clock() - LastReportTick > CLOCKS_PER_SEC))
			{
				LOG("Chunk generator performance: %.2f ch / sec (%d ch total)",
					static_cast<double>(NumChunksGenerated) * CLOCKS_PER_SEC/ (clock() - GenerationStart),
					NumChunksGenerated
				);
			}
			cCSUnlock Unlock(Lock);
			m_Event.Wait();
			if (m_ShouldTerminate)
			{
				return;
			}
			NumChunksGenerated = 0;
			GenerationStart = clock();
			LastReportTick = clock();
		}

		if (m_Queue.empty())
		{
			// Sometimes the queue remains empty
			// If so, we can't do any front() operations on it!
			continue;
		}

		cQueueItem item = m_Queue.front();  // Get next chunk from the queue
		bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
		m_Queue.erase(m_Queue.begin());  // Remove the item from the queue
		Lock.Unlock();  // Unlock ASAP
		m_evtRemoved.Set();

		// Display perf info once in a while:
		if ((NumChunksGenerated > 16) && (clock() - LastReportTick > 2 * CLOCKS_PER_SEC))
		{
			LOG("Chunk generator performance: %.2f ch / sec (%d ch total)",
				static_cast<double>(NumChunksGenerated) * CLOCKS_PER_SEC / (clock() - GenerationStart),
				NumChunksGenerated
			);
			LastReportTick = clock();
		}

		// Skip the chunk if it's already generated and regeneration is not forced:
		if (!item.m_ForceGenerate && m_ChunkSink->IsChunkValid(item.m_ChunkX, item.m_ChunkZ))
		{
			LOGD("Chunk [%d, %d] already generated, skipping generation", item.m_ChunkX, item.m_ChunkZ);
			if (item.m_Callback != nullptr)
			{
				item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ);
			}
			continue;
		}

		// Skip the chunk if the generator is overloaded:
		if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(item.m_ChunkX, item.m_ChunkZ))
		{
			LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", item.m_ChunkX, item.m_ChunkZ);
			if (item.m_Callback != nullptr)
			{
				item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ);
			}
			continue;
		}

		// Generate the chunk:
		LOGD("Generating chunk [%d, %d]", item.m_ChunkX, item.m_ChunkZ);
		DoGenerate(item.m_ChunkX, item.m_ChunkZ);
		if (item.m_Callback != nullptr)
		{
			item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ);
		}
		NumChunksGenerated++;
	}  // while (!bStop)
}
Пример #3
0
static  void    Generate( void ) {
//================================

// Generate code.

    TYPE        typ1;
    TYPE        typ2;
    OPTR        op;
    OPR         opr;
    itnode      *next;
    unsigned_16 mask;
    uint        res_size;

    next = CITNode->link;
    if( next->opn.ds == DSOPN_PHI ) {
        BadSequence();
    } else {
        typ1 = CITNode->typ;
        typ2 = next->typ;
        opr = next->opr;
        if( RecNOpn() ) {
            typ1 = FT_NO_TYPE;
            CITNode->size = next->size;
            if( (opr != OPR_PLS) && (opr != OPR_MIN) && (opr != OPR_NOT) ) {
                BadSequence();
                return;
            }
        }
        op = OprNum[ opr ];
        if( typ1 == FT_NO_TYPE ) {
            mask = LegalOprsU[ typ2 - FT_FIRST ];
        } else {
            mask = LegalOprsB[ ( typ2 - FT_FIRST ) * LEGALOPR_TAB_COLS + typ1 - FT_FIRST ];
        }
        if( (( mask >> ( op - OPTR_FIRST ) ) & 1) == 0 ) {
            // illegal combination
            MoveDown();
            if( typ1 == FT_NO_TYPE ) {
                TypeErr( MD_UNARY_OP, typ2 );
            } else if( typ1 == typ2 ) {
                TypeErr( MD_ILL_OPR, typ1 );
            } else {
                TypeTypeErr( MD_MIXED, typ1, typ2 );
            }
            BackTrack();
        } else if( DoGenerate( typ1, typ2, &res_size ) ) {
            if( ( opr >= OPR_FIRST_RELOP ) && ( opr <= OPR_LAST_RELOP ) &&
                ( (ResultType == FT_COMPLEX) || (ResultType == FT_DCOMPLEX) ||
                (ResultType == FT_XCOMPLEX) ) &&
                ( opr != OPR_EQ ) && ( opr != OPR_NE ) ) {
                // can only compare complex with .EQ. and .NE.
                Error( MD_RELOP_OPND_COMPLEX );
            } else {
                if( ( next->opn.us == USOPN_CON ) &&
                    ( ( CITNode->opn.us == USOPN_CON ) || ( typ1 == FT_NO_TYPE ) ) ) {
                    // we can do some constant folding
                    ConstTable[ op ]( typ1, typ2, op );
                } else {
                    // we have to generate code
                    if( CITNode->opn.us == USOPN_CON ) {
                        AddConst( CITNode );
                    } else if( next->opn.us == USOPN_CON ) {
                        AddConst( next );
                    }
                    GenOprTable[ op ]( typ1, typ2, op );
                }
            }
            switch( opr ) {
            case OPR_EQV:
            case OPR_NEQV:
            case OPR_OR:
            case OPR_AND:
            case OPR_NOT:
                if( _IsTypeInteger( typ1 ) ) {
                    Extension( MD_LOGOPR_INTOPN );
                }
                break;
            case OPR_EQ:        // relational operators
            case OPR_NE:
            case OPR_LT:
            case OPR_GE:
            case OPR_LE:
            case OPR_GT:
                ResultType = FT_LOGICAL;
                res_size = TypeSize( ResultType );
                break;
            case OPR_FLD:
            case OPR_DPT:
                // set result size to size of field
                res_size = next->size;
                FixFldNode();
                break;
            }
            CITNode->size = res_size;
            CITNode->typ = ResultType;
            FixList();
        }
    }
Пример #4
0
void cChunkGenerator::Execute(void)
{
	// To be able to display performance information, the generator counts the chunks generated.
	// When the queue gets empty, the count is reset, so that waiting for the queue is not counted into the total time.
	int NumChunksGenerated = 0;  // Number of chunks generated since the queue was last empty
	clock_t GenerationStart = clock();  // Clock tick when the queue started to fill
	clock_t LastReportTick = clock();  // Clock tick of the last report made (so that performance isn't reported too often)

	while (!m_ShouldTerminate)
	{
		cCSLock Lock(m_CS);
		while (m_Queue.size() == 0)
		{
			if ((NumChunksGenerated > 16) && (clock() - LastReportTick > CLOCKS_PER_SEC))
			{
				LOG("Chunk generator performance: %.2f ch/s (%d ch total)",
					(double)NumChunksGenerated * CLOCKS_PER_SEC/ (clock() - GenerationStart),
					NumChunksGenerated
				);
			}
			cCSUnlock Unlock(Lock);
			m_Event.Wait();
			if (m_ShouldTerminate)
			{
				return;
			}
			NumChunksGenerated = 0;
			GenerationStart = clock();
			LastReportTick = clock();
		}

		cChunkCoords coords = m_Queue.front();		// Get next coord from queue
		m_Queue.erase( m_Queue.begin() );	// Remove coordinate from queue
		bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
		Lock.Unlock();			// Unlock ASAP
		m_evtRemoved.Set();

		// Display perf info once in a while:
		if ((NumChunksGenerated > 16) && (clock() - LastReportTick > 2 * CLOCKS_PER_SEC))
		{
			LOG("Chunk generator performance: %.2f ch/s (%d ch total)",
				(double)NumChunksGenerated * CLOCKS_PER_SEC / (clock() - GenerationStart),
				NumChunksGenerated
			);
			LastReportTick = clock();
		}

		// Hack for regenerating chunks: if Y != 0, the chunk is considered invalid, even if it has its data set
		if ((coords.m_ChunkY == 0) && m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
		{
			LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
			// Already generated, ignore request
			continue;
		}

		if (SkipEnabled && !m_World->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkZ))
		{
			LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
			continue;
		}

		LOGD("Generating chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
		DoGenerate(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);

		// Save the chunk right after generating, so that we don't have to generate it again on next run
		m_World->GetStorage().QueueSaveChunk(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);

		NumChunksGenerated++;
	}  // while (!bStop)
}