001package arez; 002 003import grim.annotations.OmitSymbol; 004import grim.annotations.OmitType; 005import javax.annotation.Nonnull; 006import javax.annotation.Nullable; 007import java.util.Objects; 008import static org.realityforge.braincheck.Guards.*; 009 010/** 011 * An isolated Arez context. 012 */ 013@OmitType( unless = "arez.enable_zones" ) 014public final class Zone 015{ 016 /** 017 * The optional name of the zone. Only non-null when names are enabled. 018 */ 019 @Nullable 020 @OmitSymbol( unless = "arez.enable_names" ) 021 private final String _name; 022 /** 023 * The underlying context for zone. 024 */ 025 private final ArezContext _context = new ArezContext( this ); 026 027 /** 028 * Return the context for the zone. 029 * 030 * @return the context for the zone. 031 */ 032 @Nonnull 033 public ArezContext getContext() 034 { 035 return _context; 036 } 037 038 /** 039 * Create a zone with the specified name. 040 * Should only be done via {@link Arez} methods. 041 * 042 * @param name the name of the zone. Should be null if {@link Arez#areNamesEnabled()} returns false. 043 */ 044 Zone( @Nullable final String name ) 045 { 046 _name = Arez.areNamesEnabled() ? Objects.requireNonNull( name ) : null; 047 } 048 049 public boolean isActive() 050 { 051 return Arez.currentZone() == this; 052 } 053 054 /** 055 * Return the name of the zone if available. 056 * 057 * @return the name of the zone. Will be null if {@link Arez#areNamesEnabled()} returns false or if no name supplied. 058 */ 059 @Nullable 060 public String getName() 061 { 062 if ( Arez.shouldCheckApiInvariants() ) 063 { 064 apiInvariant( Arez::areNamesEnabled, 065 () -> "Arez-0169: Zone.getName() invoked when Arez.areNamesEnabled() is false" ); 066 } 067 return _name; 068 } 069 070 /** 071 * Run the specified function in the zone. 072 * Activate the zone on entry, deactivate on exit. 073 * 074 * @param <T> The type of the value returned from function. 075 * @param action the function to execute. 076 * @return the value returned from function. 077 */ 078 public <T> T safeRun( @Nonnull final SafeFunction<T> action ) 079 { 080 Arez.activateZone( this ); 081 try 082 { 083 return action.call(); 084 } 085 finally 086 { 087 Arez.deactivateZone( this ); 088 } 089 } 090 091 /** 092 * Run the specified function in the zone. 093 * Activate the zone on entry, deactivate on exit. 094 * 095 * @param <T> The type of the value returned from function. 096 * @param action the function to execute. 097 * @return the value returned from function. 098 * @throws Throwable if the function throws an exception. 099 */ 100 public <T> T run( @Nonnull final Function<T> action ) 101 throws Throwable 102 { 103 Arez.activateZone( this ); 104 try 105 { 106 return action.call(); 107 } 108 finally 109 { 110 Arez.deactivateZone( this ); 111 } 112 } 113 114 /** 115 * Run the specified procedure in the zone. 116 * Activate the zone on entry, deactivate on exit. 117 * 118 * @param action the procedure to execute. 119 */ 120 public void safeRun( @Nonnull final SafeProcedure action ) 121 { 122 Arez.activateZone( this ); 123 try 124 { 125 action.call(); 126 } 127 finally 128 { 129 Arez.deactivateZone( this ); 130 } 131 } 132 133 /** 134 * Run the specified procedure in the zone. 135 * Activate the zone on entry, deactivate on exit. 136 * 137 * @param action the procedure to execute. 138 * @throws Throwable if the procedure throws an exception. 139 */ 140 public void run( @Nonnull final Procedure action ) 141 throws Throwable 142 { 143 Arez.activateZone( this ); 144 try 145 { 146 action.call(); 147 } 148 finally 149 { 150 Arez.deactivateZone( this ); 151 } 152 } 153}