You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,374 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Reflection;
|
||||
using System.Runtime.DurableInstancing;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Activities.Debugger;
|
||||
using System.Collections.Generic;
|
||||
using System.Activities.Tracking;
|
||||
|
||||
[DataContract]
|
||||
internal abstract class WorkItem
|
||||
{
|
||||
static AsyncCallback associateCallback;
|
||||
static AsyncCallback trackingCallback;
|
||||
|
||||
// We use a protected field here because it works well with
|
||||
// ref style Cleanup exception handling.
|
||||
protected Exception workflowAbortException;
|
||||
|
||||
ActivityInstance activityInstance;
|
||||
|
||||
bool isEmpty;
|
||||
|
||||
Exception exceptionToPropagate;
|
||||
|
||||
// Used by subclasses in the pooled case.
|
||||
protected WorkItem()
|
||||
{
|
||||
}
|
||||
|
||||
protected WorkItem(ActivityInstance activityInstance)
|
||||
{
|
||||
this.activityInstance = activityInstance;
|
||||
this.activityInstance.IncrementBusyCount();
|
||||
}
|
||||
|
||||
public ActivityInstance ActivityInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.activityInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public Exception WorkflowAbortException
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.workflowAbortException;
|
||||
}
|
||||
}
|
||||
|
||||
public Exception ExceptionToPropagate
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.exceptionToPropagate;
|
||||
}
|
||||
set
|
||||
{
|
||||
Fx.Assert(value != null, "We should never set this back to null explicitly. Use the ExceptionPropagated method below.");
|
||||
|
||||
this.exceptionToPropagate = value;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract ActivityInstance PropertyManagerOwner
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public virtual ActivityInstance OriginalExceptionSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ActivityInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.isEmpty;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
this.isEmpty = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ExitNoPersistRequired
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
protected bool IsPooled
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public abstract bool IsValid
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
[DataMember(Name = "activityInstance")]
|
||||
internal ActivityInstance SerializedActivityInstance
|
||||
{
|
||||
get { return this.activityInstance; }
|
||||
set { this.activityInstance = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "IsEmpty")]
|
||||
internal bool SerializedIsEmpty
|
||||
{
|
||||
get { return this.IsEmpty; }
|
||||
set { this.IsEmpty = value; }
|
||||
}
|
||||
|
||||
public void Dispose(ActivityExecutor executor)
|
||||
{
|
||||
if (FxTrace.ShouldTraceVerboseToTraceSource)
|
||||
{
|
||||
TraceCompleted();
|
||||
}
|
||||
|
||||
if (this.IsPooled)
|
||||
{
|
||||
this.ReleaseToPool(executor);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ClearForReuse()
|
||||
{
|
||||
this.exceptionToPropagate = null;
|
||||
this.workflowAbortException = null;
|
||||
this.activityInstance = null;
|
||||
}
|
||||
|
||||
protected virtual void Reinitialize(ActivityInstance activityInstance)
|
||||
{
|
||||
this.activityInstance = activityInstance;
|
||||
this.activityInstance.IncrementBusyCount();
|
||||
}
|
||||
|
||||
// this isn't just public for performance reasons. We avoid the virtual call
|
||||
// by going through Dispose()
|
||||
protected virtual void ReleaseToPool(ActivityExecutor executor)
|
||||
{
|
||||
Fx.Assert("This should never be called ... only overridden versions should get called.");
|
||||
}
|
||||
|
||||
static void OnAssociateComplete(IAsyncResult result)
|
||||
{
|
||||
if (result.CompletedSynchronously)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CallbackData data = (CallbackData)result.AsyncState;
|
||||
|
||||
try
|
||||
{
|
||||
data.Executor.EndAssociateKeys(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
data.WorkItem.workflowAbortException = e;
|
||||
}
|
||||
|
||||
data.Executor.FinishWorkItem(data.WorkItem);
|
||||
}
|
||||
|
||||
static void OnTrackingComplete(IAsyncResult result)
|
||||
{
|
||||
if (result.CompletedSynchronously)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CallbackData data = (CallbackData)result.AsyncState;
|
||||
|
||||
try
|
||||
{
|
||||
data.Executor.EndTrackPendingRecords(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
data.WorkItem.workflowAbortException = e;
|
||||
}
|
||||
|
||||
data.Executor.FinishWorkItemAfterTracking(data.WorkItem);
|
||||
}
|
||||
|
||||
public void ExceptionPropagated()
|
||||
{
|
||||
// We just null this out, but using this API helps with
|
||||
// readability over the property setter
|
||||
this.exceptionToPropagate = null;
|
||||
}
|
||||
|
||||
public void Release(ActivityExecutor executor)
|
||||
{
|
||||
this.activityInstance.DecrementBusyCount();
|
||||
|
||||
if (this.ExitNoPersistRequired)
|
||||
{
|
||||
executor.ExitNoPersist();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void TraceScheduled();
|
||||
|
||||
protected void TraceRuntimeWorkItemScheduled()
|
||||
{
|
||||
if (TD.ScheduleRuntimeWorkItemIsEnabled())
|
||||
{
|
||||
TD.ScheduleRuntimeWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void TraceStarting();
|
||||
|
||||
protected void TraceRuntimeWorkItemStarting()
|
||||
{
|
||||
if (TD.StartRuntimeWorkItemIsEnabled())
|
||||
{
|
||||
TD.StartRuntimeWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void TraceCompleted();
|
||||
|
||||
protected void TraceRuntimeWorkItemCompleted()
|
||||
{
|
||||
if (TD.CompleteRuntimeWorkItemIsEnabled())
|
||||
{
|
||||
TD.CompleteRuntimeWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager);
|
||||
|
||||
public abstract void PostProcess(ActivityExecutor executor);
|
||||
|
||||
public bool FlushBookmarkScopeKeys(ActivityExecutor executor)
|
||||
{
|
||||
Fx.Assert(executor.BookmarkScopeManager.HasKeysToUpdate, "We should not have been called if we don't have pending keys.");
|
||||
|
||||
try
|
||||
{
|
||||
// disassociation is local-only so we don't need to yield
|
||||
ICollection<InstanceKey> keysToDisassociate = executor.BookmarkScopeManager.GetKeysToDisassociate();
|
||||
if (keysToDisassociate != null && keysToDisassociate.Count > 0)
|
||||
{
|
||||
executor.DisassociateKeys(keysToDisassociate);
|
||||
}
|
||||
|
||||
// if we have keys to associate, provide them for an asynchronous association
|
||||
ICollection<InstanceKey> keysToAssociate = executor.BookmarkScopeManager.GetKeysToAssociate();
|
||||
|
||||
// It could be that we only had keys to Disassociate. We should only do BeginAssociateKeys
|
||||
// if we have keysToAssociate.
|
||||
if (keysToAssociate != null && keysToAssociate.Count > 0)
|
||||
{
|
||||
if (associateCallback == null)
|
||||
{
|
||||
associateCallback = Fx.ThunkCallback(new AsyncCallback(OnAssociateComplete));
|
||||
}
|
||||
|
||||
IAsyncResult result = executor.BeginAssociateKeys(keysToAssociate, associateCallback, new CallbackData(executor, this));
|
||||
if (result.CompletedSynchronously)
|
||||
{
|
||||
executor.EndAssociateKeys(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
this.workflowAbortException = e;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool FlushTracking(ActivityExecutor executor)
|
||||
{
|
||||
Fx.Assert(executor.HasPendingTrackingRecords, "We should not have been called if we don't have pending tracking records");
|
||||
|
||||
try
|
||||
{
|
||||
if (trackingCallback == null)
|
||||
{
|
||||
trackingCallback = Fx.ThunkCallback(new AsyncCallback(OnTrackingComplete));
|
||||
}
|
||||
|
||||
IAsyncResult result = executor.BeginTrackPendingRecords(
|
||||
trackingCallback,
|
||||
new CallbackData(executor, this));
|
||||
|
||||
if (result.CompletedSynchronously)
|
||||
{
|
||||
executor.EndTrackPendingRecords(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Completed async so we'll return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
this.workflowAbortException = e;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class CallbackData
|
||||
{
|
||||
public CallbackData(ActivityExecutor executor, WorkItem workItem)
|
||||
{
|
||||
this.Executor = executor;
|
||||
this.WorkItem = workItem;
|
||||
}
|
||||
|
||||
public ActivityExecutor Executor
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public WorkItem WorkItem
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user