alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*******************************************************************************
 * Copyright (c) 2004, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM - Initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.utils;

import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.osgi.framework.Bundle;

/**
 * Performs string sharing passes on all string pool participants registered
 * with the platform.
 */
public class StringPoolJob extends Job {
	private static final long INITIAL_DELAY = 10000;//ten seconds
	private static final long RESCHEDULE_DELAY = 300000;//five minutes
	private long lastDuration;
	/**
	 * Stores all registered string pool participants, along with the scheduling
	 * rule required when running it.
	 */
	private Map participants = Collections.synchronizedMap(new HashMap(10));

	private final Bundle systemBundle = Platform.getBundle("org.eclipse.osgi"); //$NON-NLS-1$

	public StringPoolJob() {
		super(Messages.utils_stringJobName);
		setSystem(true);
		setPriority(DECORATE);
	}

	/**
	 * Adds a string pool participant.  The job periodically builds
	 * a string pool and asks all registered participants to share their strings in
	 * the pool.  Once all participants have added their strings to the pool, the
	 * pool is discarded to avoid additional memory overhead.
	 * 
	 * Adding a participant that is equal to a participant already registered will
	 * replace the scheduling rule associated with the participant, but will otherwise
	 * be ignored.
	 * 
	 * @param participant The participant to add
	 * @param rule The scheduling rule that must be owned at the time the
	 * participant is called.  This allows a participant to protect their data structures
	 * against access at unsafe times.
	 * 
	 * @see #removeStringPoolParticipant(IStringPoolParticipant)
	 * @since 3.1
	 */
	public void addStringPoolParticipant(IStringPoolParticipant participant, ISchedulingRule rule) {
		participants.put(participant, rule);
		if (getState() == Job.SLEEPING)
			wakeUp(INITIAL_DELAY);
		else
			schedule(INITIAL_DELAY);
	}

	/** 
	 * Removes the indicated log listener from the set of registered string
	 * pool participants.  If no such participant is registered, no action is taken.
	 *
	 * @param participant the participant to deregister
	 * @see #addStringPoolParticipant(IStringPoolParticipant, ISchedulingRule)
	 * @since 3.1
	 */
	public void removeStringPoolParticipant(IStringPoolParticipant participant) {
		participants.remove(participant);
	}

	/* (non-Javadoc)
	 * Method declared on Job
	 */
	protected IStatus run(IProgressMonitor monitor) {
		//if the system is shutting down, don't build
		if (systemBundle.getState() == Bundle.STOPPING)
			return Status.OK_STATUS;

		//copy current participants to handle concurrent additions and removals to map
		Map.Entry[] entries = (Map.Entry[]) participants.entrySet().toArray(new Map.Entry[0]);
		ISchedulingRule[] rules = new ISchedulingRule[entries.length];
		IStringPoolParticipant[] toRun = new IStringPoolParticipant[entries.length];
		for (int i = 0; i < toRun.length; i++) {
			toRun[i] = (IStringPoolParticipant) entries[i].getKey();
			rules[i] = (ISchedulingRule) entries[i].getValue();
		}
		final ISchedulingRule rule = MultiRule.combine(rules);
		long start = -1;
		int savings = 0;
		final IJobManager jobManager = Job.getJobManager();
		try {
			jobManager.beginRule(rule, monitor);
			start = System.currentTimeMillis();
			savings = shareStrings(toRun, monitor);
		} finally {
			jobManager.endRule(rule);
		}
		if (start > 0) {
			lastDuration = System.currentTimeMillis() - start;
			if (Policy.DEBUG_STRINGS)
				Policy.debug("String sharing saved " + savings + " bytes in: " + lastDuration); //$NON-NLS-1$ //$NON-NLS-2$ 
		}
		//throttle frequency if it takes too long
		long scheduleDelay = Math.max(RESCHEDULE_DELAY, lastDuration*100);
		if (Policy.DEBUG_STRINGS)
			Policy.debug("Rescheduling string sharing job in: " + scheduleDelay); //$NON-NLS-1$
		schedule(scheduleDelay);
		return Status.OK_STATUS;
	}

	private int shareStrings(IStringPoolParticipant[] toRun, IProgressMonitor monitor) {
		final StringPool pool = new StringPool();
		for (int i = 0; i < toRun.length; i++) {
			if (monitor.isCanceled())
				break;
			final IStringPoolParticipant current = toRun[i];
			SafeRunner.run(new ISafeRunnable() {
				public void handleException(Throwable exception) {
					//exceptions are already logged, so nothing to do
				}

				public void run() {
					current.shareStrings(pool);
				}
			});
		}
		return pool.getSavedStringCount();
	}
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.