/* After a successful call, the resources necessary to perform the operation * should be reserved for the time of the returned authorization. */ public RequestResult RequestLanding(Guid aircraftId) { mutex.WaitOne(); // A runway and a parking stand are available. if (NumberOfAvailableRunways() > 0 && NumberOfAvailableParkingStands() > 0) { // Reserve and return the resources' ids Guid runwayId = ReserveAvailableRunway(); Guid parkingStandId = ReserveAvailableParkingStand(); // Create the landing request token LandingRequestToken token = new LandingRequestToken(TokenValiditySeconds, aircraftId, runwayId, parkingStandId); // Subscribe for token's expiration to ensure reserved resources can be released. token.Elapsed += OnExpiredLandingToken; mutex.ReleaseMutex(); return(new RequestResult(RequestResult.RequestState.Proceed, token)); } else { mutex.ReleaseMutex(); return(new RequestResult(RequestResult.RequestState.Hold, null)); } }
// Releases resources when the landing token's timer elapses. private void OnExpiredLandingToken(object source, ElapsedEventArgs e) { LandingRequestToken token = (LandingRequestToken)source; // Unsubscribe from the token's timer. token.Elapsed -= OnExpiredLandingToken; // Release the token's resources. ReleaseLandingResources(token); }
// Release resources reserved by a landing request token that will not be used. private void ReleaseLandingResources(LandingRequestToken token) { Runway runway = GetRunwayById(token.runwayId); ParkingStand parkingStand = GetParkingStandById(token.parkingStandId); runway.state = Runway.RunwayState.Available; runway.aircraftId = Guid.Empty; parkingStand.aircraftId = Guid.Empty; parkingStand.state = ParkingStand.ParkingStandState.Available; token.Dispose(); }
/* After this call is executed successfully, the used runway is InOperation * for the length of operation duration parameter and can't handle any other * operations during this time. After the operation is completed, the runway * becomes Available again, and the reserved parking stand becomes * Occupied. The call is non-blocking, i.e. it returns before the runway is * cleared. */ public PerformResult PerformLanding(LandingRequestToken token) { token.Stop(); token.Elapsed -= OnExpiredLandingToken; // Token hasn't expired yet if (DateTime.Now <= token.expiration && !token.hasExpired) { Runway runway = GetRunwayById(token.runwayId); // Check if the runway exists and if it has been properly reserved if (runway == null || runway.state != Runway.RunwayState.Reserved) { ReleaseLandingResources(token); return(PerformResult.InvalidParameters); } ParkingStand parkingStand = GetParkingStandById(token.parkingStandId); // Check if the parkingStand exists and if it has been properly reserved if (parkingStand == null || parkingStand.state != ParkingStand.ParkingStandState.Reserved) { ReleaseLandingResources(token); return(PerformResult.InvalidParameters); } runway.aircraftId = token.aircraftId; parkingStand.aircraftId = runway.aircraftId; runway.Elapsed += OnLandingOperationComplete; token.Dispose(); runway.Operate(); return(PerformResult.Success); } else // Token has expired { if (!token.hasExpired) // the token's expiration date has passed but the elapsed event hasn't fired yet, then release the resources. { ReleaseLandingResources(token); } return(PerformResult.ExpiredToken); } }