public boolean offer(final E e) { if (null == e) { throw new NullPointerException("element cannot be null"); } long currentTail; long currentHead = sharedHeadCache; long bufferLimit = currentHead + capacity; do { currentTail = tail; if (currentTail >= bufferLimit) { currentHead = head; bufferLimit = currentHead + capacity; if (currentTail >= bufferLimit) { return false; } UNSAFE.putOrderedLong(this, SHARED_HEAD_CACHE_OFFSET, currentHead); } } while (!UNSAFE.compareAndSwapLong(this, TAIL_OFFSET, currentTail, currentTail + 1)); UNSAFE.putOrderedObject(buffer, sequenceToBufferOffset(currentTail, mask), e); return true; }
/*non-public*/ static boolean shouldBeInitialized(MemberName member) { switch (member.getReferenceKind()) { case REF_invokeStatic: case REF_getStatic: case REF_putStatic: case REF_newInvokeSpecial: break; default: // No need to initialize the class on this kind of member. return false; } Class<?> cls = member.getDeclaringClass(); if (cls == ValueConversions.class || cls == MethodHandleImpl.class || cls == Invokers.class) { // These guys have lots of <clinit> DMH creation but we know // the MHs will not be used until the system is booted. return false; } if (VerifyAccess.isSamePackage(MethodHandle.class, cls) || VerifyAccess.isSamePackage(ValueConversions.class, cls)) { // It is a system class. It is probably in the process of // being initialized, but we will help it along just to be safe. if (UNSAFE.shouldBeInitialized(cls)) { UNSAFE.ensureClassInitialized(cls); } return false; } return UNSAFE.shouldBeInitialized(cls); }
@Override protected WeakReference<Thread> computeValue(Class<?> type) { UNSAFE.ensureClassInitialized(type); if (UNSAFE.shouldBeInitialized(type)) // If the previous call didn't block, this can happen. // We are executing inside <clinit>. return new WeakReference<>(Thread.currentThread()); return null; }
@SuppressWarnings("unchecked") public E poll() { final long currentHead = head; final long elementOffset = sequenceToBufferOffset(currentHead, mask); final Object[] buffer = this.buffer; final Object e = UNSAFE.getObjectVolatile(buffer, elementOffset); if (null != e) { UNSAFE.putObject(buffer, elementOffset, null); UNSAFE.putOrderedLong(this, HEAD_OFFSET, currentHead + 1); } return (E) e; }
@Override ConstantPool getConstantPool() { HotSpotResolvedObjectType type = HotSpotResolvedObjectType.fromObjectClass(OBJECT_TYPE_BASE.getClass()); long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE); return CompilerToVMHelper.getConstantPool(type, getPtrToCpAddress() - ptrToClass); }
public boolean copyFromChannel(FileChannel channel, TableStats stats) throws IOException { if (channel.position() < channel.size()) { clear(); buffer.clear(); channel.read(buffer); memorySize = buffer.position(); while (position < memorySize) { long recordPtr = address + position; if (remain() < SizeOf.SIZE_OF_INT) { channel.position(channel.position() - remain()); memorySize = (int) (memorySize - remain()); return true; } int recordSize = UNSAFE.getInt(recordPtr); if (remain() < recordSize) { channel.position(channel.position() - remain()); memorySize = (int) (memorySize - remain()); return true; } position += recordSize; rowNum++; } return true; } else { return false; } }
static { // The Holder class will contain pre-generated DirectMethodHandles resolved // speculatively using MemberName.getFactory().resolveOrNull. However, that // doesn't initialize the class, which subtly breaks inlining etc. By forcing // initialization of the Holder class we avoid these issues. UNSAFE.ensureClassInitialized(Holder.class); }
/** * Called from the {@link Receiver} thread to processing any pending loss of packets. * * @return number of work items processed. */ int processPendingLoss() { int workCount = 0; final long changeNumber = endLossChange; if (changeNumber != lastLossChangeNumber) { final int termId = lossTermId; final int termOffset = lossTermOffset; final int length = lossLength; UNSAFE .loadFence(); // LoadLoad required so previous loads don't move past version check below. if (changeNumber == beginLossChange) { if (isReliable) { channelEndpoint.sendNakMessage( controlAddress, sessionId, streamId, termId, termOffset, length); nakMessagesSent.orderedIncrement(); } else { final UnsafeBuffer termBuffer = termBuffers[indexByTerm(initialTermId, termId)]; if (tryFillGap(rawLog.logMetaData(), termBuffer, termId, termOffset, length)) { lossGapFills.orderedIncrement(); } } lastLossChangeNumber = changeNumber; workCount = 1; } } return workCount; }
@Override public long buildOutputChain(NginxResponse response) { long r = response.request().nativeRequest(); try { long pool = UNSAFE.getAddress(r + NGX_HTTP_CLOJURE_REQ_POOL_OFFSET); int status = response.fetchStatus(NGX_HTTP_OK); Object body = response.fetchBody(); long chain = 0; if (body != null) { chain = buildResponseItemBuf(r, body, chain); if (chain == 0) { return -NGX_HTTP_INTERNAL_SERVER_ERROR; } else if (chain < 0 && chain != -204) { return chain; } } else { chain = -NGX_HTTP_NO_CONTENT; } if (chain == -NGX_HTTP_NO_CONTENT) { if (status == NGX_HTTP_OK) { status = NGX_HTTP_NO_CONTENT; } return -status; } return chain; } catch (Throwable e) { log.error("server unhandled exception!", e); return -NGX_HTTP_INTERNAL_SERVER_ERROR; } }
public Object clone() { try { PrincipalName pName = (PrincipalName) super.clone(); UNSAFE.putObject(this, NAME_STRINGS_OFFSET, nameStrings.clone()); return pName; } catch (CloneNotSupportedException ex) { throw new AssertionError("Should never happen"); } }
/** * A "Read" operation that returns an element. Similar to contains() but first try optimistic * approach * * <p>Performance: TODO * * @return Returns the value to which the specified key is mapped, or {@code null} if this map * contains no mapping for the key. */ public boolean optimisticContains(E elem) { boolean retValue; long localVersionIndex = versionIndex.get(); int localLeftRight = leftRight.get(); if (localLeftRight == READS_ON_LEFT) { retValue = leftTree.contains(elem); } else { retValue = rightTree.contains(elem); } if (retValue) { return true; } // We add a fence here to prevent the contains() above from // moving below the versionIndex.get() UNSAFE.loadFence(); final long lVersionIndex = versionIndex.get(); if (lVersionIndex == localVersionIndex) { return false; } ReadersEntry localReadersEntry = entry.get(); // Initialize a new Reader-state for this thread if needed if (localReadersEntry == null) { localReadersEntry = addState(); } localVersionIndex = lVersionIndex % 2; try { // Set the current Reader's state to READING if (localVersionIndex == VERSION0) { localReadersEntry.st.v0State = STATE_READING; } else { localReadersEntry.st.v1State = STATE_READING; } // Read the up-to-date value of leftRight. // Order is important: The leftRight value can only be read _after_ // the Reader's state has been set. if (leftRight.get() == READS_ON_LEFT) { retValue = leftTree.contains(elem); } else { retValue = rightTree.contains(elem); } } finally { // In the extreme event that TreeSet.contains() throws an exception, // we want to make sure that no Writer is left hanging. if (localVersionIndex == VERSION0) { localReadersEntry.st.v0State = STATE_NOT_READING; } else { localReadersEntry.st.v1State = STATE_NOT_READING; } } return retValue; }
/** * Tries to match node s to this node, if so, waking up thread. Fulfillers call tryMatch to * identify their waiters. Waiters block until they have been matched. * * @param s the node to match * @return true if successfully matched to s */ boolean tryMatch(SNode s) { if (match == null && UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) { Thread w = waiter; if (w != null) { // waiters need at most one unpark waiter = null; LockSupport.unpark(w); } return true; } return match == s; }
public ResolvedJavaField lookupJavaField(Field reflectionField) { String name = reflectionField.getName(); Class<?> fieldHolder = reflectionField.getDeclaringClass(); Class<?> fieldType = reflectionField.getType(); // java.lang.reflect.Field's modifiers should be enough here since VM internal modifier bits // are not used (yet). final int modifiers = reflectionField.getModifiers(); final long offset = Modifier.isStatic(modifiers) ? UNSAFE.staticFieldOffset(reflectionField) : UNSAFE.objectFieldOffset(reflectionField); HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); JavaType type = runtime.fromClass(fieldType); if (offset != -1) { HotSpotResolvedObjectType resolved = holder; return resolved.createField(name, type, offset, modifiers); } else { throw new JVMCIError("unresolved field %s", reflectionField); } }
private static boolean checkInitialized(MemberName member) { Class<?> defc = member.getDeclaringClass(); WeakReference<Thread> ref = EnsureInitialized.INSTANCE.get(defc); if (ref == null) { return true; // the final state } Thread clinitThread = ref.get(); // Somebody may still be running defc.<clinit>. if (clinitThread == Thread.currentThread()) { // If anybody is running defc.<clinit>, it is this thread. if (UNSAFE.shouldBeInitialized(defc)) // Yes, we are running it; keep the barrier for now. return false; } else { // We are in a random thread. Block. UNSAFE.ensureClassInitialized(defc); } assert (!UNSAFE.shouldBeInitialized(defc)); // put it into the final state EnsureInitialized.INSTANCE.remove(defc); return true; }
@Override public <K, V> long prepareHeaders( NginxRequest req, long status, Collection<Map.Entry<K, V>> headers) { long r = req.nativeRequest(); long pool = UNSAFE.getAddress(r + NGX_HTTP_CLOJURE_REQ_POOL_OFFSET); long headers_out = r + NGX_HTTP_CLOJURE_REQ_HEADERS_OUT_OFFSET; String contentType = null; String server = null; if (headers != null) { for (Map.Entry<?, ?> hen : headers) { Object nameObj = hen.getKey(); Object val = hen.getValue(); if (nameObj == null || val == null) { continue; } String name = normalizeHeaderName(nameObj); if (name == null || name.length() == 0) { continue; } NginxHeaderHolder pusher = fetchResponseHeaderPusher(name); if (pusher == RESP_CONTENT_TYPE_HOLDER) { if (val instanceof String) { contentType = (String) val; } else { // TODO:support another types } } pusher.push(headers_out, pool, val); } } if (contentType == null && status != NGX_HTTP_SWITCHING_PROTOCOLS) { ngx_http_set_content_type(r); } else { int contentTypeLen = pushNGXString( headers_out + NGX_HTTP_CLOJURE_HEADERSO_CONTENT_TYPE_OFFSET, contentType, DEFAULT_ENCODING, pool); // be friendly to gzip module pushNGXSizet(headers_out + NGX_HTTP_CLOJURE_HEADERSO_CONTENT_TYPE_LEN_OFFSET, contentTypeLen); } pushNGXInt(headers_out + NGX_HTTP_CLOJURE_HEADERSO_STATUS_OFFSET, (int) status); return r; }
@SuppressWarnings("unchecked") public int drainTo(final Collection<? super E> target, final int limit) { final Object[] buffer = this.buffer; final long mask = this.mask; long nextSequence = head; int count = 0; while (count < limit) { final long elementOffset = sequenceToBufferOffset(nextSequence, mask); final Object e = UNSAFE.getObjectVolatile(buffer, elementOffset); if (null == e) { break; } UNSAFE.putOrderedObject(buffer, elementOffset, null); nextSequence++; UNSAFE.putOrderedLong(this, HEAD_OFFSET, nextSequence); count++; target.add((E) e); } return count; }
@SuppressWarnings("unchecked") public int drain(final Consumer<E> elementHandler) { final Object[] buffer = this.buffer; final long mask = this.mask; final long currentHead = head; long nextSequence = currentHead; final long limit = nextSequence + mask + 1; while (nextSequence < limit) { final long elementOffset = sequenceToBufferOffset(nextSequence, mask); final Object item = UNSAFE.getObjectVolatile(buffer, elementOffset); if (null == item) { break; } UNSAFE.putOrderedObject(buffer, elementOffset, null); nextSequence++; UNSAFE.putOrderedLong(this, HEAD_OFFSET, nextSequence); elementHandler.accept((E) item); } return (int) (nextSequence - currentHead); }
/** * Called from the {@link Receiver} to send any pending Status Messages. * * @return number of work items processed. */ int sendPendingStatusMessage() { int workCount = 0; if (ACTIVE == status) { final long changeNumber = endSmChange; if (changeNumber != lastSmChangeNumber) { final long smPosition = nextSmPosition; final int receiverWindowLength = nextSmReceiverWindowLength; UNSAFE.loadFence(); // LoadLoad required so previous loads don't move past version check // below. if (changeNumber == beginSmChange) { final int termId = computeTermIdFromPosition(smPosition, positionBitsToShift, initialTermId); final int termOffset = (int) smPosition & termLengthMask; channelEndpoint.sendStatusMessage( controlAddress, sessionId, streamId, termId, termOffset, receiverWindowLength, (byte) 0); statusMessagesSent.orderedIncrement(); lastSmChangeNumber = changeNumber; workCount = 1; } } } return workCount; }
boolean casItem(Object cmp, Object val) { return item == cmp && UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); }
boolean casNext(QNode cmp, QNode val) { return next == cmp && UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); }
boolean casHead(SNode h, SNode nh) { return h == head && UNSAFE.compareAndSwapObject(this, headOffset, h, nh); }
/** Tries to cancel a wait by matching node to itself. */ void tryCancel() { UNSAFE.compareAndSwapObject(this, matchOffset, null, this); }
boolean casNext(SNode cmp, SNode val) { return cmp == next && UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); }
/** Tries to cas nt as new tail. */ void advanceTail(QNode t, QNode nt) { if (tail == t) UNSAFE.compareAndSwapObject(this, tailOffset, t, nt); }
/** Tries to cancel by CAS'ing ref to this as item. */ void tryCancel(Object cmp) { UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this); }
/** 下一个任务 */ protected FinalCommitRunner next() { if (!UNSAFE.compareAndSwapObject(this, nextOffset, null, this)) { // has more job to run return (FinalCommitRunner) next; } return null; }
/** * Tries to cas nh as new head; if successful, unlink old head's next node to avoid garbage * retention. */ void advanceHead(QNode h, QNode nh) { if (h == head && UNSAFE.compareAndSwapObject(this, headOffset, h, nh)) h.next = h; // forget old next }
protected final void soTail(long v) { UNSAFE.putOrderedLong(this, P_INDEX_OFFSET, v); }
/** Tries to CAS cleanMe slot. */ boolean casCleanMe(QNode cmp, QNode val) { return cleanMe == cmp && UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val); }
protected final boolean casHead(long expect, long newValue) { return UNSAFE.compareAndSwapLong(this, C_INDEX_OFFSET, expect, newValue); }