⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resourcedispatcher.java

📁 jxme的一些相关程序,主要是手机上程序开发以及手机和计算机通信的一些程序资料,程序编译需要Ant支持
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		// We need to get some or all of it from the extra items.
		long toAsk = nbReserved > 0 ? quantity - nbReserved : quantity;
		long res = holdExtra(toAsk);
		if (res != toAsk) {
		    // Could not get enough. We got nothing.
		    releaseExtra(res);
		    return false;
		}
	    }

	    // Now record it.
	    nbReserved -= quantity;
	    return true;
	}

	/**
	 * Try and grant a new item to this account. If it cannot be done,
	 * the account may be eligible for the next available extra item.
	 * That there is need is assumed (otherwise, why is this called ?).
	 * @return boolean true if an item was granted, false otherwise.
	 */
	public boolean obtainItem() {

	    // Set it for consistency. It will get cleared when
	    // the item is used to satisfy the need.
	    needs = true;

	    if (nbReserved > 0) {
		notEligible();
		--nbReserved;
		return true;  // Its pre-reserved.
	    }

	    // This account may deliberately limit the number of extra
	    // items it uses. this translates into a lower limit for
	    // nbReserved when <= 0.
	    if (nbReserved <= extraLimit) {
		notEligible();
		return false;
	    }

	    if (holdExtra(1) == 1) { // Need authorization.
		notEligible();
		--nbReserved;
		return true;
	    }

	    // We are out of luck but eligible.
	    beEligible();
	    return false;
	}

	/**
	 * This will release a number of items at once rather than
	 * once. To be used in conjunctino with obtainItems(). See that
	 * method.
	 * @param quantity the number of items to be released.
	 */
	public void releaseQuantity(long quantity) {
	    if (nbReserved < 0) {
		releaseExtra(quantity < -nbReserved ? quantity : -nbReserved);
	    }
	    nbReserved += quantity;
	}

	/**
	 * This will release an item and return the most eligible account to
	 * re-use this item for. The account that is returned has been granted
	 * the item and thus the invoker is expected to do with this account
	 * whatever an invoker of obtainItem() would do in case of success.
	 * If the items that are managed are threads, the invoker is
	 * likely to be one these threads and it should therefore process
	 * the returned account as it did the one for which it was calling
	 * releaseItem, however be very carefull not to process the new account
	 * in the context of the old one; that would rapidly lead to stack
	 * overflow. In other words, be carefull of not making a construct
	 * equivalent to:
	 * process() {
	 *   doStuff();
	 *   myAccount.releaseItem().getUserObject().process();
	 * }
	 *
	 * That won't work.
	 * Instead do:
	 * work() {
	 *  while (myAccount != null) {
	 *   myAccount.getUserObject().doStuff();
	 *   myAccount = myAccount.releaseItem();
	 *  }
	 * }
	 * Or similar; always go back to base stack level.
	 * It is mandatory to handle accounts returned by releaseItem().
	 * If handling leads to releaseItem, then it has to be done in a
	 * forever loop. No choice. That's typical if the items are threads.
	 * That's normally not happening if the items are memory.
	 * 
	 * If this account is not using any extra
	 * item, it is the only eligible account to reuse this item.
	 * In that case, if this account needs the item, "this" is returned.
	 * Else the item is accounted as released and null is returned.
	 * If this account is using extra items, the item is accounted as
	 * released for this account, and granted to the most eligible account,
	 * which is returned. If roundRobin mode is OFF, the most eligible
	 * account can only be this.
	 * If no account has any need for the item, the item is counted
	 * as released for this item and globaly, and null is returned.
	 * If RoundRobin is ON, this account may not always be eligible
	 * for an extra item.
	 *
	 * @return ResourceAccount the account to which the released item
	 * has been re-assigned. null if the released item was not re-assigned.
	 */

	public ResourceAccount releaseItem() {

	    if (nbReserved < 0) {
		if (eligibles == null) {
		    // RoundRobin is OFF either we reuse it or we let
		    // it go.
		    if (needs) return this;

		    ++nbReserved; 
		    releaseExtra(1);
		    return null;
		}

		// RoundRobin is ON, we compete with others for this item.
		++nbReserved;

		// Update our eligibility which depends on extraLimit and
		// whether we have a use for the item or not.
		if ((nbReserved > extraLimit) && needs) {
		    beEligible();
		}

		ClientAccount next = mostEligible();

		if (next == null) {
		    releaseExtra(1); // noone wants it. return to main pool
		} else {
		    next.granted();
		}
		return next;
	    }

	    // Since we are (back) in our reserved range, we can't be eligible
	    // for extra.
	    notEligible();

	    // In reserved range; we keep using the item if we need it.
	    if (needs) return this;

	    ++nbReserved;
	    return null;
	}

	/**
	 * Call this with true as soon as account needs a new item.
	 * Call this with false as soon as account has all it needs.
	 * Accounts are taken out of the eligible list as soon as one
	 * item is obtained. Calling inNeed() is a way to get the item
	 * back in list (at the end) if the need is still present.
	 * @param needs Whether the account needs a new item or not.
	 */
	public void inNeed(boolean needs) {
	    this.needs = needs;
	    if ((nbReserved < 0) && (nbReserved > extraLimit) && needs) {
		beEligible();
	    } else {
		notEligible();
	    }
	}

	/**
	 * @return Object The userObject that was supplied when creating the
	 * account.
	 */
	public Object getUserObject() {
	    return userObject;
	}

	/**
	 * Set the userObject associated with that account.
	 */
	public void setUserObject(Object obj) {
	    userObject = obj;
	}

	/**
	 * Returns the number of reserved items that can still be obtained by
	 * this account.
	 * If that number is negative it means that all reserved items are
	 * currently in use, and the number is the opposite of the number
	 * of extra items that are also currently in use by that account.
	 * @return long The number of reserved items.
	 */
	public long getNbReserved() {
	    return nbReserved;
	}
    }

    /**
     * The list of eligible accounts.
     */
    private Dlist eligibles;


    /**
     * Construct a Fair Resource Allocator with the given parameters:
     * @param minAccounts The minimum number of client accounts that we want to
     * garantee we can handle. <0 means 0
     * @param minReservedPerAccount The minimum reservation request that we will
     * always grant to accounts as long as we have less than minAccounts <0 means
     * 0.
     * @param maxReservedPerAccount The maximum reservation request that we ever
     * will grant to any given account. <minReservedPerAccount means ==
     * @param extraItems The total number of items that we will authorize
     * beyond what has been reserved. <0 means 0.
     * @param maxExtraPerAccount The maximum number of extra items we will ever
     * let any given account occupy. <0 or >extraItems means ==extraItems.
     * @param roundRobin If true, when there is no items available, all
     * eligible accounts are put in a FIFO. Accounts release items often, and the
     * oldest account in the FIFO will get it. If false, accounts always keep
     * items for as long as they can use them, and there is no FIFO of eligible
     * accounts. Accounts can obtain new resources only if available at the time
     * they try to aquire it. RoundRobin is more fair but has more overhead.
     * Neither mode will cause starvation as long as accounts reserve at least
     * one item each. RoundRobin is most usefull when allocating threads.
     */
    public ResourceDispatcher(long minAccounts, long minReservedPerAccount,
			      long maxReservedPerAccount, long extraItems,
			      long maxExtraPerAccount,
			      boolean roundRobin)
    {
	if (minAccounts < 0) minAccounts = 0;
	if (minReservedPerAccount < 0) minReservedPerAccount = 0;
	if (maxReservedPerAccount < minReservedPerAccount) {
	    maxReservedPerAccount = minReservedPerAccount;
	}
	if (extraItems < 0) extraItems = 0;
	if ((maxExtraPerAccount < 0) || (maxExtraPerAccount > extraItems)) {
	    maxExtraPerAccount = extraItems;
	}
	this.extraItems = extraItems;
	this.maxReservedPerAccount = maxReservedPerAccount;
	this.minReservedPerAccount = minReservedPerAccount;
	this.reservedItems = minAccounts * minReservedPerAccount;
	this.maxExtraPerAccount = maxExtraPerAccount;
	nbEligibles = 0;
	if (roundRobin) eligibles = new Dlist();
    }

    private long holdReserved(long req) {
	if (req > reservedItems) req = reservedItems;
	reservedItems -= req;
	return req;
    }

    private void releaseReserved(long nb) {
	reservedItems += nb;
    }

    private long holdExtra(long req) {
	if (req > extraItems) req = extraItems;
	extraItems -= req;
	return req;
    }

    private void releaseExtra(long nb) {
	extraItems += nb;
    }

    private void newEligible(ClientAccount account) {
	++nbEligibles;
	eligibles.putLast(account);
    }

    private ClientAccount mostEligible() {
	if (nbEligibles == 0) return null;
	return (ClientAccount) eligibles.getFirst();
    }

    private void unEligible(ClientAccount account) {
	--nbEligibles;
	account.unlink();
    }

    // Not synch; it's just a snapshot for trace purposes.
    public int getNbEligibles() {
	return nbEligibles;
    }

    /**
     * Creates and returns a new client account.
     * @param nbReq the number of reserved items requested (may not be
     * always granted in full). A negative value is taken to mean 0. 
     * @param maxExtra the number of additional items that this account
     * authorizes to be allocated in addition to the reserved ones. This
     * is typically usefull if the items are threads and if some accounts
     * are not re-entrant. Then nbReq would be 1 and maxExtra would be 0.
     * It is also permitted to have some accounts receive no items at all
     * ever by setting nbReq and maxExtra both to zero. A negative maxExtra
     * is taken as meaning no specified limit, in which case an actual limit
     * may be set silently.
     * @param userObject An opaque cookie that the account object will return
     * when requested. This is usefull to relate an account returned by
     * ClientAccount.releaseItem() to an invoking code relevant object.
     * @return ResourceAccount An account with this allocator.
     */
    public ResourceAccount newAccount(long nbReq, long maxExtra,
				      Object userObject) {

	long extra = 0;    // reserved from extra pool
	long reserved = 0; // reserved from reserved pool

	if (nbReq > maxReservedPerAccount) nbReq = maxReservedPerAccount;

	// Anything beyond the minimum omes from extra items if there's
	// enough.
	if (nbReq > minReservedPerAccount) {
	    extra = holdExtra(nbReq - minReservedPerAccount);
	    nbReq = minReservedPerAccount;
	}

	// Then the minimum comes from reserved items, if we can.
	reserved = holdReserved(nbReq);
	nbReq -= reserved;

	// If there's some letf to be had, it means that we're getting
	// short on reserved items, we'll try to compensate by getting
	// more items from extra, but the app should start getting rid
	// of stale accounts if it can.
	if (nbReq > 0) {
	    if (LOG.isEnabledFor(Priority.WARN)) {
		LOG.warn("Accepting extra account on a best effort basis.");
	    }
	    
	    extra += holdExtra(nbReq);
	    if (extra + reserved < minReservedPerAccount) {
		// Even that was not enough to reach our minimal commitment.
		// The app should realy consider some cleanup.
		if (LOG.isEnabledFor(Priority.WARN)) {
		    LOG.warn("Accepting extra account with below minimal commitement.");
		}
	    }
	}

	if ((maxExtra > maxExtraPerAccount) || (maxExtra < 0)) {
	    maxExtra = maxExtraPerAccount;
	}

	return new ClientAccount(reserved, extra, maxExtra, userObject);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -