private ResourceHandle *GetResourceHandler(bool isSync, ResourceManager *resourceManager, ResourceCategory *categoryId, ResourceType *resourceType, int *resourceHash, byte *path, void *unk, bool isUnk) { if (!Utf8GamePath.FromPointer(path, out var gamePath)) { PluginLog.Error("Could not create GamePath from resource path."); return(CallOriginalHandler(isSync, resourceManager, categoryId, resourceType, resourceHash, path, unk, isUnk)); } CompareHash(gamePath.Path.Crc32, *resourceHash, gamePath); ResourceRequested?.Invoke(gamePath, isSync); // If no replacements are being made, we still want to be able to trigger the event. var(resolvedPath, data) = ResolvePath(gamePath, *categoryId, *resourceType, *resourceHash); PathResolved?.Invoke(gamePath, resolvedPath, data); if (resolvedPath == null) { var retUnmodified = CallOriginalHandler(isSync, resourceManager, categoryId, resourceType, resourceHash, path, unk, isUnk); ResourceLoaded?.Invoke((Structs.ResourceHandle *)retUnmodified, gamePath, null, data); return(retUnmodified); } // Replace the hash and path with the correct one for the replacement. *resourceHash = resolvedPath.Value.InternalName.Crc32; path = resolvedPath.Value.InternalName.Path; var retModified = CallOriginalHandler(isSync, resourceManager, categoryId, resourceType, resourceHash, path, unk, isUnk); ResourceLoaded?.Invoke((Structs.ResourceHandle *)retModified, gamePath, resolvedPath.Value, data); return(retModified); }
/// <summary> /// Reserves the specified request. Removes it from availability, but not from the pool. This is typically an intermediate state held during resource negotiation. /// </summary> /// <param name="request">The request.</param> /// <returns><c>true</c> if the resource was successfully reserved, <c>false</c> otherwise.</returns> public bool Reserve(IResourceRequest request) { ResourceRequested?.Invoke(request, this); RequestEvent?.Invoke(request, this); lock (this) { if (AttemptExecution(request)) { ReservedEvent?.Invoke(request, this); ResourceReserved?.Invoke(request, this); return(true); } return(false); } }
/// <summary> /// Acquires the specified request. Removes it from availability and from the resource pool. /// </summary> /// <param name="request">The request.</param> /// <returns><c>true</c> if if the resource was successfully acquired, <c>false</c> otherwise.</returns> public bool Acquire(IResourceRequest request) { ResourceRequested?.Invoke(request, this); RequestEvent?.Invoke(request, this); lock (this) { if (AttemptExecution(request)) { AcquiredEvent?.Invoke(request, this); ResourceAcquired?.Invoke(request, this); return(true); } else { return(false); } } }
/// <summary> /// Determines and reserves the 'best' resource in the pool for the specified resource request. The /// determination is based on the access regulator agreeing that the requestor may request it, and the /// scoring algorithm in the resourceRequest providing the best score for the resource. /// </summary> /// <param name="resourceRequest">The resource request that contains the description of the resource /// desired, and with the algorithm to apparaise the 'goodness' of each resource.</param> /// <returns>true if a resource was successfully reserved.</returns> protected virtual bool ReserveBestResource(IResourceRequest resourceRequest) { if (resourceRequest.Status == RequestStatus.Reserved) { return(true); } ResourceRequested?.Invoke(resourceRequest, null); // If the resource request provides a selection strategy, we will use it. // otherwise, we will cycle through resources, executing the scoring strategy. if (resourceRequest.ResourceSelectionStrategy != null) { return(resourceRequest.ResourceSelectionStrategy(m_resources) != null); } double highestCapacity = double.MinValue; double bestScore = double.MinValue; IResource bestResource = null; foreach (IResource resource in m_resources) { if (m_accessRegulator == null || m_accessRegulator.CanAcquire(resource, resourceRequest.Key)) { if (resource.Capacity > highestCapacity) { highestCapacity = resource.Capacity; } lock ( resource ) { if ((resource.Available + resource.PermissibleOverbook) < resourceRequest.QuantityDesired) { continue; } double thisScore = resourceRequest.GetScore(resource); if (thisScore > bestScore) { bestResource?.Unreserve(resourceRequest); if (resource.Reserve(resourceRequest)) { bestScore = thisScore; bestResource = resource; // ReSharper disable once CompareOfFloatsByEqualityOperator (Explicitly set to this.) if (bestScore == Double.MaxValue) { break; } } } } } } // if ( ( bestResource == null ) && highestCapacity < resourceRequest.QuantityDesired ) { // throw new ResourcePoolInsufficientException(this,resourceRequest); // } if (bestResource != null) { resourceRequest.ResourceObtainedFrom = this; _Debug.Assert(resourceRequest.Status == RequestStatus.Free); resourceRequest.Status = RequestStatus.Reserved; return(true); } else { // // Let's see if we can *ever* satisfy the request in this Resource Request... // foreach ( IResource resource in m_resources ) { // if ( resourceRequest.GetScore(resource) > double.MinValue ) return false; // } // throw new ApplicationException("Resource manager " + Name + " cannot satisfy resource request " + resourceRequest.ToString()); return(false); } }