void
tmTransactionManager::HandleTransaction(tmTransaction *aTrans) {

  PRUint32 action = aTrans->GetAction();
  PRUint32 ownerID = aTrans->GetOwnerID();
  tmQueue *queue = nsnull;

  // get the right queue -- attaches do it differently
  if (action == TM_ATTACH) {
    const char *name = (char*) aTrans->GetMessage(); // is qName for Attaches
    queue = GetQueue(name);  
    if (!queue) {
      PRInt32 index = AddQueue(name);
      if (index >= 0)
        queue = GetQueue(index); // GetQueue may return nsnull
    }
  }
  else  // all other trans should have a valid queue ID already
    queue = GetQueue(aTrans->GetQueueID());

  if (queue) {
    // All possible actions should have a case, default is not valid
    //   delete trans when done with them, let the queue own the trans
    //   that are posted to them.
    PRInt32 result = 0;
    switch (action) {
    case TM_ATTACH:
      queue->AttachClient(ownerID);
      break;
    case TM_POST:
      result = queue->PostTransaction(aTrans);
      if (result >= 0) // post failed, aTrans cached in a tmQueue
        return;
      break;
    case TM_FLUSH:
      queue->FlushQueue(ownerID);
      break;
    case TM_DETACH:
      if (queue->DetachClient(ownerID) == TM_SUCCESS_DELETE_QUEUE) {
        // the last client has been removed, remove the queue
        RemoveQueue(aTrans->GetQueueID()); // this _could_ be out of bounds
      }
      break;
    default:
      PR_NOT_REACHED("bad action in the transaction");
    }
  }
  delete aTrans;
}
Пример #2
0
void TGUICopyParamType::Save(THierarchicalStorage * Storage)
{
  TCopyParamType::Save(Storage);

  Storage->WriteBool("Queue", GetQueue());
  Storage->WriteBool("QueueNoConfirmation", GetQueueNoConfirmation());
  Storage->WriteBool("QueueIndividually", GetQueueIndividually());
}
Пример #3
0
void TGUICopyParamType::Load(THierarchicalStorage * Storage)
{
  TCopyParamType::Load(Storage);

  SetQueue(Storage->ReadBool("Queue", GetQueue()));
  SetQueueNoConfirmation(Storage->ReadBool("QueueNoConfirmation", GetQueueNoConfirmation()));
  SetQueueIndividually(Storage->ReadBool("QueueIndividually", GetQueueIndividually()));
}
    // Execute CommandBuffer
    void DeviceVulkanw::CommitCommandBuffer( bool in_wait_till_completed )
    {
        const auto fence = GetFence( m_cpu_fence_id );

        m_is_command_buffer_recording = false;
        m_command_buffer->stop_recording();

        GetQueue()->submit_command_buffer( m_command_buffer.get(), in_wait_till_completed, fence );
    }
Пример #5
0
void* __stdcall XRespone(char type, void* pApi1, void* pApi2, double double1, double double2, void* ptr1, int size1, void* ptr2, int size2, void* ptr3, int size3)
{
	if (pApi1 == nullptr)
	{
		return nullptr;
	}

	CMsgQueue* pQueue = GetQueue(pApi1);
	pQueue->Input(type, pApi1, pApi2, double1, double2, ptr1, size1, ptr2, size2, ptr3, size3);

	return pApi1;
}
Пример #6
0
TakeoffQueueInSim * TakeoffQueuesManager::GetRunwayExitQueue( RunwayExitInSim * pRunwayExit )
{
	//ASSERT(pRunwayExit);
	if(!pRunwayExit)
		return NULL;

	for(int i = 0 ;i< GetQueueCount() ;i++)
	{
		TakeoffQueueInSim * pQueue = GetQueue(i);
		FlightGroundRouteDirectSegInSim * pDirSeg  = pRunwayExit->GetRouteSeg();
		FlightGroundRouteDirectSegInSim * pOtherSeg = pDirSeg->GetOppositeSegment();

		if( pQueue->GetRunway() == pRunwayExit->GetLogicRunway() && pQueue->IsHaveSegment(pOtherSeg) )
		{
			return pQueue;
		}
	}
	return NULL;
}
Пример #7
0
void* __stdcall XRequest(char type, void* pApi1, void* pApi2, double double1, double double2, void* ptr1, int size1, void* ptr2, int size2, void* ptr3, int size3)
{
	RequestType rt = (RequestType)type;
	if (rt == RequestType::Create)
	{
		return new CMsgQueue();
	}

	if (pApi1 == nullptr)
	{
		return nullptr;
	}

	CMsgQueue* pQueue = GetQueue(pApi1);

	switch (rt)
	{
	case RequestType::Release:
		delete pQueue;
		return 0;
	case RequestType::Register:
		pQueue->Register(ptr1);
		break;
	case RequestType::Clear:
		pQueue->Clear();
		break;
	case RequestType::Process:
		pQueue->Process();
		break;
	case RequestType::Connect:
		pQueue->StartThread();
		break;
	case RequestType::Disconnect:
		pQueue->StopThread();
		break;
	default:
		break;
	}

	return pApi1;
}
typename EventStreamHandler<ButtonsType>::GetButtonsStatus
EventStreamHandler<ButtonsType>::GetLocalButtons(const Port port, int frame,
                                                 ButtonsType* buttons) {
  ButtonsInputQueue* queue = GetQueue(port);
  if (queue == nullptr) {
    // Error already logged
    return GetButtonsStatus::NO_SUCH_PORT;
  }

  // If button data is already in the queue, return it immediately.
  typename ButtonsInputQueue::GetButtonsStatus status =
      queue->GetButtons(frame, 0 /* zero seconds */, buttons);

  if (status == ButtonsInputQueue::GetButtonsStatus::SUCCESS) {
    return GetButtonsStatus::SUCCESS;
  } else {
    LOG(ERROR) << "Failed to read buttons from local port " << Port_Name(port)
               << " and frame " << frame;
    return GetButtonsStatus::FAILURE;
  }
}
typename EventStreamHandler<ButtonsType>::GetButtonsStatus
EventStreamHandler<ButtonsType>::GetRemoteButtons(const Port port, int frame,
                                                  ButtonsType* buttons) {
  ButtonsInputQueue* queue = GetQueue(port);
  if (queue == nullptr) {
    // Error already logged
    return GetButtonsStatus::NO_SUCH_PORT;
  }

  // If button data is already in the queue, return it immediately.
  typename ButtonsInputQueue::GetButtonsStatus status =
      queue->GetButtons(frame, 0 /* zero seconds */, buttons);
  if (status == ButtonsInputQueue::GetButtonsStatus::SUCCESS) {
    return GetButtonsStatus::SUCCESS;
  } else if (status != ButtonsInputQueue::GetButtonsStatus::TIMEOUT) {
    LOG(ERROR) << "Failed to read buttons from remote port " << Port_Name(port)
               << " and frame " << frame;
    return GetButtonsStatus::FAILURE;
  }

  // Process the stream until we encounter the requested buttons.
  if (ReadUntilButtons(port, frame) != ReadUntilButtonsStatus::GOT_BUTTONS) {
    // TODO(alexgolec): Flesh these return statuses out a little instead of
    // returning failure on any non-button event.
    return GetButtonsStatus::FAILURE;
  }

  if (queue->GetButtons(frame, 5E6 /* five seconds */, buttons) !=
      ButtonsInputQueue::GetButtonsStatus::SUCCESS) {
    LOG(ERROR) << "Failed to get buttons for remote port " << Port_Name(port)
               << " and frame " << frame
               << " after reading the buttons event and placing them into the "
                  "queue. Probable logic error.";
    return GetButtonsStatus::FAILURE;
  }

  return GetButtonsStatus::SUCCESS;
}
Пример #10
0
int FalconATCMessage::Process(uchar autodisp)
{
	AircraftClass *aircraft = (AircraftClass*)vuDatabase->Find(dataBlock.from );
	ObjectiveClass *atc = (ObjectiveClass*)vuDatabase->Find(EntityId());
	runwayQueueStruct *info = NULL;
	FalconRadioChatterMessage *radioMessage = NULL;
	
	if (autodisp)
		return 0;

	float cosAngle=0.0F, dx=0.0F, dy=0.0F, finalHdg=0.0F;
	float finalX=0.0F, finalY=0.0F, baseX=0.0F, baseY=0.0F, x=0.0F ,y=0.0F,z=0.0F, dist=0.0F;
	int	taxiPoint=0, tod=0, time_in_minutes=0;
	int delay = 7 * CampaignSeconds;
	if (!PlayerOptions.PlayerRadioVoice)
	    delay = 500;

	if (aircraft && aircraft->IsAirplane())
	{      
		DigitalBrain *acBrain = aircraft->DBrain();
		ATCBrain*	atcBrain = NULL;

		if(atc)
		{
			atcBrain = atc->brain;
			dx = aircraft->XPos() - atc->XPos();
			dy = aircraft->YPos() - atc->YPos();
			dist = dx*dx + dy*dy;
		}

		switch (dataBlock.type)
		{
		case ContactApproach:
        case RequestClearance:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
			{
				if(aircraft->pctStrength < STRENGTH_PCT_FOR_EMERG_LDG)
					SendCallToATC(aircraft, EntityId(), rcLANDCLEAREMERGENCY, FalconLocalSession);
				else
					SendCallToATC(aircraft, EntityId(), rcLANDCLEARANCE, FalconLocalSession);
			}
			
			if(atcBrain && atc->IsLocal())
			{
				info = atcBrain->InList(aircraft->Id());
				if( info )
				{
					cosAngle = atcBrain->DetermineAngle(aircraft, acBrain->Runway(), lOnFinal);

					//if(info->status >= tReqTaxi)
					//if(info->status < tReqTaxi) // JB 010802 RTBing AI aircraft won't land. This compare was messed up.  Right? I hope so.
					if(info->status >= tReqTaxi) // JB It appears to work but this was called a bit much for my comfort level. We'll try another approach.
					{
						if(!aircraft->OnGround())
						{
							if(dist < (TOWER_RANGE + 100) * NM_TO_FT * NM_TO_FT)
							{
								if(!aircraft->IsPlayer() && aircraft->pctStrength < STRENGTH_PCT_FOR_EMERG_LDG)
									atcBrain->RequestEmerClearance(aircraft);
								else
									atcBrain->RequestClearance(aircraft);
							}
							else if(dist < APPROACH_RANGE * NM_TO_FT * NM_TO_FT && dist >= (TOWER_RANGE + 100) * NM_TO_FT * NM_TO_FT)
							{
								if(!aircraft->IsPlayer() && aircraft->GetCampaignObject()->GetComponentLead() == aircraft)
									HandleInboundFlight( atc, (Flight)aircraft->GetCampaignObject());
								else
									HandleInbound(atc, aircraft);			
							}
							else
							{
								//note this comm should be rcOUTSIDEAIRSPACE, but Joe misnamed it
								radioMessage = CreateCallFromATC(atc, aircraft, rcOUTSIDEAIRSPEED, FalconLocalGame);
								radioMessage->dataBlock.edata[4]	= (short)(rand()%2);
								radioMessage->dataBlock.time_to_play= delay;
								atcBrain->RemoveTraffic(aircraft->Id(), PtHeaderDataTable[info->rwindex].runwayNum);
							}
							info->lastContacted = SimLibElapsedTime;
						}
						break;
					}
					else if(info->rwindex)
					{
						switch(info->status)
						{
						case noATC:

						case lReqClearance:
						case lReqEmerClearance:

						case lIngressing:
						case lTakingPosition:
							ShiWarning("This should never happen!");
							radioMessage = CreateCallFromATC(atc, aircraft, rcCONTINUEINBOUND1, FalconLocalGame);
							//M.N. changed to 32767 -> flexibly use randomized value of max available eval indexes
							radioMessage->dataBlock.edata[4]	= 32767;
							radioMessage->dataBlock.edata[5]	= (short)atcBrain->GetRunwayName(atcBrain->GetOppositeRunway(info->rwindex));
							if(rand()%2)
								radioMessage->dataBlock.edata[6]	= 4;
							else
								radioMessage->dataBlock.edata[6]	= -1;
							break;

						case lAborted:
							atcBrain->FindAbortPt(aircraft, &x, &y, &z);
							radioMessage = CreateCallFromATC (atc, aircraft, rcATCGOAROUND, FalconLocalSession);
					
							atcBrain->CalculateStandRateTurnToPt(aircraft, x, y, &finalHdg);
							radioMessage->dataBlock.edata[3] = (short)FloatToInt32(finalHdg);
							//M.N. changed to 32767 -> flexibly use randomized value of max available eval indexes
							radioMessage->dataBlock.edata[4] = 32767;
							break;

						case lEmerHold:
						case lHolding:
							radioMessage = CreateCallFromATC (atc, aircraft, rcATCORBIT2, FalconLocalGame);
							radioMessage->dataBlock.edata[2] = -1; //altitude in thousands
							radioMessage->dataBlock.edata[3] = -1; //altitude in thousands
							break;

						case lFirstLeg:
						case lToBase:
						case lToFinal:
							radioMessage = CreateCallFromATC(atc, aircraft, rcATCLANDSEQUENCE, FalconLocalGame);
							radioMessage->dataBlock.edata[4] = (short)atcBrain->GetLandingNumber(info);
							//atcBrain->SendCmdMessage(aircraft, info);
							break;

						case lOnFinal:
						case lClearToLand:
							if(aircraft->DBrain()->IsSetATC(DigitalBrain::ClearToLand))
							{
								radioMessage = CreateCallFromATC (atc, aircraft, rcCLEAREDLAND, FalconLocalGame);
								radioMessage->dataBlock.edata[4] = (short)atcBrain->GetRunwayName(atcBrain->GetOppositeRunway(acBrain->Runway()));
							}
							else
							{
								radioMessage = CreateCallFromATC(atc, aircraft, rcATCLANDSEQUENCE, FalconLocalGame);
								radioMessage->dataBlock.edata[4] = (short)atcBrain->GetLandingNumber(info);
							}
							break;

						case lLanded:
							radioMessage = CreateCallFromATC (atc, aircraft, rcTAXICLEAR, FalconLocalGame);
							break;

						case lTaxiOff:
							//there isn't anything better to say, oh well :)
							radioMessage = CreateCallFromATC (atc, aircraft, rcTAXICLEAR, FalconLocalGame);
							break;

						case lEmergencyToBase:
						case lEmergencyToFinal:
						case lEmergencyOnFinal:
							atcBrain->RequestClearance(aircraft);
							return 1;
							break;

						case lCrashed:
							radioMessage = CreateCallFromATC (atc, aircraft, rcCLEAREDEMERGLAND, FalconLocalGame);
							radioMessage->dataBlock.edata[3] = -1;

							radioMessage->dataBlock.edata[4] = -1;
							//M.N. changed to 32767 -> flexibly use randomized value of max available eval indexes
							radioMessage->dataBlock.edata[5] = 32767;
							break;
						}
					}
					else
					{
						radioMessage = CreateCallFromATC(atc, aircraft, rcCONTINUEINBOUND2, FalconLocalGame);

						if(rand()%2)
						{
							radioMessage->dataBlock.edata[3]	= (short)(rand()%3);
						}
						else
						{
							time_in_minutes =  TheCampaign.GetMinutesSinceMidnight();
							if (time_in_minutes < 180)//3am
								tod = 1;
							else if(time_in_minutes < 720 )//noon
								tod = 0;
							else if(time_in_minutes < 1020 ) //5pm
								tod = 2;
							else
								tod = 1;

							radioMessage->dataBlock.edata[3]	= (short)(3 + tod + (rand()%3)*3);
						}

						if(rand()%2)
							radioMessage->dataBlock.edata[4]	= 4;
						else
							radioMessage->dataBlock.edata[4]	= -1;

						atcBrain->SendCmdMessage(aircraft, info);
					}
					if (radioMessage)
					{
						info->lastContacted = SimLibElapsedTime;
						if (PlayerOptions.PlayerRadioVoice)
						    radioMessage->dataBlock.time_to_play= 2 * CampaignSeconds;
						else 
						    radioMessage->dataBlock.time_to_play= delay;
						FalconSendMessage(radioMessage, TRUE);
					}
				}
				else
				{
					if(dist <= (TOWER_RANGE + 100) * NM_TO_FT * NM_TO_FT)
					{
						if(aircraft->GetCampaignObject()->GetComponentLead() == aircraft)
						{
							AircraftClass *element = NULL;
							Flight flight = (Flight)aircraft->GetCampaignObject();
							VuListIterator	flightIter(flight->GetComponents());

							element = (AircraftClass*) flightIter.GetFirst();
							while(element)
							{
								runwayQueueStruct *tempinfo = atcBrain->InList(element->Id());
								if(!tempinfo)
								{
									if( !element->IsPlayer() && element->pctStrength < STRENGTH_PCT_FOR_EMERG_LDG)
									{
										SendCallToATC(element, EntityId(), rcLANDCLEAREMERGENCY, FalconLocalGame);
										atcBrain->RequestEmerClearance(element);
									}
									else
										atcBrain->RequestClearance(element);
								}
								element = (AircraftClass*) flightIter.GetNext();
							}
						}
						else
						{
							if(!aircraft->IsPlayer() && aircraft->pctStrength < STRENGTH_PCT_FOR_EMERG_LDG)
							{
								SendCallToATC(aircraft, EntityId(), rcLANDCLEAREMERGENCY, FalconLocalGame);
								atcBrain->RequestEmerClearance(aircraft);
							}
							else
								atcBrain->RequestClearance(aircraft);
						}
					}
					else if(dist < APPROACH_RANGE * NM_TO_FT * NM_TO_FT && dist > (TOWER_RANGE + 100) * NM_TO_FT * NM_TO_FT)
					{
						if(aircraft->GetCampaignObject()->GetComponentLead() == aircraft)
							HandleInboundFlight( atc, (Flight)aircraft->GetCampaignObject());
						else
							HandleInbound(atc, aircraft);						
					}
					else
					{
						//note this comm should be rcOUTSIDEAIRSPACE, but Joe misnamed it
						radioMessage = CreateCallFromATC(atc, aircraft, rcOUTSIDEAIRSPEED, FalconLocalGame);
						radioMessage->dataBlock.edata[4]	= (short)(rand()%2);
						radioMessage->dataBlock.time_to_play= delay;
						FalconSendMessage(radioMessage, TRUE);
					}
				}
			}
			break;
			
        case RequestEmerClearance:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
				SendCallToATC(aircraft, EntityId(), rcLANDCLEAREMERGENCY, FalconLocalSession);
			if(atcBrain && atc->IsLocal())
				atcBrain->RequestEmerClearance(aircraft);			
			break;
		
        case RequestTakeoff:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
				SendCallToATC(aircraft, EntityId(), rcREADYFORDERARTURE, FalconLocalSession);
			if(atcBrain && atc->IsLocal())
				atcBrain->RequestTakeoff(aircraft);
			break;
			
        case RequestTaxi:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
				SendCallToATC(aircraft, EntityId(), rcREADYFORDERARTURE, FalconLocalSession);
			if(atcBrain && atc->IsLocal())
				atcBrain->RequestTaxi(aircraft);
			break;
// M.N. 2001-12-20
		case AbortApproach:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
				SendCallToATC(aircraft, EntityId(), rcABORTAPPROACH, FalconLocalSession);
				atcBrain->AbortApproach(aircraft);//Cobra
			if (atcBrain && atc->IsLocal())
				atcBrain->AbortApproach(aircraft);
			break;

// RAS - 22Jan04 - Set flag for traffic in sight call 
		case TrafficInSight:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
				SendCallToATC(aircraft, EntityId(), rcCOPY, FalconLocalSession);
			if (atcBrain && atc->IsLocal())
				atcBrain->trafficInSightFlag = TRUE;
			break;
// TJL 08/16/04 - Set flag for Hotpit Refueling //Cobra 10/31/04 TJL
 		case RequestHotpitRefuel:
			if(!aircraft->IsPlayer() || !aircraft->IsLocal())
 				SendCallToATC(aircraft, EntityId(), rcCOPY, FalconLocalSession);
				aircraft->requestHotpitRefuel = TRUE; //Cobra 11/13/04 TJL will this make online work?
 			if (atcBrain && atc->IsLocal())
 				aircraft->requestHotpitRefuel = TRUE;
 			break;


		case UpdateStatus:
			if(atcBrain)
			{
				if(atc->IsLocal())
				{
					info = atcBrain->InList(aircraft->Id());
					if(info)
					{
						switch(dataBlock.status)
						{
						case noATC:
							if(info->rwindex)
								atcBrain->RemoveTraffic(aircraft->Id(), PtHeaderDataTable[info->rwindex].runwayNum);
							else
								atcBrain->RemoveInbound(info);
							break;
						case lReqClearance:
						case lReqEmerClearance:
						case tReqTaxi:
						case tReqTakeoff:
						case lIngressing:
						case lTakingPosition:
							break;
						case tFlyOut:
							info->lastContacted = SimLibElapsedTime;
							info->status = noATC;
							break;
						case lCrashed:
							info->lastContacted = SimLibElapsedTime;
							info->status = lCrashed;
							{
								atcBrain->RemoveFromAllOtherATCs(aircraft);
								int Runway = atcBrain->IsOverRunway(aircraft);
								if(GetQueue(Runway) != GetQueue(info->rwindex))
								{
									atcBrain->RemoveTraffic(aircraft->Id(), GetQueue(info->rwindex));
									atcBrain->AddTraffic(aircraft->Id(), lCrashed, Runway, SimLibElapsedTime);
								}
								atcBrain->FindNextEmergency(GetQueue(Runway));
								atcBrain->SetEmergency(GetQueue(Runway));
							}
							break;
						default:
							info->lastContacted = SimLibElapsedTime;
							info->status = (AtcStatusEnum)dataBlock.status;
							break;
						}
					}
					else
					{
						//he thinks we already know about him, orig owner of atc must have dropped
						//offline, so we need to put him into the appropriate list
						switch(dataBlock.status)
						{
							case lIngressing:
								break;
							case lTakingPosition:
							case lAborted:
							case lEmerHold:
							case lHolding:
							case lFirstLeg:
							case lToBase:
							case lToFinal:
							case lOnFinal:
							case lLanded:
							case lTaxiOff:
							case lEmergencyToBase:
							case lEmergencyToFinal:
							case lEmergencyOnFinal:
							case lClearToLand:
								atcBrain->RequestClearance(aircraft);			
								break;
							case lCrashed:
								{
									atcBrain->RemoveFromAllOtherATCs(aircraft);
									int Runway = atcBrain->IsOverRunway(aircraft);
									atcBrain->AddTraffic(aircraft->Id(), lCrashed, Runway, SimLibElapsedTime);
									atcBrain->FindNextEmergency(GetQueue(Runway));
									atcBrain->SetEmergency(GetQueue(Runway));
								}
								break;
							case tEmerStop:
							case tTaxi:
							case tHoldShort:
							case tPrepToTakeRunway:
							case tTakeRunway:
							case tTakeoff:
								atcBrain->RequestTaxi(aircraft);
								break;
							case tFlyOut:
								break;
							default:
								break;
						}
					}
				}

				//update track point, taxi point, timer, status, etc...
				switch(dataBlock.status)
				{
				case noATC:
					break;
				case lClearToLand:
					break;
				case lIngressing:
				case lTakingPosition:
					atcBrain->FindFinalPt(aircraft, acBrain->Runway(), &x, &y);
					acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, lTakingPosition));
					break;
				case lEmerHold:
				case lHolding:
					acBrain->SetTrackPoint(aircraft->XPos(), aircraft->YPos(), atcBrain->GetAltitude(aircraft, lHolding));
					break;

				case lFirstLeg:				
					if(acBrain->ATCStatus() != lFirstLeg && acBrain->ATCStatus() <= lOnFinal)
					{
						atcBrain->FindFinalPt(aircraft, acBrain->Runway(), &finalX, &finalY);
						cosAngle = atcBrain->DetermineAngle(aircraft, acBrain->Runway(), lFirstLeg);
						if(cosAngle < 0.0F)
						{
							atcBrain->FindBasePt(aircraft, acBrain->Runway(), finalX, finalY, &baseX, &baseY);
							atcBrain->FindFirstLegPt(aircraft, acBrain->Runway(), acBrain->RwTime(), baseX, baseY, TRUE, &x, &y);
						}
						else
						{
							atcBrain->FindFirstLegPt(aircraft, acBrain->Runway(), acBrain->RwTime(), finalX, finalY, FALSE, &x, &y);
						}

						acBrain->SetATCStatus(lFirstLeg);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, lFirstLeg));
						acBrain->CalculateNextTurnDistance();
					}

					if( !aircraft->IsPlayer() )
					{
						atcBrain->MakeVectorCall(aircraft, FalconLocalSession);
					}
					break;

				case lToBase:
					if(acBrain->ATCStatus() != lToBase && acBrain->ATCStatus() <= lOnFinal)
					{
						atcBrain->FindFinalPt(aircraft, acBrain->Runway(), &finalX, &finalY);
						atcBrain->FindBasePt(aircraft, acBrain->Runway(), finalX, finalY, &baseX, &baseY);
						acBrain->SetATCStatus(lToBase);
						acBrain->SetTrackPoint(baseX, baseY, atcBrain->GetAltitude(aircraft, lToBase));
						acBrain->CalculateNextTurnDistance();
					}

					if( !aircraft->IsPlayer() )
					{
						atcBrain->MakeVectorCall(aircraft, FalconLocalSession);
					}
					break;

				case lToFinal:
					if(acBrain->ATCStatus() != lToFinal && acBrain->ATCStatus() <= lOnFinal)
					{
						atcBrain->FindFinalPt(aircraft, acBrain->Runway(), &finalX, &finalY);
						acBrain->SetATCStatus(lToFinal);
						acBrain->SetTrackPoint(finalX, finalY, atcBrain->GetAltitude(aircraft, lToFinal));
						acBrain->CalculateNextTurnDistance();
					}

					if( !aircraft->IsPlayer() )
					{
						atcBrain->MakeVectorCall(aircraft, FalconLocalSession);
					}
					break;

				case lOnFinal:
					TranslatePointData (atc, GetFirstPt(acBrain->Runway()), &x, &y);
					//if we sent the message we already know this				
					if(acBrain->ATCStatus() != lOnFinal && acBrain->ATCStatus() <= lOnFinal)
					{						
						acBrain->SetATCStatus(lOnFinal);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, lOnFinal));
						acBrain->CalculateNextTurnDistance();
					}

					if( !aircraft->IsPlayer() )
					{
						radioMessage = CreateCallFromATC (atc, aircraft, rcTURNTOFINAL, FalconLocalSession);
#if 0
						//MI Turn final for AI fix
						if(atcBrain->CalculateStandRateTurnToPt(aircraft, x, y, &finalHdg) > 0)
							radioMessage->dataBlock.edata[2] = 1;
						else
							radioMessage->dataBlock.edata[2] = 0;
#else
						if(atcBrain->CalculateStandRateTurnToPt(aircraft, x, y, &finalHdg) > 0)
							radioMessage->dataBlock.edata[2] = 0;
						else
							radioMessage->dataBlock.edata[2] = 1;
#endif	
						finalHdg = PtHeaderDataTable[acBrain->Runway()].data + 180.0F;
						if(finalHdg > 360)
							finalHdg -= 360;

						radioMessage->dataBlock.edata[3] = (short)FloatToInt32(finalHdg);
						//M.N. changed to 32767 -> flexibly use randomized value of max available eval indexes
						radioMessage->dataBlock.edata[4] = 32767; //vector type
						FalconSendMessage(radioMessage, TRUE);
					}
					break;


				case lLanded:
					//if we sent the message we already know this	
					if(acBrain->ATCStatus() != lLanded)
					{
						acBrain->SetATCStatus(lLanded);
						taxiPoint = GetFirstPt(acBrain->Runway());
						TranslatePointData (atc,GetNextPt(taxiPoint) , &x, &y);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, lLanded));
					}
					break;

				case lTaxiOff:
					break;

				case lAborted:					
					if(acBrain->ATCStatus() != lAborted)
					{
						atcBrain->FindAbortPt(aircraft, &x, &y, &z);
						acBrain->SetATCStatus(lAborted);					
						acBrain->SetTrackPoint(x, y, z);
					}

					if(atc->IsLocal())
					{
						atcBrain->RemoveTraffic(aircraft->Id(), PtHeaderDataTable[acBrain->Runway()].runwayNum);
					}
					break;

				case lEmergencyToBase:
					if(acBrain->ATCStatus() != lEmergencyToBase)
					{
						atcBrain->FindFinalPt(aircraft, acBrain->Runway(), &finalX, &finalY);
						atcBrain->FindBasePt(aircraft, acBrain->Runway(), finalX, finalY, &baseX, &baseY);
						acBrain->SetATCStatus(lEmergencyToBase);
						acBrain->SetTrackPoint(baseX, baseY, atcBrain->GetAltitude(aircraft, lEmergencyToBase));
					}
					break;

				case lEmergencyToFinal:
					if(acBrain->ATCStatus() != lEmergencyToFinal)
					{
						atcBrain->FindFinalPt(aircraft, acBrain->Runway(), &finalX, &finalY);
						acBrain->SetATCStatus(lEmergencyToFinal);
						acBrain->SetTrackPoint(finalX, finalY, atcBrain->GetAltitude(aircraft, lEmergencyToFinal));
					}
					break;

				case lEmergencyOnFinal:
					if(acBrain->ATCStatus() != lEmergencyOnFinal)
					{
						TranslatePointData (atc, GetFirstPt(acBrain->Runway()), &x, &y);
						acBrain->SetATCStatus(lEmergencyOnFinal);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, lEmergencyOnFinal));
					}
					break;

				case lCrashed:
					acBrain->SetATCStatus(lCrashed);
					break;

				case tEmerStop:
					acBrain->SetATCStatus(tEmerStop);
					break;

				case tTaxi:
					if(acBrain->ATCStatus() != tTaxi)
					{
						acBrain->SetATCStatus(tTaxi);
						TranslatePointData (atc,acBrain->GetTaxiPoint() , &x, &y);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, tTaxi));
					}
					break;

				case tHoldShort:
					acBrain->ClearATCFlag(DigitalBrain::PermitRunway);
					acBrain->ClearATCFlag(DigitalBrain::PermitTakeoff);

					if(acBrain->ATCStatus() != tHoldShort)
					{
						acBrain->SetATCStatus(tHoldShort);
						taxiPoint = GetFirstPt(acBrain->Runway());
						taxiPoint = GetNextPt(taxiPoint);
						TranslatePointData (atc,taxiPoint , &x, &y);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, tHoldShort));
					}
					break;

				case tPrepToTakeRunway:
					acBrain->SetATCFlag(DigitalBrain::PermitTakeRunway);
					if(acBrain->ATCStatus() != tTaxi)
					{
						acBrain->SetATCStatus(tTaxi);
						if(PtDataTable[acBrain->GetTaxiPoint()].type == TakeoffPt)
							atcBrain->FindTakeoffPt((Flight)aircraft->GetCampaignObject(), aircraft->vehicleInUnit, acBrain->Runway(), &x, &y);
						else
							TranslatePointData (atc,acBrain->GetTaxiPoint() , &x, &y);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, tTaxi));
					}
					break;

				case tTakeRunway:
					if(acBrain->ATCStatus() != tTakeRunway)
					{
						acBrain->SetATCFlag(DigitalBrain::PermitTakeRunway);
						acBrain->SetATCStatus(tTakeRunway);
						atcBrain->FindTakeoffPt((Flight)aircraft->GetCampaignObject(), aircraft->vehicleInUnit, acBrain->Runway(), &x, &y);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, tTakeRunway));
					}
					break;

				case tTakeoff:
					if(acBrain->ATCStatus() != tTakeoff)
					{
						acBrain->SetATCFlag(DigitalBrain::PermitRunway);
						acBrain->SetATCFlag(DigitalBrain::PermitTakeoff);
						acBrain->SetATCStatus(tTakeRunway);
						atcBrain->FindRunwayPt((Flight)aircraft->GetCampaignObject(), aircraft->vehicleInUnit, acBrain->Runway(), &x, &y);
						acBrain->SetTrackPoint(x, y, atcBrain->GetAltitude(aircraft, tTakeRunway));
					}
					break;

				case tTaxiBack:
					if(acBrain->ATCStatus() != tTaxiBack)
					{
						acBrain->SetATCStatus(tTaxiBack);
					}
					break;

				case tFlyOut:
					if(acBrain->ATCStatus() != tFlyOut)
					{
						acBrain->ResetATC();
					}
				default:
					break;
				}
			}
			break;
		}
	}
	return 1;
}
Пример #11
0
/* Route a trace on the BOARD.
 * Parameters:
 * 1 side / 2 sides (0 / 1)
 * Coord source (row, col)
 * Coord destination (row, col)
 * Net_code
 * Pointer to the ratsnest reference
 *
 * Returns:
 * SUCCESS if routed
 * TRIVIAL_SUCCESS if pads are connected by overlay (no track needed)
 * If failure NOSUCCESS
 * Escape STOP_FROM_ESC if demand
 * ERR_MEMORY if memory allocation failed.
 */
static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe,
                                wxDC*           DC,
                                int             two_sides,
                                int             row_source,
                                int             col_source,
                                int             row_target,
                                int             col_target,
                                RATSNEST_ITEM*  pt_rat )
{
    int          r, c, side, d, apx_dist, nr, nc;
    int          result, skip;
    int          i;
    long         curcell, newcell, buddy, lastopen, lastclos, lastmove;
    int          newdist, olddir, _self;
    int          current_net_code;
    int          marge;
    LSET         padLayerMaskStart;    // Mask layers belonging to the starting pad.
    LSET         padLayerMaskEnd;      // Mask layers belonging to the ending pad.

    LSET         topLayerMask( g_Route_Layer_TOP );

    LSET         bottomLayerMask( g_Route_Layer_BOTTOM );

    LSET         routeLayerMask;       // Mask two layers for routing.

    LSET         tab_mask[2];           // Enables the calculation of the mask layer being
                                        // tested. (side = TOP or BOTTOM)
    int          start_mask_layer = 0;
    wxString     msg;

    // @todo this could be a bottle neck
    LSET all_cu = LSET::AllCuMask( pcbframe->GetBoard()->GetCopperLayerCount() );

    wxBusyCursor dummy_cursor;      // Set an hourglass cursor while routing a
                                    // track

    result = NOSUCCESS;

    marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );

    // clear direction flags
    i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL);

    if( two_sides )
        memset( RoutingMatrix.m_DirSide[TOP], FROM_NOWHERE, i );
    memset( RoutingMatrix.m_DirSide[BOTTOM], FROM_NOWHERE, i );

    lastopen = lastclos = lastmove = 0;

    // Set tab_masque[side] for final test of routing.
    if( two_sides )
        tab_mask[TOP] = topLayerMask;
    tab_mask[BOTTOM] = bottomLayerMask;

    // Set active layers mask.
    routeLayerMask = topLayerMask | bottomLayerMask;

    pt_cur_ch = pt_rat;

    current_net_code  = pt_rat->GetNet();
    padLayerMaskStart = pt_cur_ch->m_PadStart->GetLayerSet();

    padLayerMaskEnd = pt_cur_ch->m_PadEnd->GetLayerSet();


    /* First Test if routing possible ie if the pads are accessible
     * on the routing layers.
     */
    if( ( routeLayerMask & padLayerMaskStart ) == 0 )
        goto end_of_route;

    if( ( routeLayerMask & padLayerMaskEnd ) == 0 )
        goto end_of_route;

    /* Then test if routing possible ie if the pads are accessible
     * On the routing grid (1 grid point must be in the pad)
     */
    {
        int cX = ( RoutingMatrix.m_GridRouting * col_source )
                 + pcbframe->GetBoard()->GetBoundingBox().GetX();
        int cY = ( RoutingMatrix.m_GridRouting * row_source )
                 + pcbframe->GetBoard()->GetBoundingBox().GetY();
        int dx = pt_cur_ch->m_PadStart->GetSize().x / 2;
        int dy = pt_cur_ch->m_PadStart->GetSize().y / 2;
        int px = pt_cur_ch->m_PadStart->GetPosition().x;
        int py = pt_cur_ch->m_PadStart->GetPosition().y;

        if( ( ( int( pt_cur_ch->m_PadStart->GetOrientation() ) / 900 ) & 1 ) != 0 )
            std::swap( dx, dy );

        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
            goto end_of_route;

        cX = ( RoutingMatrix.m_GridRouting * col_target )
             + pcbframe->GetBoard()->GetBoundingBox().GetX();
        cY = ( RoutingMatrix.m_GridRouting * row_target )
             + pcbframe->GetBoard()->GetBoundingBox().GetY();
        dx = pt_cur_ch->m_PadEnd->GetSize().x / 2;
        dy = pt_cur_ch->m_PadEnd->GetSize().y / 2;
        px = pt_cur_ch->m_PadEnd->GetPosition().x;
        py = pt_cur_ch->m_PadEnd->GetPosition().y;

        if( ( ( int( pt_cur_ch->m_PadEnd->GetOrientation() ) / 900) & 1 ) != 0 )
            std::swap( dx, dy );

        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
            goto end_of_route;
    }

    // Test the trivial case: direct connection overlay pads.
    if( row_source == row_target  && col_source == col_target &&
            ( padLayerMaskEnd & padLayerMaskStart & all_cu ).any() )
    {
        result = TRIVIAL_SUCCESS;
        goto end_of_route;
    }

    // Placing the bit to remove obstacles on 2 pads to a link.
    pcbframe->SetStatusText( wxT( "Gen Cells" ) );

    PlacePad( pt_cur_ch->m_PadStart, CURRENT_PAD, marge, WRITE_OR_CELL );
    PlacePad( pt_cur_ch->m_PadEnd, CURRENT_PAD, marge, WRITE_OR_CELL );

    // Regenerates the remaining barriers (which may encroach on the
    // placement bits precedent)
    i = pcbframe->GetBoard()->GetPadCount();

    for( unsigned ii = 0; ii < pcbframe->GetBoard()->GetPadCount(); ii++ )
    {
        D_PAD* ptr = pcbframe->GetBoard()->GetPad( ii );

        if( ( pt_cur_ch->m_PadStart != ptr ) && ( pt_cur_ch->m_PadEnd != ptr ) )
        {
            PlacePad( ptr, ~CURRENT_PAD, marge, WRITE_AND_CELL );
        }
    }

    InitQueue(); // initialize the search queue
    apx_dist = RoutingMatrix.GetApxDist( row_source, col_source, row_target, col_target );

    // Initialize first search.
    if( two_sides )   // Preferred orientation.
    {
        if( abs( row_target - row_source ) > abs( col_target - col_source ) )
        {
            if( ( padLayerMaskStart & topLayerMask ).any() )
            {
                start_mask_layer = 2;

                if( SetQueue( row_source, col_source, TOP, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }

            if( ( padLayerMaskStart & bottomLayerMask ).any() )
            {
                start_mask_layer |= 1;

                if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
        }
        else
        {
            if( ( padLayerMaskStart & bottomLayerMask ).any() )
            {
                start_mask_layer = 1;

                if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }

            if( ( padLayerMaskStart & topLayerMask ).any() )
            {
                start_mask_layer |= 2;

                if( SetQueue( row_source, col_source, TOP, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
        }
    }
    else if( ( padLayerMaskStart & bottomLayerMask ).any() )
    {
        start_mask_layer = 1;

        if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist, row_target, col_target ) == 0 )
        {
            return ERR_MEMORY;
        }
    }

    // search until success or we exhaust all possibilities
    GetQueue( &r, &c, &side, &d, &apx_dist );

    for( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
    {
        curcell = RoutingMatrix.GetCell( r, c, side );

        if( curcell & CURRENT_PAD )
            curcell &= ~HOLE;

        if( (r == row_target) && (c == col_target)  // success if layer OK
           && (tab_mask[side] & padLayerMaskEnd).any() )
        {
            // Remove link.
            GRSetDrawMode( DC, GR_XOR );
            GRLine( pcbframe->GetCanvas()->GetClipBox(),
                    DC,
                    segm_oX,
                    segm_oY,
                    segm_fX,
                    segm_fY,
                    0,
                    WHITE );

            // Generate trace.
            if( Retrace( pcbframe, DC, row_source, col_source,
                         row_target, col_target, side, current_net_code ) )
            {
                result = SUCCESS;   // Success : Route OK
            }

            break;                  // Routing complete.
        }

        if( pcbframe->GetCanvas()->GetAbortRequest() )
        {
            result = STOP_FROM_ESC;
            break;
        }

        // report every COUNT new nodes or so
        #define COUNT 20000

        if( ( OpenNodes - lastopen > COUNT )
           || ( ClosNodes - lastclos > COUNT )
           || ( MoveNodes - lastmove > COUNT ) )
        {
            lastopen = OpenNodes;
            lastclos = ClosNodes;
            lastmove = MoveNodes;
            msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d" ),
                        OpenNodes, ClosNodes, MoveNodes );
            pcbframe->SetStatusText( msg );
        }

        _self = 0;

        if( curcell & HOLE )
        {
            _self = 5;

            // set 'present' bits
            for( i = 0; i < 8; i++ )
            {
                selfok2[i].present = 0;

                if( curcell & selfok2[i].trace )
                    selfok2[i].present = 1;
            }
        }

        for( i = 0; i < 8; i++ ) // consider neighbors
        {
            nr = r + delta[i][0];
            nc = c + delta[i][1];

            // off the edge?
            if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
                nc < 0 || nc >= RoutingMatrix.m_Ncols )
                continue;  // off the edge

            if( _self == 5 && selfok2[i].present )
                continue;

            newcell = RoutingMatrix.GetCell( nr, nc, side );

            if( newcell & CURRENT_PAD )
                newcell &= ~HOLE;

            // check for non-target hole
            if( newcell & HOLE )
            {
                if( nr != row_target || nc != col_target )
                    continue;
            }
            // check for traces
            else if( newcell & HOLE & ~(newmask[i]) )
            {
                continue;
            }

            // check blocking on corner neighbors
            if( delta[i][0] && delta[i][1] )
            {
                // check first buddy
                buddy = RoutingMatrix.GetCell( r + blocking[i].r1, c + blocking[i].c1, side );

                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;

                if( buddy & HOLE )
                    continue;

//              if (buddy & (blocking[i].b1)) continue;
                // check second buddy
                buddy = RoutingMatrix.GetCell( r + blocking[i].r2, c + blocking[i].c2, side );

                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;

                if( buddy & HOLE )
                    continue;

//              if (buddy & (blocking[i].b2)) continue;
            }

            olddir  = RoutingMatrix.GetDir( r, c, side );
            newdist = d + RoutingMatrix.CalcDist( ndir[i], olddir,
                                    ( olddir == FROM_OTHERSIDE ) ?
                                    RoutingMatrix.GetDir( r, c, 1 - side ) : 0, side );

            // if (a) not visited yet, or (b) we have
            // found a better path, add it to queue
            if( !RoutingMatrix.GetDir( nr, nc, side ) )
            {
                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
                RoutingMatrix.SetDist( nr, nc, side, newdist );

                if( SetQueue( nr, nc, side, newdist,
                              RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < RoutingMatrix.GetDist( nr, nc, side ) )
            {
                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
                RoutingMatrix.SetDist( nr, nc, side, newdist );
                ReSetQueue( nr, nc, side, newdist,
                            RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                            row_target, col_target );
            }
        }

        //* Test the other layer. *
        if( two_sides )
        {
            olddir = RoutingMatrix.GetDir( r, c, side );

            if( olddir == FROM_OTHERSIDE )
                continue;   // useless move, so don't bother

            if( curcell )   // can't drill via if anything here
                continue;

            // check for holes or traces on other side
            if( ( newcell = RoutingMatrix.GetCell( r, c, 1 - side ) ) != 0 )
                continue;

            // check for nearby holes or traces on both sides
            for( skip = 0, i = 0; i < 8; i++ )
            {
                nr = r + delta[i][0]; nc = c + delta[i][1];

                if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
                    nc < 0 || nc >= RoutingMatrix.m_Ncols )
                    continue;  // off the edge !!

                if( RoutingMatrix.GetCell( nr, nc, side ) /* & blocking2[i] */ )
                {
                    skip = 1; // can't drill via here
                    break;
                }

                if( RoutingMatrix.GetCell( nr, nc, 1 - side ) /* & blocking2[i] */ )
                {
                    skip = 1; // can't drill via here
                    break;
                }
            }

            if( skip )      // neighboring hole or trace?
                continue;   // yes, can't drill via here

            newdist = d + RoutingMatrix.CalcDist( FROM_OTHERSIDE, olddir, 0, side );

            /*  if (a) not visited yet,
             *  or (b) we have found a better path,
             *  add it to queue */
            if( !RoutingMatrix.GetDir( r, c, 1 - side ) )
            {
                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                RoutingMatrix.SetDist( r, c, 1 - side, newdist );

                if( SetQueue( r, c, 1 - side, newdist, apx_dist, row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < RoutingMatrix.GetDist( r, c, 1 - side ) )
            {
                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                RoutingMatrix.SetDist( r, c, 1 - side, newdist );
                ReSetQueue( r, c,
                            1 - side,
                            newdist,
                            apx_dist,
                            row_target,
                            col_target );
            }
        }     // Finished attempt to route on other layer.
    }

end_of_route:
    PlacePad( pt_cur_ch->m_PadStart, ~CURRENT_PAD, marge, WRITE_AND_CELL );
    PlacePad( pt_cur_ch->m_PadEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL );

    msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d"),
                OpenNodes, ClosNodes, MoveNodes );
    pcbframe->SetStatusText( msg );

    return result;
}
Пример #12
0
/* Route une piste du BOARD.
	Parametres:
		1 face / 2 faces ( 0 / 1)
		coord source (row,col)
		coord destination (row,col)
		net_code
		pointeur sur le chevelu de reference

	Retourne :
		SUCCESS si route trouvee
		TRIVIAL_SUCCESS si pads connectes par superposition ( pas de piste a tirer)
		NOSUCCESS si echec
		STOP_FROM_ESC si Escape demande
		ERR_MEMORY defaut alloc RAM
*/
static int Route_1_Trace(WinEDA_PcbFrame * pcbframe, wxDC * DC,
				int two_sides, int row_source,int col_source,
				int row_target,int col_target, CHEVELU * pt_chevelu )
{
int  r, c, side , d, apx_dist, nr, nc;
int result, skip;
int i;
LISTE_PAD * ptr;
long curcell, newcell, buddy, lastopen, lastclos, lastmove;
int newdist, olddir, _self;
int current_net_code;
int marge, via_marge;
int pad_masque_layer_s; /* Masque des couches appartenant au pad de depart */
int pad_masque_layer_e; /* Masque des couches appartenant au pad d'arrivee */
int masque_layer_TOP = g_TabOneLayerMask[Route_Layer_TOP];
int masque_layer_BOTTOM = g_TabOneLayerMask[Route_Layer_BOTTOM];
int masque_layers;		/* Masque des 2 couches de routage */
int tab_mask[2];		/* permet le calcul du Masque de la couche en cours
							de tst (side = TOP ou BOTTOM)*/
int start_mask_layer = 0;
wxString msg;
	
	result = NOSUCCESS;

	marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentTrackWidth / 2);
	via_marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentViaSize / 2);

	/* clear direction flags */
	i = Nrows * Ncols * sizeof(char);
	memset(Board.m_DirSide[TOP], FROM_NOWHERE, i );
	memset(Board.m_DirSide[BOTTOM], FROM_NOWHERE, i );

	lastopen = lastclos = lastmove = 0;

	/* Init tab_masque[side] pour tests de fin de routage */
	tab_mask[TOP] = masque_layer_TOP;
	tab_mask[BOTTOM] = masque_layer_BOTTOM;
	/* Init masque des couches actives */
	masque_layers = masque_layer_TOP | masque_layer_BOTTOM;

	pt_cur_ch = pt_chevelu;
	current_net_code = pt_chevelu->m_NetCode;
	pad_masque_layer_s = pt_cur_ch->pad_start->m_Masque_Layer;
	pad_masque_layer_e = pt_cur_ch->pad_end->m_Masque_Layer;

	/* Test 1 Si routage possible c.a.d si les pads sont accessibles
			sur les couches de routage */

	if( (masque_layers & pad_masque_layer_s) == 0 ) goto end_of_route;
	if( (masque_layers & pad_masque_layer_e) == 0 ) goto end_of_route;

	/* Test 2 Si routage possible c.a.d si les pads sont accessibles
		sur la grille de routage ( 1 point de grille doit etre dans le pad)*/
	{
	int cX = (pas_route * col_source) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.x;
	int cY = (pas_route * row_source) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.y;
	int dx = pt_cur_ch->pad_start->m_Size.x / 2;
	int dy = pt_cur_ch->pad_start->m_Size.y / 2;
	int px = pt_cur_ch->pad_start->m_Pos.x;
	int py = pt_cur_ch->pad_start->m_Pos.y;

	if ( ((pt_cur_ch->pad_start->m_Orient/900)&1) != 0 ) EXCHG(dx,dy) ;
	if ( (abs(cX - px) > dx ) || (abs(cY - py) > dy) ) goto end_of_route;

	cX = (pas_route * col_target) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.x;
	cY = (pas_route * row_target) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.y;
	dx = pt_cur_ch->pad_end->m_Size.x / 2;
	dy = pt_cur_ch->pad_end->m_Size.y / 2;
	px = pt_cur_ch->pad_end->m_Pos.x;
	py = pt_cur_ch->pad_end->m_Pos.y;
	if ( ((pt_cur_ch->pad_end->m_Orient/900)&1) != 0 ) EXCHG(dx,dy) ;

	if ( (abs(cX - px) > dx ) || (abs(cY - py) > dy) ) goto end_of_route;
	}

	/* Test du cas trivial: connection directe par superposition des pads */
	if( (row_source == row_target) && (col_source == col_target)
		&& ( pad_masque_layer_e & pad_masque_layer_s & g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount-1]) )
	{
		result = TRIVIAL_SUCCESS;
		goto end_of_route;
	}



	/* Placement du bit de suppression d'obstacle relative aux 2 pads a relier */
	pcbframe->Affiche_Message( wxT("Gen Cells") );

	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_start,CURRENT_PAD ,marge,WRITE_OR_CELL);
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_end, CURRENT_PAD ,marge,WRITE_OR_CELL);

	/* Regenere les barrieres restantes (qui peuvent empieter sur le placement
		des bits precedents) */
	ptr = (LISTE_PAD*) pcbframe->m_Pcb->m_Pads; i = pcbframe->m_Pcb->m_NbPads;
	for( ; i > 0 ; i-- , ptr++)
		{
		if((pt_cur_ch->pad_start != *ptr) && (pt_cur_ch->pad_end != *ptr) )
			{
			Place_1_Pad_Board(pcbframe->m_Pcb, *ptr, ~CURRENT_PAD,marge,WRITE_AND_CELL);
			}
		}

	InitQueue(); /* initialize the search queue */
	apx_dist = GetApxDist( row_source, col_source, row_target, col_target );

	/* Init 1ere recherche */
	if(two_sides)	/* orientation preferentielle */
		{
		if( abs(row_target-row_source) > abs(col_target-col_source) )
			{
			if( pad_masque_layer_s & masque_layer_TOP )
				{
				start_mask_layer = 2;
				if(SetQueue( row_source, col_source, TOP, 0, apx_dist,
							row_target, col_target ) == 0)
 					{
					return(ERR_MEMORY);
					}
				}
			if( pad_masque_layer_s & masque_layer_BOTTOM )
				{
				start_mask_layer |= 1;

				if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			}
		else
			{
			if( pad_masque_layer_s & masque_layer_BOTTOM )
				{
				start_mask_layer = 1;
				if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			if( pad_masque_layer_s & masque_layer_TOP )
				{
				start_mask_layer |= 2;

				if (SetQueue( row_source, col_source, TOP, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			}
		}

	else
		if( pad_masque_layer_s & masque_layer_BOTTOM )
			{
			start_mask_layer = 1;

			if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
				{
				return(ERR_MEMORY);
				}
			}

	/* search until success or we exhaust all possibilities */
	GetQueue( &r, &c, &side, &d, &apx_dist );
	for ( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
		{
		curcell = GetCell( r, c, side );
		if(curcell & CURRENT_PAD) curcell &= ~HOLE ;
		if( (r == row_target) && (c == col_target)  /* success si layer OK */
			&& ( tab_mask[side] & pad_masque_layer_e) )
			{
			/* Efface Liaison */
			GRSetDrawMode(DC, GR_XOR);
			GRLine(&pcbframe->DrawPanel->m_ClipBox, DC, segm_oX, segm_oY, segm_fX, segm_fY, WHITE);

			/* Generation de la trace */
			if( Retrace(pcbframe, DC, row_source, col_source,
						 row_target, col_target, side, current_net_code) )
				{
				result = SUCCESS;	/* Success : Route OK */
				}
			break;	/* Fin du routage */
			}
		/* report every 300 new nodes or so */
		if( (OpenNodes-lastopen > 300) || (ClosNodes-lastclos > 300) || (MoveNodes - lastmove > 300))
			{
			lastopen = (OpenNodes/300)*300; lastclos = (ClosNodes/300)*300;
			lastmove = (MoveNodes/300)*300;

			if( pcbframe->DrawPanel->m_AbortRequest )
				{
				result = STOP_FROM_ESC; break;
				}
			AFFICHE_ACTIVITE_ROUTE;
			}

		_self = 0;
		if (curcell & HOLE)
			{
			_self = 5;
			/* set 'present' bits */
			for (i = 0; i < 8; i++)
				{
				selfok2[i].present = 0;
				if( (curcell & selfok2[i].trace) ) selfok2[i].present = 1;
				}
			}

		for (i = 0; i < 8; i++) /* consider neighbors */
			{
			nr = r+delta[i][0]; nc = c+delta[i][1];

			/* off the edge? */
			if( nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols)
				continue; /* off the edge */

			if (_self == 5 && selfok2[i].present) continue;
			newcell = GetCell( nr, nc, side );
			if(newcell & CURRENT_PAD) newcell &= ~HOLE;

			/* check for non-target hole */
			if (newcell & HOLE)
				{
				if (nr != row_target || nc != col_target) continue;
				}

			/* check for traces */
			else if (newcell & HOLE & ~(newmask[i])) continue;

			/* check blocking on corner neighbors */
			if (delta[i][0] && delta[i][1])
				{
				/* check first buddy */
				buddy = GetCell( r+blocking[i].r1, c+blocking[i].c1, side );
				if(buddy & CURRENT_PAD) buddy &= ~HOLE;
				if (buddy & HOLE) continue;
//				if (buddy & (blocking[i].b1)) continue;
				/* check second buddy */
				buddy = GetCell( r+blocking[i].r2, c+blocking[i].c2, side );
				if(buddy & CURRENT_PAD) buddy &= ~HOLE;
				if (buddy & HOLE) continue;
//				if (buddy & (blocking[i].b2)) continue;
				}

			olddir = GetDir( r, c, side );
			newdist = d + CalcDist( ndir[i], olddir,
				(olddir == FROM_OTHERSIDE) ? GetDir( r, c, 1-side ) : 0 , side);

			/* if (a) not visited yet, or (b) we have */
			/* found a better path, add it to queue */
			if (!GetDir( nr, nc, side ))
				{
				SetDir( nr, nc, side, ndir[i] );
				SetDist( nr, nc, side, newdist );
				if( SetQueue( nr, nc, side, newdist,
					GetApxDist( nr, nc, row_target, col_target ),
						row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}

			else if (newdist < GetDist( nr, nc, side ))
				{
				SetDir( nr, nc, side, ndir[i] );
				SetDist( nr, nc, side, newdist );
				ReSetQueue( nr, nc, side, newdist,
					GetApxDist( nr, nc, row_target, col_target ),
					row_target, col_target );
				}
			}

		/** etude de l'autre couche **/
		if( (two_sides) && ! g_No_Via_Route )
			{
			olddir = GetDir( r, c, side );
			if (olddir == FROM_OTHERSIDE)
				continue; /* useless move, so don't bother */
			if (curcell) /* can't drill via if anything here */
				continue;
			/* check for holes or traces on other side */
			if( (newcell = GetCell( r, c, 1-side )) != 0 )
				continue;
			/* check for nearby holes or traces on both sides */
			for (skip = 0, i = 0; i < 8; i++)
				{
				nr = r + delta[i][0]; nc = c + delta[i][1];

				if (nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols)
					continue;  /* off the edge !! */

				if (GetCell( nr, nc, side )/* & blocking2[i]*/)
					{
					skip = 1; /* can't drill via here */
					break;
					}

				if (GetCell( nr, nc, 1-side )/* & blocking2[i]*/)
					{
					skip = 1; /* can't drill via here */
					break;
					}
				}

			if (skip) /* neighboring hole or trace? */
				continue; /* yes, can't drill via here */

			newdist = d + CalcDist( FROM_OTHERSIDE, olddir, 0 , side);

			/*  if (a) not visited yet,
				or (b) we have found a better path,
				add it to queue */
			if (!GetDir( r, c, 1-side ))
				{
				SetDir( r, c, 1-side, FROM_OTHERSIDE );
				SetDist( r, c, 1-side, newdist );
				if( SetQueue( r, c, 1-side, newdist, apx_dist, row_target,
								 col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			else if (newdist < GetDist( r, c, 1-side ))
				{
				SetDir( r, c, 1-side, FROM_OTHERSIDE );
				SetDist( r, c, 1-side, newdist );
				ReSetQueue( r, c, 1-side, newdist, apx_dist, row_target, col_target );
				}
			} /* Fin de l'exploration de l'autre couche */
		}

end_of_route:
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_start,~CURRENT_PAD ,marge,WRITE_AND_CELL);
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_end, ~CURRENT_PAD ,marge,WRITE_AND_CELL);

	AFFICHE_ACTIVITE_ROUTE;
	return(result);
}
typename EventStreamHandler<ButtonsType>::ReadUntilButtonsStatus
EventStreamHandler<ButtonsType>::ReadUntilButtons(const Port port, int frame) {
  bool found_buttons = false;

  while (!found_buttons) {
    IncomingEventPB event;

    VLOG(3) << "Looping on buttons for port " << Port_Name(port)
            << " and frame " << frame;

    timings_->add_event()->set_key_state_read_start(client_utils::now_nanos());
    bool success = stream_->Read(&event);
    timings_->add_event()->set_key_state_read_finish(client_utils::now_nanos());
    if (!success) {
      LOG(ERROR) << "Failed to read event.";
      return ReadUntilButtonsStatus::RPC_READ_FAILURE;
    }

    VLOG(3) << "Read incoming event from stream:\n" << event.DebugString();

    if (event.has_stop_console()) {
      VLOG(3) << "Received console stopped message";
      return ReadUntilButtonsStatus::CONSOLE_TERMINATED;
    }

    // Return an error on all non-button statuses.
    // TODO(alexgolec): handle this more gracefully
    if (event.has_start_game() || !event.invalid_data().empty()) {
      LOG(ERROR)
          << "Received non-button message when expecting button message: "
          << event.DebugString();
      return ReadUntilButtonsStatus::NON_BUTTON_MESSAGE;
    }

    for (const KeyStatePB& keys : event.key_press()) {
      ButtonsInputQueue* queue = GetQueue(keys.port());
      if (queue == nullptr) {
        LOG(ERROR) << "Received buttons state data for unconnected port : "
                   << Port_Name(keys.port());
        return ReadUntilButtonsStatus::INVALID_BUTTONS_MESSAGE;
      }

      ButtonsType buttons;
      if (!coder_.DecodeButtons(keys, &buttons)) {
        LOG(ERROR) << "Failed to decode buttons from message: "
                   << keys.DebugString();
        return ReadUntilButtonsStatus::INVALID_BUTTONS_MESSAGE;
      }

      if (!queue->PutButtons(keys.frame_number(), buttons)) {
        LOG(ERROR) << "Failed to insert buttons into queue for port "
                   << Port_Name(keys.port()) << " and frame "
                   << keys.frame_number();
        return ReadUntilButtonsStatus::REJECTED_BY_QUEUE;
      }

      if (!found_buttons && keys.port() == port &&
          keys.frame_number() == frame) {
        VLOG(3) << "Found buttons for frame " << port << " and frame " << frame;
        found_buttons = true;
      }
    }
  }

  // We only exit the loop if we've found the requested frames.
  return ReadUntilButtonsStatus::GOT_BUTTONS;
}
    // Execution Not thread safe
    void DeviceVulkanw::Execute( Function const* func, std::uint32_t queue, size_t global_size, size_t local_size, Event** e )
    {
        FunctionVulkan* vulkan_function = ConstCast<FunctionVulkan>( func );

        uint32_t number_of_parameters = (uint32_t)( vulkan_function->GetParameters().size() );

        // get the Function's descriptor set group
        Anvil::DescriptorSetGroup* new_descriptor_set = vulkan_function->GetDescriptorSetGroup();

        // if it's empty, this is 1st run of the Function so we have to create it
        if ( nullptr == new_descriptor_set )
        {
            // allocate it through Anvil
            new_descriptor_set = new Anvil::DescriptorSetGroup( m_anvil_device, false, 1 );

            // add bindings and items (Buffers) to the new DSG
            for ( uint32_t i = 0; i < number_of_parameters; ++i )
            {
                const Buffer* parameter = vulkan_function->GetParameters()[ i ];
                BufferVulkan* buffer = ConstCast<BufferVulkan>( parameter );
                new_descriptor_set->add_binding( 0, i, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT );
            }

            // set it to the Function to be reused during any subsequent run
            vulkan_function->SetDescriptorSetGroup( new_descriptor_set );
        }

        // bind new items (Buffers), releasing the old ones
        for ( uint32_t i = 0; i < number_of_parameters; ++i )
        {
            const Buffer* parameter = vulkan_function->GetParameters()[ i ];
            BufferVulkan* buffer = ConstCast<BufferVulkan>( parameter );
            new_descriptor_set->set_binding_item( 0, i, buffer->GetAnvilBuffer() );

        }

        // get the Function's pipeline
        Anvil::ComputePipelineID pipeline_id = vulkan_function->GetPipelineID();

        // if it is invalid, this is 1st run of the Function so we have to create it
        if ( ~0u == pipeline_id )
        {
            // create the pipeline through Anvil with the shader module as a parameter
            m_anvil_device->get_compute_pipeline_manager()->add_regular_pipeline( false, false, vulkan_function->GetFunctionEntryPoint(), &pipeline_id );

            // attach the DSG to it
            m_anvil_device->get_compute_pipeline_manager()->attach_dsg_to_pipeline( pipeline_id, new_descriptor_set );

            // remember the pipeline for any seubsequent run
            vulkan_function->SetPipelineID( pipeline_id );
        }

        // indicate we'll be recording Vulkan commands to the CommandBuffer from now on
        StartRecording();

        // attach pipeline
        m_command_buffer->record_bind_pipeline( VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_id );

        Anvil::PipelineLayout* pipeline_layout = m_anvil_device->get_compute_pipeline_manager()->get_compute_pipeline_layout( pipeline_id );
        Anvil::DescriptorSet* descriptor_set = new_descriptor_set->get_descriptor_set( 0 );

        // attach layout and 0 descriptor set (we don't use any other set currently)
        m_command_buffer->record_bind_descriptor_sets( VK_PIPELINE_BIND_POINT_COMPUTE,
                                                    pipeline_layout,
                                                    0,
                                                    1,
                                                    &descriptor_set,
                                                    0,
                                                    nullptr );

        // set memory barriers 
        for ( uint32_t i = 0; i < number_of_parameters; ++i )
        {
            const Buffer* parameter = vulkan_function->GetParameters()[ i ];
            BufferVulkan* buffer = ConstCast<BufferVulkan>( parameter );

            Anvil::BufferBarrier bufferBarrier( VK_ACCESS_HOST_WRITE_BIT,
                                                VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
                                                GetQueue()->get_queue_family_index(),
                                                GetQueue()->get_queue_family_index(),
                                                buffer->GetAnvilBuffer(),
                                                0,
                                                buffer->GetSize() );

            m_command_buffer->record_pipeline_barrier( VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                                                    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                                                    VK_FALSE,
                                                    0, nullptr,
                                                    1, &bufferBarrier,
                                                    0, nullptr );
            // tell buffer that we are used by this submit
            buffer->SetFenceId( GetFenceId() );

        }

        // dispatch the Function's shader module
        m_command_buffer->record_dispatch( (uint32_t)global_size, 1, 1 );

        // end recording
        EndRecording( false, e );

        // remove references to buffers. they were already referenced by the CommandBuffer.
        vulkan_function->UnreferenceParametersBuffers();
    }