List of usage examples for android.os ConditionVariable block
public void block()
From source file:com.jogden.spunkycharts.pricebyvolumechart.PriceByVolumeChartFragmentAdapter.java
private Thread _createPriceAxisAndMainPanel() { Thread thisThread = new Thread() { public void run() { /////////////////////////////////// /* START PREEMPTION LOGIC */ ///////////////////////////////// boolean noWait; final int MAX_PREEMPT_COUNT = ApplicationPreferences.getMaxPreemptCount(); if (!(noWait = _priceAxisLck.tryLock())) { synchronized (_priceAxisThrdMntr) { if (_priceAxisPrmptCnt++ > MAX_PREEMPT_COUNT) return; if (_priceAxisThrd != null) _priceAxisThrd.interrupt(); }/*from www.j a va 2 s .co m*/ _priceAxisPrmptStck.offer(this); _priceAxisLck.lock(); } try { /* everything that follows should assume we own monitor */ if (!noWait) { if (this != _priceAxisPrmptStck.peekLast()) return; else { /* don't assume stack hasn't grown since the peek */ Iterator<Thread> dIter = _priceAxisPrmptStck.iterator(); do { _priceAxisPrmptStck.poll(); } while (dIter.next() != this); } } synchronized (_priceAxisThrdMntr) { _priceAxisThrd = this; } ///////////////////////////////// /* END PREEMPTION LOGIC */ ////////////////////////////// float rangeDiff = _highPrice - _lowPrice; /* deal with problematic high/low parameters */ if (rangeDiff <= 0 || _highPrice < 0 || _lowPrice < 0) if (rangeDiff == 0 && _highPrice > 0) { _highPrice *= 1.001; _lowPrice *= .999; rangeDiff = _highPrice - _lowPrice; } else throw new IllegalStateException("Invalid high and/or low price in the ChartAdapter"); /* if we haven't calculated the height of a price-label view */ if (_priceElemHght == 0) {/* can cached value doesn't go stale? */ final YAxisPriceLabel tv1 = (YAxisPriceLabel) _inflater.inflate(R.layout.y_axis_price_label, null); tv1.setText("X"); tv1.setTextSize(_axisFontSz); tv1.setVisibility(View.INVISIBLE); final ConditionVariable cond = new ConditionVariable(); _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.removeAllViews(); _priceAxis.addView(tv1); cond.open(); } }); cond.block(); cond.close(); YAxisPriceLabel tv1b = (YAxisPriceLabel) _priceAxis.getChildAt(0); /* make sure a valid priceElemHeightt, or quit entirely */ /* just spin, a new thread preempts us anyway */ while ((_priceElemHght = tv1b.getHeight()) == 0) Thread.sleep(_axisTimeoutIncr); } _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.removeAllViews(); } }); int totalHeight; /* make sure a valid totalHeight, or quit entirely */ /* just spin, a new thread preempts us anyway */ while ((totalHeight = _priceAxis.getHeight()) == 0 || totalHeight > _myContainer.getHeight()) Thread.sleep(_axisTimeoutIncr); float[] incrVals = new float[2]; try { int maxNodes = (int) (totalHeight / _priceElemHght); if (rangeDiff < 0 || maxNodes < 0) throw new PriceByVolumeChartLogicError("rangeDiff and maxNodes can't be negative."); incrVals = /* call down to our native sub to find increment values */ MainApplication.IncrementRegressNative(rangeDiff, maxNodes); if (incrVals[0] < 0 || incrVals[1] <= 0) throw new PriceByVolumeChartLogicError("IncrementRegressNative() sub-routine aborted. " + "retVals[0]: " + incrVals[0] + "retVals[1]: " + incrVals[1] + "adjRangeDiff: " + rangeDiff + "maxNodes" + maxNodes); _segCount = (int) incrVals[1]; _segSize = incrVals[0]; } catch (PriceByVolumeChartLogicError e) { Log.e("PriceByVolumeChartLogicError", e.getMessage()); return; /* just leave the axis empty*/ } /* adjust height to new increment values */ final int adjPriceElemHeight = (int) (totalHeight / _segCount); /* we'll need to account for any unused spaced in the axis */ final int vacantHeight = totalHeight - (int) (adjPriceElemHeight * _segCount); double distFromIncr = Math.IEEEremainder((double) _highPrice, (double) _segSize); /* distance from rounded incr value */ double adjTopNodeVal = (double) _highPrice - distFromIncr; if (distFromIncr > 0) /* be sure to round to the upper incr */ adjTopNodeVal += _segSize; DecimalFormat df = new DecimalFormat("0.00"); double lastNodeVal = adjTopNodeVal; int count = 0; do { /* loop through the increments */ final YAxisPriceLabel tv = (YAxisPriceLabel) _inflater.inflate(R.layout.y_axis_price_label, null); tv.setTextSize(_axisFontSz); tv.setText(df.format(lastNodeVal)); tv.setTextColor(_axisFontColor); tv.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 0, 1)); _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.addView(tv); } }); /* for the loop-contingent side-effect */ } while (++count < (int) _segCount && (lastNodeVal -= _segSize) > 0); final float halfVacantHeight = vacantHeight / 2; _mainSgmnt.setVerticalBuffers((int) halfVacantHeight, (int) halfVacantHeight); _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.setPadding( /* center price-views */ 0, (int) halfVacantHeight, 0, (int) halfVacantHeight); _priceAxis.setClipChildren(false); _priceAxis.setClipToPadding(false); _priceAxis.invalidate(); } }); synchronized (_priceAxisThrdMntr) { _priceAxisPrmptCnt = 0; } } catch (InterruptedException e) { } catch (IllegalStateException e) { Log.d("IllegalState(High, Low): ", "IllegalStateException caught in _createPriceAxisAndMainPanelY: " + Float.toString(_highPrice) + " - " + Float.toString(_lowPrice)); } catch (RuntimeException e) { e.printStackTrace(); throw e; } finally { synchronized (_priceAxisThrdMntr) { _priceAxisThrd = null; } _activeThreads.remove(this); _priceAxisLck.unlock(); } } }; _activeThreads.add(thisThread); thisThread.start(); return thisThread; }
From source file:com.jogden.spunkycharts.traditionalchart.TraditionalChartFragmentAdapter.java
private void _createTimeAxisX() { Thread thisThread = new Thread() { public void run() { if (!_timeAxisLck.tryLock()) /* be sure only one running */ return; try { int axisWidth; final HideHorizontalLeftOverflowWrapper axisWrapper = (HideHorizontalLeftOverflowWrapper) _myContainer .findViewById(R.id.ofwrap_xAxis); int failCount = 0; /* if we can't get valid width data, exit completely */ while ((axisWidth = axisWrapper.getWidth()) == 0 || axisWidth > _myContainer.getWidth()) { Thread.sleep(_axisTimeoutIncr); if ((failCount += _axisTimeoutIncr) >= _axisTimeout) return; }// w w w . ja va 2 s . c om int xElemWidth = 0; final XAxisTimeLabel tvSent = (XAxisTimeLabel) _inflater.inflate(R.layout.x_axis_time_label, null); tvSent.setTag("sentinel_x_axis_view"); tvSent.setTextSize(_axisFontSz); /* sacrifice first time-stamp for size info, otherwise block */ //TODO: re-think why we have to sacrifice it ?? // could be a big deal on narrow charts tvSent.setText(_timeStampQueue.take()); /* Log.d("Data-Consumer-Time-Take", String.valueOf(lastElem) );*/ final ConditionVariable cond = new ConditionVariable(); _guiThrdHndlr.post(new Runnable() { public void run() { tvSent.setVisibility(View.INVISIBLE); _timeAxis.addView(tvSent); cond.open(); } }); cond.block(); cond.close(); final XAxisTimeLabel tvSentB = (XAxisTimeLabel) _timeAxis .findViewWithTag("sentinel_x_axis_view"); failCount = 0; while ((xElemWidth = tvSentB.getWidth()) == 0) { Thread.sleep(_axisTimeoutIncr); if ((failCount += _axisTimeoutIncr) >= _axisTimeout) return; } _guiThrdHndlr.post(new Runnable() { public void run() { _timeAxis.removeView(tvSentB); } }); /* how much space we'll need to 'stradle' price segs */ int adjElem = xElemWidth + _xAxisPadSz; int reqPriceSegs = (int) Math.ceil((double) adjElem / _priceSegWdth); if ((reqPriceSegs % 2) == 0) ++reqPriceSegs; adjElem = reqPriceSegs * _priceSegWdth; /* how much space is open for a new view at each iteration*/ int openSpace = _priceSegWdth * (reqPriceSegs / 2); /* also, do we need to drop views from the other side ? */ int fullSpace = _priceSegWdth * (reqPriceSegs / 2); CharSequence cachedElem = null; int rOffset = _myResources.getDimensionPixelSize(R.dimen.chart_frag_trad_segs_right_padding); /* a view to hold open space that isn't big enough yet */ final XAxisTimeLabel spaceHolder = (XAxisTimeLabel) _inflater .inflate(R.layout.x_axis_time_label, null); spaceHolder.setTag("front_adj_x_axis_view"); spaceHolder.setVisibility(View.INVISIBLE); /// START MAIN TIME-STAMP UPDATE LOOP /// while (!this.isInterrupted()) { CharSequence lastElem = _timeStampQueue.take(); /* Log.d("Data-Consumer-Time-Take", String.valueOf(lastElem) );*/ openSpace += _priceSegWdth; /* if no open space but need THIS element */ if ((openSpace >= (adjElem / 2)) && cachedElem == null) cachedElem = lastElem; /* if this pushes past the container limits, drop oldest */ if ((fullSpace + _priceSegWdth) > (axisWidth - rOffset)) { _guiThrdHndlr.post(new Runnable() { public void run() { /* be sure its big enough */ if (_timeAxis.getChildCount() > 0) _timeAxis.removeViewAt(0); _timeAxis.forceLayout(); } }); fullSpace -= adjElem; } /* if element cached and open space for it is large enough */ if ((cachedElem != null) && openSpace == adjElem) { final XAxisTimeLabel tvVal = (XAxisTimeLabel) _inflater .inflate(R.layout.x_axis_time_label, null); tvVal.setTag("valid_x_axis_view"); tvVal.setTextSize(_axisFontSz); tvVal.setTextColor(_axisFontColor); tvVal.setText(cachedElem); tvVal.setWidth(adjElem); _guiThrdHndlr.post(new Runnable() { public void run() { /* remove the view holding space */ _timeAxis.removeView(spaceHolder); _timeAxis.addView(tvVal); spaceHolder.setWidth(0); spaceHolder.invalidate(); /* after adjusting re-insert at front */ _timeAxis.addView(spaceHolder); _timeAxis.forceLayout(); } }); /* no open space and that much more full space */ cachedElem = null; openSpace = 0; fullSpace += _priceSegWdth; } else { /* if no element cached or not enough space */ final int fOpenSpace = openSpace; _guiThrdHndlr.post(new Runnable() { public void run() { /* shift all views left regardless */ spaceHolder.setWidth(fOpenSpace); spaceHolder.invalidate(); _timeAxis.forceLayout(); } }); fullSpace += _priceSegWdth; } } /// END MAIN TIME-STAMP UPDATE LOOP /// } catch (InterruptedException e) { } catch (RuntimeException e) { throw e; } finally { _activeThreads.remove(this); _timeAxisLck.unlock(); } } }; _activeThreads.add(thisThread); thisThread.start(); }
From source file:com.jogden.spunkycharts.traditionalchart.TraditionalChartFragmentAdapter.java
private void _createPriceAxisY() { Thread thisThread = new Thread() { public void run() { /////////////////////////////////// /* START PREEMPTION LOGIC */ ///////////////////////////////// boolean noWait; final int MAX_PREEMPT_COUNT = ApplicationPreferences.getMaxPreemptCount(); if (!(noWait = _priceAxisLck.tryLock())) { synchronized (_priceAxisThrdMntr) { if (_priceAxisPrmptCnt++ > MAX_PREEMPT_COUNT) return; if (_priceAxisThrd != null) _priceAxisThrd.interrupt(); }/* w w w. java2s . c o m*/ _priceAxisPrmptStck.offer(this); _priceAxisLck.lock(); } try { /* everything that follows should assume we own monitor */ if (!noWait) { if (this != _priceAxisPrmptStck.peekLast()) return; else { /* don't assume stack hasn't grown since the peek */ Iterator<Thread> dIter = _priceAxisPrmptStck.iterator(); do { _priceAxisPrmptStck.poll(); } while (dIter.next() != this); } } synchronized (_priceAxisThrdMntr) { _priceAxisThrd = this; } ///////////////////////////////// /* END PREEMPTION LOGIC */ /////////////////////////////// _updateLtch.await(); /* wait for historic data to be inserted */ float rangeDiff = _highPriceDsply - _lowPriceDsply; /* deal with problematic high/low parameters */ if (rangeDiff <= 0 || _highPriceDsply < 0 || _lowPriceDsply < 0) if (rangeDiff == 0 && _highPriceDsply > 0) { _highPriceDsply *= 1.001; _lowPriceDsply *= .999; rangeDiff = _highPriceDsply - _lowPriceDsply; _priceSgmnt.setYRange(_highPriceDsply, _lowPriceDsply, _highPrice, _lowPrice); } else throw new IllegalStateException("Invalid high and/or low price in the ChartAdapter"); /* if we haven't calculated the height of a price-label view */ if (_priceElemHght == 0) {/* can cached value doesn't go stale? */ final YAxisPriceLabel tv1 = (YAxisPriceLabel) _inflater.inflate(R.layout.y_axis_price_label, null); tv1.setText("X"); tv1.setTextSize(_axisFontSz); tv1.setVisibility(View.INVISIBLE); final ConditionVariable cond = new ConditionVariable(); _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.removeAllViews(); _priceAxis.addView(tv1); cond.open(); } }); cond.block(); cond.close(); YAxisPriceLabel tv1b = (YAxisPriceLabel) _priceAxis.getChildAt(0); /* make sure a valid priceElemHeightt, or quit entirely */ /* just spin, a new thread preempts us anyway */ while ((_priceElemHght = tv1b.getHeight()) == 0) Thread.sleep(_axisTimeoutIncr); } _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.removeAllViews(); } }); int totalHeight; /* make sure a valid totalHeight, or quit entirely */ /* just spin, a new thread preempts us anyway */ while ((totalHeight = _priceAxis.getHeight()) == 0 || totalHeight > _myContainer.getHeight()) Thread.sleep(_axisTimeoutIncr); float[] incrVals = new float[2]; try { int maxNodes = (int) (totalHeight / _priceElemHght); if (rangeDiff < 0 || maxNodes < 0) throw new TraditionalChartLogicError("rangeDiff and maxNodes can't be negative."); /* call down to our native sub to find increment values */ incrVals = MainApplication.IncrementRegressNative(rangeDiff, maxNodes); if (incrVals[0] < 0 || incrVals[1] <= 0) throw new TraditionalChartLogicError("IncrementRegressNative() sub-routine aborted. " + "retVals[0]: " + incrVals[0] + "retVals[1]: " + incrVals[1] + "adjRangeDiff: " + rangeDiff + "maxNodes" + maxNodes); } catch (TraditionalChartLogicError e) { Log.e("TraditionalChartLogicError", e.getMessage()); return; /* just leave the axis empty*/ } /* adjust height to new increment values */ final int adjPriceElemHeight = (int) (totalHeight / (int) incrVals[1]); /* we'll need to account for any unused space in the axis */ final int vacantHeight = totalHeight - (int) (adjPriceElemHeight * (int) incrVals[1]); double distFromIncr = Math.IEEEremainder((double) _highPriceDsply, (double) incrVals[0]); /* distance from rounded incr */ double adjTopNodeVal = (double) _highPriceDsply - distFromIncr; if (distFromIncr > 0) /* be sure to round to the upper incr */ adjTopNodeVal += incrVals[0]; DecimalFormat df = new DecimalFormat("0.00"); double lastNodeVal = adjTopNodeVal; int count = 0; do { /* loop through the increments */ final YAxisPriceLabel tv = (YAxisPriceLabel) _inflater.inflate(R.layout.y_axis_price_label, null); tv.setTextSize(_axisFontSz); tv.setText(df.format(lastNodeVal)); tv.setTextColor(_axisFontColor); tv.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 0, 1)); _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.addView(tv); } }); /* for the loop-contingent side-effect */ } while (++count < (int) incrVals[1] && (lastNodeVal -= incrVals[0]) > 0); /* values for padding the axis and adjusting the segments */ final double adjTopNodeOffset = ((adjTopNodeVal - _highPriceDsply) / rangeDiff) * totalHeight; final double adjBottomNodeOffset = ((_lowPriceDsply - lastNodeVal) / rangeDiff) * totalHeight; final float halfVacantHeight = vacantHeight / 2; final float halfPriceElemHeight = adjPriceElemHeight / 2; final int topBuf = (int) (adjTopNodeOffset + halfVacantHeight + halfPriceElemHeight); final int bottomBuf = (int) (adjBottomNodeOffset + halfVacantHeight + halfPriceElemHeight); /* adjust price segments so they align w/ axis vals */ _priceSgmnt.setVerticalBuffers(topBuf, bottomBuf); _guiThrdHndlr.post(new Runnable() { public void run() { _priceAxis.setPadding( /* center price-views */ 0, (int) halfVacantHeight, 0, (int) halfVacantHeight); _priceAxis.setClipChildren(false); _priceAxis.setClipToPadding(false); _priceAxis.invalidate(); _priceSgmnt.forceDraw(); } }); synchronized (_priceAxisThrdMntr) { _priceAxisPrmptCnt = 0; } } catch (InterruptedException e) { } catch (IllegalStateException e) { Log.d("IllegalState(High, Low): ", "IllegalStateException caught in _createPriceAxisY: " + Float.toString(_highPriceDsply) + " - " + Float.toString(_lowPriceDsply)); } catch (RuntimeException e) { e.printStackTrace(); throw e; } finally { synchronized (_priceAxisThrdMntr) { _priceAxisThrd = null; } _activeThreads.remove(this); _priceAxisLck.unlock(); } } }; _activeThreads.add(thisThread); thisThread.start(); }