bool completed;
bool isRoot;
+ bool asyncFlowEnabled;
+
public TransactionScope ()
: this (TransactionScopeOption.Required,
TransactionManager.DefaultTimeout)
{
}
+ public TransactionScope(TransactionScopeAsyncFlowOption asyncFlow)
+ : this(TransactionScopeOption.Required,
+ TransactionManager.DefaultTimeout, asyncFlow)
+ {
+ }
+
public TransactionScope (Transaction transaction)
: this (transaction, TransactionManager.DefaultTimeout)
{
TimeSpan timeout, DTCOption opt)
{
Initialize (TransactionScopeOption.Required,
- transaction, defaultOptions, opt, timeout);
+ transaction, defaultOptions, opt, timeout, TransactionScopeAsyncFlowOption.Suppress);
}
public TransactionScope (TransactionScopeOption option)
}
public TransactionScope (TransactionScopeOption option,
- TimeSpan timeout)
+ TimeSpan timeout)
+ : this (option, timeout, TransactionScopeAsyncFlowOption.Suppress)
+ {
+ }
+
+ public TransactionScope(TransactionScopeOption option, TransactionScopeAsyncFlowOption asyncFlow)
+ : this(option, TransactionManager.DefaultTimeout, asyncFlow)
+ {
+ }
+
+ public TransactionScope (TransactionScopeOption option,
+ TimeSpan timeout, TransactionScopeAsyncFlowOption asyncFlow)
{
Initialize (option, null, defaultOptions,
- DTCOption.None, timeout);
+ DTCOption.None, timeout, asyncFlow);
}
public TransactionScope (TransactionScopeOption scopeOption,
DTCOption opt)
{
Initialize (scopeOption, null, options, opt,
- TransactionManager.DefaultTimeout);
+ TransactionManager.DefaultTimeout, TransactionScopeAsyncFlowOption.Suppress);
}
void Initialize (TransactionScopeOption scopeOption,
Transaction tx, TransactionOptions options,
- DTCOption interop, TimeSpan timeout)
+ DTCOption interop, TimeSpan timeout, TransactionScopeAsyncFlowOption asyncFlow)
{
completed = false;
isRoot = false;
nested = 0;
+ asyncFlowEnabled = asyncFlow == TransactionScopeAsyncFlowOption.Enabled;
if (timeout < TimeSpan.Zero)
throw new ArgumentOutOfRangeException ("timeout");
throw new InvalidOperationException ("TransactionScope nested incorrectly");
}
- if (Transaction.CurrentInternal != transaction) {
+ if (Transaction.CurrentInternal != transaction && !asyncFlowEnabled) {
if (transaction != null)
transaction.Rollback ();
if (Transaction.CurrentInternal != null)
Transaction.CurrentInternal.Rollback ();
throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
- }
+ }
- if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
- oldTransaction.Scope = parentScope;
+ if (asyncFlowEnabled) {
+ if (oldTransaction != null)
+ oldTransaction.Scope = parentScope;
- Transaction.CurrentInternal = oldTransaction;
+ var variedTransaction = Transaction.CurrentInternal;
- if (transaction == null)
- /* scope was not in a transaction, (Suppress) */
- return;
+ if (transaction == null && variedTransaction == null)
+ /* scope was not in a transaction, (Suppress) */
+ return;
- transaction.Scope = null;
+ variedTransaction.Scope = parentScope;
+ Transaction.CurrentInternal = oldTransaction;
- if (!IsComplete) {
- transaction.Rollback ();
- return;
- }
+ transaction.Scope = null;
- if (!isRoot)
- /* Non-root scope has completed+ended */
- return;
+ if (!IsComplete) {
+ transaction.Rollback ();
+ variedTransaction.Rollback();
+ return;
+ }
+
+ if (!isRoot)
+ /* Non-root scope has completed+ended */
+ return;
+
+ variedTransaction.CommitInternal();
+ transaction.CommitInternal();
+ } else {
+ if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
+ oldTransaction.Scope = parentScope;
+
+ Transaction.CurrentInternal = oldTransaction;
- transaction.CommitInternal ();
+ if (transaction == null)
+ /* scope was not in a transaction, (Suppress) */
+ return;
+
+ transaction.Scope = null;
+
+ if (!IsComplete)
+ {
+ transaction.Rollback();
+ return;
+ }
+
+ if (!isRoot)
+ /* Non-root scope has completed+ended */
+ return;
+
+ transaction.CommitInternal();
+
+ }
}
if (cfg->exception_type != MONO_EXCEPTION_NONE) \
goto exception_exit; \
} while (0)
-#define METHOD_ACCESS_FAILURE(method, cmethod) do { \
- method_access_failure ((cfg), (method), (cmethod)); \
- goto exception_exit; \
- } while (0)
#define FIELD_ACCESS_FAILURE(method, field) do { \
field_access_failure ((cfg), (method), (field)); \
goto exception_exit; \
G_BREAKPOINT ();
}
-static MONO_NEVER_INLINE void
-method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method)
-{
- char *method_fname = mono_method_full_name (method, TRUE);
- char *cil_method_fname = mono_method_full_name (cil_method, TRUE);
- mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
- mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname);
- g_free (method_fname);
- g_free (cil_method_fname);
-}
-
static MONO_NEVER_INLINE void
field_access_failure (MonoCompile *cfg, MonoMethod *method, MonoClassField *field)
{
return ins;
}
+
+static void
+emit_method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method)
+{
+ MonoInst *args [16];
+
+ args [0] = emit_get_rgctx_method (cfg, mono_method_check_context_used (method), method, MONO_RGCTX_INFO_METHOD);
+ args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (cil_method), cil_method, MONO_RGCTX_INFO_METHOD);
+
+ mono_emit_jit_icall (cfg, mono_throw_method_access, args);
+}
+
static MonoMethod*
get_memcpy_method (void)
{
}
if (!mono_method_can_access_method (method_definition, target_method) &&
!mono_method_can_access_method (method, cil_method))
- METHOD_ACCESS_FAILURE (method, cil_method);
+ emit_method_access_failure (cfg, method, cil_method);
}
if (mono_security_core_clr_enabled ())
cil_method = cmethod;
if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
- METHOD_ACCESS_FAILURE (method, cil_method);
+ emit_method_access_failure (cfg, method, cil_method);
if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod);