| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML> |
| <HEAD> |
| |
| <meta name="copyright" content="Copyright (c) IBM Corporation and others 2000, 2005. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." > |
| |
| <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1"> |
| <META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> |
| |
| <LINK REL="STYLESHEET" HREF="../book.css" CHARSET="ISO-8859-1" TYPE="text/css"> |
| <TITLE> |
| Batching resource changes |
| </TITLE> |
| |
| <link rel="stylesheet" type="text/css" HREF="../book.css"> |
| </HEAD> |
| <BODY BGCOLOR="#ffffff"> |
| <H3> |
| Batching resource changes</H3> |
| <p>When you need to modify resources in the workspace, it is important to keep in mind that other plug-ins might be |
| working with the same resources. The resources API provides robust mechanisms for keeping plug-ins informed about |
| changes in the workspace, and for making sure that multiple plug-ins do not modify the same resource at the same time. |
| Where possible, your plug-in's modifications to the workspace should be batched in units of work inside a <b>workspace runnable</b>. |
| These runnables help to reduce the amount of change notifications generated by changes. They also allow you to declare |
| which part of the workspace is to be modified, so that other plug-ins can be locked out of changing the same part of the |
| workspace. |
| </p> |
| <p>The protocol for <b><a href="../reference/api/org/eclipse/core/resources/IWorkspaceRunnable.html">IWorkspaceRunnable</a></b> |
| is fairly simple. A workspace runnable looks just like a long-running operation or platform job. The actual work is done inside |
| a <b>run</b> method, with progress reported to the supplied |
| <b><a href="../reference/api/org/eclipse/core/runtime/IProgressMonitor.html">IProgressMonitor</a></b>. Code that |
| manipulates the workspace is performed inside the <b>run</b> method. |
| </p> |
| <pre>IWorkspaceRunnable myRunnable = |
| new IWorkspaceRunnable() { |
| <b>public void run(IProgressMonitor monitor) throws CoreException {</b> |
| //do the actual work in here |
| ... |
| } |
| } |
| </pre> |
| <p>When it is time to the run the code, your plug-in tells the workspace to run the code on its behalf. This way, the |
| workspace can generate any necessary change events and ensure that no two plug-ins are modifying the same resource |
| at the same time. (Even if your plug-in is not using background jobs and the concurrency framework to modify the |
| workspace, other plug-ins may be doing so.) |
| </p> |
| <h4>Scheduling rules and locking</h4> |
| <p><b><a href="../reference/api/org/eclipse/core/resources/IWorkspace.html">IWorkspace</a></b> protocol is used to |
| run a workspace runnable. The preferred technique is using the long form of the <b>run</b> method which supplies |
| a scheduling rule and specifies how resource change events are broadcast. |
| </p> |
| <p>Specifying a scheduling rule when running a workspace runnable allows the workspace to determine whether |
| the resource changes will conflict with workspace changes happening in other threads. (See |
| <a href="runtime_jobs_rules.htm">Scheduling rules</a> for an overview of scheduling rules and |
| <b><a href="../reference/api/org/eclipse/core/runtime/jobs/ISchedulingRule.html">ISchedulingRule</a></b> protocol.) |
| Fortunately, <b><a href="../reference/api/org/eclipse/core/resources/IResource.html">IResource</a></b> |
| protocol includes the protocol for <b><a href="../reference/api/org/eclipse/core/runtime/jobs/ISchedulingRule.html">ISchedulingRule</a></b>, |
| which means that a resource can often be used as a scheduling rule for itself. |
| </p> |
| <p>Confused? Code can help to clarify this point. Suppose your plug-in is getting ready to modify a bunch of |
| resources in a particular project. It can use the project itself as the scheduling rule for making the changes. |
| The following snippet runs the workspace runnable that we created earlier: |
| </p> |
| <pre>IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| workspace.run(myRunnable, <b>myProject</b>, <b>IWorkspace.AVOID_UPDATE</b>, null); |
| </pre> |
| <p>The runnable is passed to the workspace, followed by the project that the |
| code is manipulating. This tells the workspace that all of the changes in the |
| runnable are confined to <tt>myProject</tt>. Any requests by other threads |
| to change <tt>myProject</tt> will be blocked until this runnable completes. |
| Likewise, this call will block if some other thread is already modifying |
| <tt>myProject</tt>. By specifying which part of the resource tree will be |
| modified by the runnable, you are allowing other threads to continue modifying |
| other portions of the workspace. It is important to be sure that your resource rule |
| matches the work being done inside the runnable. When a non-null scheduling |
| rule is used, any attempt to access a resource outside the scope of the scheduling |
| rule will trigger an exception. |
| </p> |
| <p> |
| There are two special scheduling rules that are important to consider. First, |
| if you use an instance of <tt>IWorkspaceRoot</tt> as the scheduling rule, |
| it means your thread is blocking access to <b>all</b> resources in the tree. |
| While a thread holds the root rule, no other thread is allowed to modify the |
| workspace. Conversely, a rule of <tt>null</tt> indicates that the thread |
| will block access to <b>no</b> resources in the tree. While a thread with the |
| null rule is free to modify the workspace itself, other threads will not be prevented |
| from performing their own modifications. The <tt>IWorkspaceRoot</tt> and |
| <tt>null</tt> scheduling rules occupy opposite ends of the concurrency spectrum. |
| With <tt>IWorkspaceRoot</tt> there is no concurrency |
| and only one thread is modifying the workspace at a time. With a <tt>null</tt> rule, |
| there is maximum concurrency as all threads can modify the workspace concurrently. |
| </p> |
| <p>The third parameter to the <b>run</b> method specifies whether any periodic resource change events should |
| be broadcast during the scope of this call. Using <tt>IWorkspace.AVOID_UPDATE</tt> tells the platform to suppress any |
| resource change events while the runnable is running and to broadcast one event at the end of the changes. |
| During this call, any other runnables created in the runnable will be considered part of the parent batch |
| operation. Resource changes made in those runnables will appear in the parent's resource change notification. |
| </p> |
| <h4>Resource rule factory</h4> |
| <p>In the example above, we assumed that the code inside our runnable only modified resources in a particular project. |
| This made it very easy to specify a scheduling rule for the runnable. In practice, it can be more difficult |
| to compute what parts of the workspace are affected by a particular change. For example, moving a resource from one |
| project to another affects both projects. <b><a href="../reference/api/org/eclipse/core/resources/IResourceRuleFactory.html">IResourceRuleFactory</a></b> |
| can be used to help compute an appropriate resource rule for certain kinds of resource changes. You can get |
| a resource rule factory from the workspace itself. |
| </p> |
| <pre>IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| IResourceRuleFactory ruleFactory = <b>workspace.getRuleFactory()</b>; |
| </pre> |
| <p>The factory can supply rules appropriate for many kinds of operations. If your runnable is moving a resource |
| from one location to another, it can obtain a rule appropriate for this operation: |
| </p> |
| <pre>ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); |
| workspace.run(myRunnable, <b>movingRule</b>, IWorkspace.AVOID_UPDATE, null); |
| </pre> |
| <p>See the javadoc for <b><a href="../reference/api/org/eclipse/core/resources/IResourceRuleFactory.html">IResourceRuleFactory</a></b> |
| for the list of available rules. The resources plug-in uses these rules itself to implement most resource operations. |
| Browsing the code that references these rule methods will help demonstrate how they are used in practice. |
| </p> |
| <p>Multiple rules can be combined using |
| <b><a href="../reference/api/org/eclipse/core/runtime/jobs/MultiRule.html">MultiRule</a></b>. |
| </p> |
| <pre>ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); |
| ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource); |
| workspace.run(myRunnable, <b>MultiRule.combine(movingRule, modifyRule)</b>, IWorkspace.AVOID_UPDATE, null); |
| </pre> |
| <h4>Ignoring the rules</h4> |
| <p>The short form of the <b>run</b> method in |
| <b><a href="../reference/api/org/eclipse/core/resources/IWorkspace.html">IWorkspace</a></b> |
| is also available. It is retained for backward compatibility. The short form does not include a rule or an update |
| flag. |
| </p> |
| <pre>workspace.run(myRunnable, null); |
| </pre> |
| <p>is effectively the same as calling |
| </p> |
| <pre>workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null); |
| </pre> |
| <p>Specifying the workspace root as the scheduling rule will put a lock on the entire workspace until the runnable |
| is finished. This is the most conservative way to perform a workspace update, but it is not very friendly to |
| other concurrency-minded plug-ins. |
| </p> |
| |
| </BODY> |
| </HTML> |