# Refactoring for Java-Structured Concurrency
## 4 Design
### Precondition
#### 4.3.1 Precondition for _shutdownOnFailure_ Strategy
By invoking the methods _husConDep_ and _hasDataDep_, the Algorithm 1 performs the control and data dependency analysis (line 2). If any dependency exists, it returns _true_ (line 3). Figure 5: Check task result acquisition. ```
Input: Method: \(m\), Set: tasks Output: True or False
1 FunctiontaskDependencyAnalysis(\(m\), tasks):
2 if\(hasConDep(m,tasks)\mid\mid hasDataDep(m,tasks)\)then
3 returntrue;
4 returnfalse;
5 FunctionhasConDep(\(m\), tasks):
6 res\(\leftarrow\) obtain all the futures and futures' results in \(m\);
7 foreachtask in tasksdo
8 foreachstmt in task\({}^{\prime}\)s statementsdo
9 ifstmt contains value && value \(\in\)resthen
10 returntrue;
11 returnfalse;
12 FunctionhasDataDep(\(m\), tasks):
13 pta\(\leftarrow\)pointsToAnalysis(\(i\));
14 set\(\leftarrow\)O;
15 foreachtask in tasksdo
16 mp\(\leftarrow\)O;
17 foreachstmt in task\({}^{\prime}\)s statementsdo
18 ifstmt contains valuethen
19 mp.put(value, pta.reachingObjects(value));
20 set.add(mp);
21\(mp_{1}\), \(mp_{2}\leftarrow\) different maps from set;
22 foreach(\(k_{1},v_{1}\)) in \(mp_{1}\)do
23 foreach(\(k_{2},v_{2}\)) in \(mp_{2}\)do
24 if\(v_{1}\cap v_{2}\
eq\emptyset\)&& hasWriteOp \((k_{1},k_{2})\)then
25 returntrue;
26 returnfalse;
```  
**Algorithm 1**Task Dependency Analysis  
The method _hasConDep_ is used to detect control dependencies between tasks. Typically, tasks at the same level do not have mutual calling relationships. Therefore, the control dependency here primarily determines whether one task depends on the execution results of another task. The _hasConDep_ method also takes \(m\) and _tasks_ as input parameters. First, it obtains all the _Future_ objects and the results of these _Future_ objects in \(m\), recording them as a set (_res_) (line 6). This step ensures that all the possible sources of dependencies are covered. Then, it iterates through the statements in _tasks_. If a statement uses a variable that belongs to _res_, it indicates that the current task depends on the results of the execution of other tasks. In this case, the algorithm returns _true_ (lines 7-10). If no such variables are found, it checks the following statement. Finally, if no dependency is detected, it returns _false_ (line 11). The method _hasDataDep_ is used to analyze data dependencies between tasks; _hasDataDep_ determines dependency by analyzing the method (\(m\)) and the collection of tasks. First, it performs pointer analysis and returns the result of the pointer analysis (_pta_) (line 13). Here, _pta_ is an instance of the interface _PointsToAnalysis_, which implements pointer analysis. _PointsToAnalysis_ defines a series of methods for performing pointer analysis. Among them, the method _reachingObject_ takes an object as input and returns the set of variables that reference this object. Next, a collection (_set_) is defined to store the pointer information of the variables for each class (line 14). Then, it iterates through each task, collecting the \"value\"objects and their corresponding pointer information in the task and storing them in the map (_mp_). \"Value\" represents a general variable in a program, including constants and variables. After the completion of the task traversal, _mp_ is added to _set_ (lines 15-20). In this way, the _set_ contains the pointer information of the variables in _m_'s tasks. Finally, if the values of different maps in _set_ have an intersection and one of them involves a write operation on its keys, _true_ is returned (lines 21-25).