public static LifetimeDefinition Define(OuterLifetime lifetime, [CanBeNull] string id = null, [CanBeNull][InstantHandle] Action <LifetimeDefinition, Lifetime> atomicAction = null) { lifetime.AssertNotNull(); // Fallback to defaults if (String.IsNullOrEmpty(id)) { id = LifetimeDefinition.AnonymousLifetimeId; } // var nested = new LifetimeDefinition(id, 0, logger ?? Log.Root); var nested = new LifetimeDefinition { Id = id } /*{ Logger = logger ?? Log.Root }*/; try { // Atomic init on the new lifetime atomicAction?.Invoke(nested, nested.Lifetime); // Attach as nested to the parent lifetime // if(!nested.IsTerminated) // Might have been terminated by FAtomic lifetime.Def.Attach(nested); // Pass True: might be terminated async on another thread between our check and AttachNested body (example: Queue from another thread) } catch { nested.Terminate(); throw; } return(nested); }
/// <summary> /// Terminates current lifetime and starts new. /// </summary> /// <returns>New lifetime. Note, In case of a race condition this lifetime might be terminated.</returns> public Lifetime Next() { TerminateCurrent(); var next = new LifetimeDefinition(myParentLifetime); return(TrySetNewAndTerminateOld(next).Lifetime); }
/// <summary> /// <para>Scopes your code in <paramref name="action" /> with a lifetime that is terminated automatically when <paramref name="action" /> completes execution, or when its execution is aborted by an exception.</para> /// <para>Analogous to the <c>using</c> statement of the C# language on everything that is added to the lifetime.</para> /// </summary> /// <param name="action">The code to execute with a temporary lifetime.</param> public static async Task <T> UsingAsync <T>([NotNull][InstantHandle] Func <Lifetime, Task <T> > action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } using (var def = new LifetimeDefinition()) return(await action(def.Lifetime)); }
public static T Using <T>([NotNull, InstantHandle] Func <Lifetime, T> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } using (var def = new LifetimeDefinition()) return(action(def.Lifetime)); }
public static void Using([NotNull, InstantHandle] Action <Lifetime> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } using (var def = new LifetimeDefinition()) action(def.Lifetime); }
public static LifetimeDefinition DefineIntersection([NotNull] params OuterLifetime[] lifetimes) { var res = new LifetimeDefinition(); foreach (var lf in lifetimes) { lf.Def.Attach(res); } return(res); }
/// <summary> /// Terminates the current lifetime and calls your handler with the new lifetime. /// </summary> public void Next([NotNull] Action <Lifetime> atomicAction) { if (atomicAction == null) { throw new ArgumentNullException(nameof(atomicAction)); } TerminateCurrent(); var next = new LifetimeDefinition(myParentLifetime, atomicAction); SetNextAndTerminateCurrent(next); }
/// <summary> /// Terminates the current lifetime, calls your handler with the new lifetime and tries to set it as current. /// Similar to <see cref="Next(System.Action{JetBrains.Lifetimes.Lifetime})"/> /// </summary> public void DefineNext([NotNull] Action <LifetimeDefinition> atomicAction) { if (atomicAction == null) { throw new ArgumentNullException(nameof(atomicAction)); } TerminateCurrent(); var next = new LifetimeDefinition(myParentLifetime); TrySetNewAndTerminateOld(next, definition => definition.ExecuteOrTerminateOnFail(atomicAction)); }
public static LifetimeDefinition DefineIntersection(Lifetime lifetime1, Lifetime lifetime2) //reduces memory traffic { if (lifetime1.Status >= LifetimeStatus.Terminating || lifetime2.Status >= LifetimeStatus.Terminating) { return(LifetimeDefinition.Terminated); } var res = new LifetimeDefinition(); lifetime1.Definition.Attach(res); lifetime2.Definition.Attach(res); return(res); }
/// <summary> /// <para>Scopes your code in <paramref name="action" /> with a lifetime that is terminated automatically when <paramref name="action" /> completes execution, or when its execution is aborted by an exception.</para> /// <para>Analogous to the <c>using</c> statement of the C# language on everything that is added to the lifetime.</para> /// </summary> /// <param name="parent">A parent lifetime which limits the lifetime given to your action, and migth terminate it before the action ends.</param> /// <param name="action">The code to execute with a temporary lifetime.</param> public static async Task UsingAsync(OuterLifetime parent, [NotNull][InstantHandle] Func <Lifetime, Task> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } using (var def = new LifetimeDefinition()) { parent.Def.Attach(def); await action(def.Lifetime); } }
public static LifetimeDefinition DefineIntersection([NotNull] params Lifetime[] lifetimes) { if (lifetimes == null) { throw new ArgumentNullException(nameof(lifetimes)); } var res = new LifetimeDefinition(); foreach (var lf in lifetimes) { lf.Definition.Attach(res); } return(res); }
/// <summary> /// Atomically, assigns the new lifetime and terminates the old one. /// </summary> private LifetimeDefinition SetNextAndTerminateCurrent([NotNull] LifetimeDefinition def) { var old = Interlocked.Exchange(ref myCurrentDef, def); try { old.AllowTerminationUnderExecution = true; old.Terminate(); } catch (Exception ex) { Log.Root.Error(ex); } return(def); }
/// <summary> /// Atomically, assigns the new lifetime and terminates the old one. /// In case of a race condition when current lifetime is overwritten new lifetime is terminated /// </summary> /// <param name="newLifetimeDefinition">New lifetime definition to set</param> /// <param name="actionWithNewLifetime">Action to perform once new lifetime is set</param> /// <returns>New lifetime definition which can be terminated in case of a race condition</returns> private LifetimeDefinition TrySetNewAndTerminateOld(LifetimeDefinition newLifetimeDefinition, [CanBeNull] Action <LifetimeDefinition> actionWithNewLifetime = null) { void TerminateLifetimeDefinition(LifetimeDefinition lifetimeDefinition) { lifetimeDefinition.AllowTerminationUnderExecution = true; lifetimeDefinition.Terminate(); } // temporary lifetime definition to cope with race condition var tempLifetimeDefinition = new LifetimeDefinition(myParentLifetime); // the lifetime needs to be terminated but LifetimeDefinition.Terminated cannot be used as we will use Interlocked.CompareExchange tempLifetimeDefinition.Terminate(); var old = Interlocked.Exchange(ref myCurrentDef, tempLifetimeDefinition); try { TerminateLifetimeDefinition(old); } catch (Exception e) { Log.Root.Error(e); } try { actionWithNewLifetime?.Invoke(newLifetimeDefinition); } finally { if (Interlocked.CompareExchange(ref myCurrentDef, newLifetimeDefinition, tempLifetimeDefinition) != tempLifetimeDefinition) { TerminateLifetimeDefinition(newLifetimeDefinition); } } return(newLifetimeDefinition); }
//ctor internal Lifetime([NotNull] LifetimeDefinition definition) { myDefinition = definition; }
//ctor internal Lifetime([NotNull] LifetimeDefinition def) { myDef = def; }