/// <summary>Initialize the <see cref="RootBuildHandle"/> for all <see cref="EngineRegistry.Engines"/></summary> internal static void InitializeEngineBuildHandles() { foreach (var engine in EngineRegistry.Engines) { engine.RootBuildHandle = EngineBuildHandle.Create(EngineIdResolver(null, engine.Name)); } }
void SerializeExtern <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s) where TDoc : class where TCursor : class { /* var prototype = KSoft.Debug.TypeCheck.CastReference<BlamEngineSystem>(s.Owner); * if (s.IsReading) * Prototype = prototype; * else * Contract.Assert(prototype == Prototype);*/ EngineBuildHandle.Serialize(s, ref mRootBuildHandleBaseline); using (s.EnterUserDataBookmark(this)) { SerializeExternBody(s); } if (s.IsReading) { int expected_engine_index = Engine.RootBuildHandle.EngineIndex; int actual_engine_index = RootBuildHandle.EngineIndex; KSoft.Debug.ValueCheck.AreEqual( string.Format("{0} definition for {1} uses wrong engine id", GetType().Name, Engine.Name), expected_engine_index, actual_engine_index); } }
public static void Serialize <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, ref BlamEngineTargetHandle value) where TDoc : class where TCursor : class { bool reading = s.IsReading; var build = reading ? EngineBuildHandle.None : value.Build; var platform_index = reading ? TypeExtensions.kNone : value.TargetPlatformIndex; var rsrc_model_index = reading ? TypeExtensions.kNone : value.ResourceModelIndex; EngineBuildHandle.Serialize(s, ref build); if (!build.IsNone) { if (EngineTargetPlatform.SerializeId(s, "targetPlatform", ref platform_index, true)) { EngineRegistry.SerializeResourceModelId(s, "resourceModel", ref rsrc_model_index, true); } } if (reading) { value = new BlamEngineTargetHandle(build, platform_index, rsrc_model_index); } }
/// <summary> /// Creates an engine target handle using the build handlew, but with the platform and resource model set to NONE /// </summary> /// <param name="buildHandle"></param> /// <returns></returns> public static BlamEngineTargetHandle FromBuildHandleOnly(EngineBuildHandle buildHandle) { int target_platform_index = TypeExtensions.kNone; int resource_model_index = TypeExtensions.kNone; return(new BlamEngineTargetHandle(buildHandle, target_platform_index, resource_model_index)); }
internal async Task RemoveReferenceAsync(EngineBuildHandle buildHandle) { Contract.Requires <ArgumentNullException>(!buildHandle.IsNone); bool unload_externs = !Prototype.SystemMetadata.KeepExternsLoaded; var update_refs_side_effect = UpdateReferenceSideEffect.None; if (Prototype.SystemRequiresReferenceTracking) { update_refs_side_effect = UpdateReferencesByBuild(-1, buildHandle); unload_externs = mReferencesByBuildCounts.Count == 0; // This will remove the EngineSystem from the active systems, meaning UnloadExterns will be safe // to call without locking or such as nothing can call LoadExterns on this object anymore if (unload_externs) { Engine.CloseSystem(this); mActiveInBlamEngine = false; } } else { update_refs_side_effect = UpdateReferencesByBuild(-1, buildHandle); unload_externs = update_refs_side_effect == UpdateReferenceSideEffect.OldBuildUnreferenced; // This will remove the EngineSystem from the active systems, meaning UnloadExterns will be safe // to call without locking or such as nothing can call LoadExterns on this object anymore if (unload_externs) { Engine.CloseSystem(this); mActiveInBlamEngine = false; } } if (unload_externs) { // mExternIOTask should previously be a Task for LoadExterns bool didntTimeout = WaitForExternsIO(); Contract.Assert(didntTimeout); if (mExternIOTask != null) { throw new InvalidOperationException(string.Format(Util.InvariantCultureInfo, "Tried to perform an externs IO task while one was in flight under {0}", this.Prototype.Engine)); } mExternIOTask = Task.Run((Action)UnloadExternsBegin); await mExternIOTask.ConfigureAwait(false); mExternIOTask = null; } // #REVIEW_BLAM: also don't do this if Prototype.SystemRequiresReferenceTracking==false? // reminder: we're calling this AFTER externs are unloaded...be sure your dispose code handles this if (update_refs_side_effect == UpdateReferenceSideEffect.OldBuildUnreferenced) { DisposeFromOldBuildReference(buildHandle); } }
EngineSystemReference(bool dummy) { Util.MarkUnusedVariable(ref dummy); mSystem = null; mBuildHandle = EngineBuildHandle.None; }
public BlamEngineTargetHandle(EngineBuildHandle buildHandle, int platformIndex, int resourceModelIndex) { Contract.Requires <ArgumentOutOfRangeException>(EngineTargetPlatform.IsValidIndex(platformIndex)); Contract.Requires <ArgumentOutOfRangeException>(EngineRegistry.IsValidResourceModelIndex(resourceModelIndex) || (platformIndex.IsNone() && resourceModelIndex.IsNone())); InitializeHandle(out mHandle, buildHandle, platformIndex, resourceModelIndex); }
/// <summary>Tries to get an <see cref="EngineSystemBase"/> associated with a registered engine</summary> /// <typeparam name="T"></typeparam> /// <param name="forBuild">The build requesting this system</param> /// <returns><see cref="EngineSystemReference{T}.None"/> if the engine doesn't support the requested system</returns> public static EngineSystemReference <T> TryGetSystem <T>(EngineBuildHandle forBuild) where T : EngineSystemBase { Contract.Requires <ArgumentNullException>(!forBuild.IsNone); var engine = Engines[forBuild.EngineIndex]; return(engine.TryGetSystem <T>(forBuild)); }
/// <summary>Initialize the <see cref="BranchHandle"/> and the handles for all <see cref="Revisions"/></summary> /// <param name="engineIndex"></param> /// <param name="branchIndex"></param> internal void InitializeBuildHandles(int engineIndex, int branchIndex) { BranchHandle = EngineBuildHandle.Create(engineIndex, branchIndex); foreach (var revisn in Revisions) { int revisn_index = RevisionIdResolver(this, revisn.Version); var handle = EngineBuildHandle.Create(engineIndex, branchIndex, revisn_index); revisn.InitializeBuildHandle(handle); } }
public EngineSystemReference <T> GetSystem <T>(EngineBuildHandle forBuild) where T : EngineSystemBase { Contract.Requires <ArgumentNullException>(!forBuild.IsNone); Contract.Requires(forBuild.EngineIndex == RootBuildHandle.EngineIndex); var system_guid = EngineSystemAttribute.GetSystemGuid <T>(); var system = (T)GetSystem(system_guid, forBuild); return(new EngineSystemReference <T>(system, forBuild)); }
/// <summary>Only call me if you are <see cref="EngineSystemAttribute.NewInstance"/></summary> /// <param name="prototype">The <see cref="BlamEngineSystem"/> used to describe this instance</param> internal void InitializeForNewInstance(BlamEngineSystem prototype) { Prototype = prototype; mActiveInBlamEngine = true; mRootBuildHandleBaseline = Prototype.Engine.RootBuildHandle; // ReSharper disable once InconsistentlySynchronizedField - method is construction, don't need a lock if (Prototype.SystemRequiresReferenceTracking) { mReferencesByBuildCounts = new Dictionary <EngineBuildHandle, int>(); } }
internal EngineSystemReference(EngineSystemBase system, EngineBuildHandle buildHandle) { Contract.Assume(system != null); Contract.Assume(!buildHandle.IsNone); mSystem = system; mBuildHandle = buildHandle; #pragma warning disable 4014 system.AddReferenceAsync(buildHandle); #pragma warning restore 4014 }
int UpdateReferencesByHandle(int amount, EngineBuildHandle handle, ref UpdateReferenceSideEffect sideEffect) { if (Prototype.SystemRequiresReferenceTracking) { if (!handle.IsNone) { int ref_count; if (!mReferencesByBuildCounts.TryGetValue(handle, out ref_count)) { mReferencesByBuildCounts[handle] = 0; } int ref_count_update = ref_count + amount; if (sideEffect == UpdateReferenceSideEffect.None) { if (ref_count_update == 0) // the update closed all existing references... { sideEffect = UpdateReferenceSideEffect.OldBuildUnreferenced; } else if (ref_count == 0) // existing count is 0, this is the first reference { sideEffect = UpdateReferenceSideEffect.NewBuildReferenced; } } return(mReferencesByBuildCounts[handle] = ref_count_update); } } else { int ref_count = Interlocked.CompareExchange(ref mNonBuildSpecificReferences, 0, 0); int ref_count_update = Interlocked.Add(ref mNonBuildSpecificReferences, amount); if (sideEffect == UpdateReferenceSideEffect.None) { if (ref_count_update == 0) // the update closed all existing references... { sideEffect = UpdateReferenceSideEffect.OldBuildUnreferenced; } else if (ref_count == 0) // existing count is 0, this is the first reference { sideEffect = UpdateReferenceSideEffect.NewBuildReferenced; } } return(ref_count_update); } return(0); }
UpdateReferenceSideEffect UpdateReferencesByBuild(int amount, EngineBuildHandle buildHandle) { var side_effect = UpdateReferenceSideEffect.None; if (Prototype.SystemRequiresReferenceTracking) { EngineBuildHandle engine, branch; buildHandle.ExtractHandles(out engine, out branch); int revisn_count, branch_count, engine_count; lock (mReferencesByBuildCounts) { revisn_count = UpdateReferencesByHandle(amount, buildHandle, ref side_effect); branch_count = UpdateReferencesByHandle(amount, branch, ref side_effect); engine_count = UpdateReferencesByHandle(amount, engine, ref side_effect); } // Validate that a RemoveReference hasn't made a count go negative (ie, there was an extra call) if (amount < 0) { if (revisn_count < 0 || branch_count < 0 || engine_count < 0) { throw new InvalidOperationException(string.Format( "Extra or bad RemoveReference call detected for {0} using the handle {1}", Prototype, buildHandle.ToDisplayString())); } } } else { int new_count = UpdateReferencesByHandle(amount, EngineBuildHandle.None, ref side_effect); // Validate that a RemoveReference hasn't made a count go negative (ie, there was an extra call) if (amount < 0) { if (new_count < 0) { throw new InvalidOperationException(string.Format( "Extra or bad RemoveReference call detected for {0}", Prototype)); } } } return(side_effect); }
EngineSystemBase GetSystem(Values.KGuid systemGuid, EngineBuildHandle forBuild) { if (!SupportsSystem(systemGuid)) { string system_display_name = EngineRegistry.GetSystemDebugDisplayString(systemGuid); string msg = string.Format("{0} doesn't support the system {1}", forBuild.ToDisplayString(), system_display_name); throw new InvalidOperationException(msg); } var system_metadata = EngineRegistry.TryGetRegisteredSystem(systemGuid); Contract.Assume(system_metadata != null); return(GetNewOrExistingSystem(system_metadata)); }
//internal uint Handle { get { return mHandle; } } static void InitializeHandle(out uint handle, EngineBuildHandle buildHandle, int platformIndex, int resourceModelIndex) { if (platformIndex.IsNone() && resourceModelIndex.IsNone()) { resourceModelIndex = 0; } var encoder = new Bitwise.HandleBitEncoder(); EngineRegistry.BitEncodeResourceModelIndex(ref encoder, resourceModelIndex); EngineTargetPlatform.BitEncodeIndex(ref encoder, platformIndex); encoder.Encode32(buildHandle.Handle, EngineBuildHandle.Bitmask); Contract.Assert(encoder.UsedBitCount == BlamEngineTargetHandle.BitCount); handle = encoder.GetHandle32(); }
internal async Task AddReferenceAsync(EngineBuildHandle buildHandle) { Contract.Requires <ArgumentNullException>(!buildHandle.IsNone); Contract.Assert(mActiveInBlamEngine); // #REVIEW_BLAM: this isn't an optimal setup bool load_externs = true; var update_refs_side_effect = UpdateReferenceSideEffect.None; if (Prototype.SystemRequiresReferenceTracking) { load_externs = mReferencesByBuildCounts.Count == 0; update_refs_side_effect = UpdateReferencesByBuild(+1, buildHandle); } else { update_refs_side_effect = UpdateReferencesByBuild(+1, buildHandle); load_externs = update_refs_side_effect == UpdateReferenceSideEffect.NewBuildReferenced; } if (load_externs) { Contract.Assert(mExternIOTask == null); if (mExternIOTask != null) { throw new InvalidOperationException(string.Format(Util.InvariantCultureInfo, "Tried to perform an externs IO task while one was in flight under {0}", this.Prototype.Engine)); } mExternIOTask = Task.Run((Action)LoadExternsBegin); await mExternIOTask.ConfigureAwait(false); mExternIOTask = null; } // #REVIEW_BLAM: also don't do this if Prototype.SystemRequiresReferenceTracking==false? if (update_refs_side_effect == UpdateReferenceSideEffect.NewBuildReferenced) { InitializeForNewBuildReference(buildHandle); } }
EngineSystemReference(bool dummy) { mSystem = null; mBuildHandle = EngineBuildHandle.None; }
/// <summary>Create a new reference to this system using an existing build handle</summary> /// <param name="buildHandle">The engine build which is in need of this system</param> /// <returns></returns> public EngineSystemReference NewReference(EngineBuildHandle buildHandle) => new EngineSystemReference(this, buildHandle);
/// <summary>Create a new reference to this system using an existing build handle</summary> /// <param name="buildHandle">The engine build which is in need of this system</param> /// <returns></returns> public EngineSystemReference NewReference(EngineBuildHandle buildHandle) { return(new EngineSystemReference(this, buildHandle)); }
/// <summary>Handle a specific build being referenced for the first time</summary> /// <param name="newBuildHandle">Handle that caused a build reference to be first created</param> protected virtual void InitializeForNewBuildReference(EngineBuildHandle newBuildHandle) { }
/// <summary>Handle a specific build being unreferenced for the last time</summary> /// <param name="oldBuildHandle">Handle that caused a build reference to be disposed</param> protected virtual void DisposeFromOldBuildReference(EngineBuildHandle oldBuildHandle) { }
/// <summary>Initialize the <see cref="BuildHandle"/></summary> /// <param name="handle"></param> internal void InitializeBuildHandle(EngineBuildHandle handle) { BuildHandle = handle; }