midp_link.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 971 行 · 第 1/2 页
C
971 行
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <jvm.h>#include <kni.h>#include <kni_globals.h>#include <midp_libc_ext.h>#include <midp_logging.h>#include <midp_thread.h>#include <midpError.h>#include <midpServices.h>#include <pcsl_memory.h>#include <sni.h>#include <stdio.h>#include <stdlib.h>#include <string.h>static const char* const midpClosedLinkException = "com/sun/midp/links/ClosedLinkException"; /* IMPL_NOTE - move to midpError.h? *//** * Native methods for the com.sun.midp.links.Link class. Definitions for a * native data structure representing a rendezvous point that underlies a pair * of Link objects. * * While sending and receiving threads are blocked, they each put a reference * to a LinkMessage object into the rendezvous point. When awakening, the * reference is checked against the one that's a parameter to the native * method. If they are the same object, processing continues. If they are * different objects, this indicates that another thread is in the midst of an * operation on this Link, so the calling thread simply goes back to sleep. * * This works unambiguously for receivers, since the receive() method creates * a unique LinkMessage object whenever it's called. It's possible for * multiple threads to call send() on the same LinkMessage object. Since * they're sending the same object, it doesn't matter which thread is * considered to have processed it -- the order of execution doesn't matter. * * IMPL_NOTE - use AddStrongReference or AddWeakReference? * * IMPL_NOTE - test for out-of-memory after AddStrongReference */#define INVALID_REFERENCE_ID (-1)/** * The current state of the rendezvous point. The initial state is IDLE. * There are two normal paths through the state machine, depending upon * whether a receiver or sender thread arrives first. * * The state transitions are asymmetrical because of the need for the receiver * to allocate an object that will receive the message. It doesn't know what * to allocate until a sender arrives with a message. Therefore, there is an * extra set of context switches if the receiver arrives first. * * If the sender arrives first, the transitions are as follows: * * IDLE * - sender calls send0() and blocks * SENDING * - receiver calls receive0(), transfers message, sets retcode, * awakens sender, and continues * DONE * - sender awakens and cleans up * IDLE * * If the receiver blocks first, the transitions are as follows: * * IDLE * - receiver calls receive0() and blocks * RECEIVING * - sender calls send0(), awakens receiver, and blocks * RENDEZVOUS * - receiver awakens, transfers message, sets retcode, * awakens sender, and continues * DONE * - sender awakens and cleans up * IDLE * * The close() call will move the state to CLOSED and awaken any waiters. */typedef enum { IDLE, /* no operations pending */ SENDING, /* a thread has called send() and awaits a receiver */ RECEIVING, /* a thread has called receive() and awaits a sender */ RENDEZVOUS, /* receiver and sender threads have rendezvoused */ DONE, /* the receiver is done with the transfer */ CLOSED /* no further operations permitted */} state_t;/** * Return code set by the collaborating thread. That is, if a thread is * blocked in receive(), a thread that calls send() is the collaborating * thread, and vice-versa. This value is significant only when the rendezvous * state is RECEIVED or SENT. */typedef enum { OK, /* collaborator transferred a message successfully */ ERROR /* collaborator failed for some reason */} retcode_t;/** * Implements the concept of a "rendezvous point" as defined in the JSR-121 * specification. */typedef struct _rendezvous { state_t state; /* current state */ retcode_t retcode; /* collaborator's return code */ int refcount; /* num Java objs pointing to this struct */ jint msg; /* refId for the sender's pending message */ int sender; /* the isolate ID of the sender */ int receiver; /* the isolate ID of the receiver */} rendezvous;/** * An entry in the array of portals. Count is the number of rendezvous * points. Its value is -1 if none have been set, 0 if set to an empty array, * or >0 if there is an actual array. The rppa field points to the array of * rendezvous points, or NULL if not allocated. Note that if count is 0, rppa * will be NULL but the array is considered to have been set. */typedef struct _portal { int count; /* the number of rendezvous points */ rendezvous **rppa; /* array of pointers to rendezvous points */} portal;/** * Pointer to an array of portal entries. Allocated lazily; will have size of * JVM_MaxIsolates(). * * IMPL_NOTE: need to deal with initialization and finalization. */static portal *portals = NULL;#if ENABLE_I3_TESTstatic void log_rp_free(rendezvous *);#endif/** * Creates a new rendezvous point with the given sender and receiver. Returns * a pointer to the rendezvous point, otherwise NULL if out of memory. */static rendezvous *rp_create(int sender, int receiver) { rendezvous *rp; rp = (rendezvous *)pcsl_mem_malloc(sizeof(rendezvous)); if (rp == NULL) { return NULL; } rp->state = IDLE; rp->retcode = OK; rp->refcount = 0; rp->msg = INVALID_REFERENCE_ID; rp->sender = sender; rp->receiver = receiver; return rp;}static voidrp_incref(rendezvous *rp){ rp->refcount += 1;}static voidrp_decref(rendezvous *rp){ rp->refcount -= 1; if (rp->refcount == 0) { if (rp->msg != INVALID_REFERENCE_ID) { /* IMPL_NOTE: really should be an assertion failure */ KNI_FatalError("rp_decref refcount 0 with stale refid!"); }#if ENABLE_I3_TEST log_rp_free(rp);#endif pcsl_mem_free(rp); }}/* * Checks refId for validity, gets its handle value, and stores it * into obj. An error message incorporating msg is emitted if refId is * invalid or if the handle returns is null. */static voidgetReference(int refId, char *msg, jobject obj){ if (refId == INVALID_REFERENCE_ID) { midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE, "invalid reference ID in %s", msg); REPORT_CRIT(LC_CORE, gKNIBuffer); KNI_ReleaseHandle(obj); } else { SNI_GetReference(refId, obj); if (KNI_IsNullHandle(obj)) { midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE, "null reference from SNI_GetReference in %s", msg); REPORT_CRIT(LC_CORE, gKNIBuffer); } }}static voidsetNativePointer(jobject linkObj, rendezvous *rp){ jfieldID nativePointerField; KNI_StartHandles(1); KNI_DeclareHandle(linkClass); KNI_GetObjectClass(linkObj, linkClass); nativePointerField = KNI_GetFieldID(linkClass, "nativePointer", "I"); KNI_SetIntField(linkObj, nativePointerField, (jint)rp); KNI_EndHandles();}static rendezvous *getNativePointer(jobject linkObj){ rendezvous *rp; jfieldID nativePointerField; KNI_StartHandles(1); KNI_DeclareHandle(linkClass); KNI_GetObjectClass(linkObj, linkClass); nativePointerField = KNI_GetFieldID(linkClass, "nativePointer", "I"); rp = (rendezvous *)KNI_GetIntField(linkObj, nativePointerField); KNI_EndHandles(); return rp;}static voidgetContents(jobject linkMessageObj, jobject contentsObj){ jfieldID contentsField; KNI_StartHandles(1); KNI_DeclareHandle(linkMessageClass); KNI_GetObjectClass(linkMessageObj, linkMessageClass); contentsField = KNI_GetFieldID(linkMessageClass, "contents", "Ljava/lang/Object;"); KNI_GetObjectField(linkMessageObj, contentsField, contentsObj); KNI_EndHandles();}static voidsetContents(jobject linkMessageObj, jobject contentsObj){ jfieldID contentsField; KNI_StartHandles(1); KNI_DeclareHandle(linkMessageClass); KNI_GetObjectClass(linkMessageObj, linkMessageClass); contentsField = KNI_GetFieldID(linkMessageClass, "contents", "Ljava/lang/Object;"); KNI_SetObjectField(linkMessageObj, contentsField, contentsObj); KNI_EndHandles();}static voidgetRange(jobject linkMessageObj, int *offset, int *length){ jfieldID offsetField; jfieldID lengthField; KNI_StartHandles(1); KNI_DeclareHandle(linkMessageClass); KNI_GetObjectClass(linkMessageObj, linkMessageClass); offsetField = KNI_GetFieldID(linkMessageClass, "offset", "I"); lengthField = KNI_GetFieldID(linkMessageClass, "length", "I"); *offset = KNI_GetIntField(linkMessageObj, offsetField); *length = KNI_GetIntField(linkMessageObj, lengthField); KNI_EndHandles();}static voidsetRange(jobject linkMessageObj, int offset, int length){ jfieldID offsetField; jfieldID lengthField; KNI_StartHandles(1); KNI_DeclareHandle(linkMessageClass); KNI_GetObjectClass(linkMessageObj, linkMessageClass); offsetField = KNI_GetFieldID(linkMessageClass, "offset", "I"); lengthField = KNI_GetFieldID(linkMessageClass, "length", "I"); KNI_SetIntField(linkMessageObj, offsetField, offset); KNI_SetIntField(linkMessageObj, lengthField, length); KNI_EndHandles();}/** * Copies the contents of fromMsg to the contents of toMsg. Both must be * instances of LinkMessage. The toLink object must be an instance of Link. * It's filled in if the contents of fromMsg are a Link. Returns KNI_TRUE if * successful, otherwise KNI_FALSE. */static jbooleancopy(jobject fromMsg, jobject toMsg, jobject toLink) { jboolean retval; KNI_StartHandles(6); KNI_DeclareHandle(byteArrayClass); KNI_DeclareHandle(stringClass); KNI_DeclareHandle(linkClass); KNI_DeclareHandle(fromContents); KNI_DeclareHandle(newString); KNI_DeclareHandle(newByteArray); KNI_FindClass("[B", byteArrayClass); KNI_FindClass("java/lang/String", stringClass); KNI_FindClass("com/sun/midp/links/Link", linkClass); getContents(fromMsg, fromContents); if (KNI_IsInstanceOf(fromContents, byteArrayClass)) { /* do a byte array copy */ jint fromOffset; jint fromLength; getRange(fromMsg, &fromOffset, &fromLength); SNI_NewArray(SNI_BYTE_ARRAY, fromLength, newByteArray); if (KNI_IsNullHandle(newByteArray)) { retval = KNI_FALSE; } else { KNI_GetRawArrayRegion(fromContents, fromOffset, fromLength, SNI_GetRawArrayPointer(newByteArray)); setContents(toMsg, newByteArray); setRange(toMsg, 0, fromLength); retval = KNI_TRUE; } } else if (KNI_IsInstanceOf(fromContents, stringClass)) { /* do a string copy */ jchar *buf; jsize slen = KNI_GetStringLength(fromContents); SNI_NewArray(SNI_BYTE_ARRAY, slen*sizeof(jchar), newByteArray); if (KNI_IsNullHandle(newByteArray)) { retval = KNI_FALSE; } else { buf = SNI_GetRawArrayPointer(newByteArray); KNI_GetStringRegion(fromContents, 0, slen, buf); KNI_NewString(buf, slen, newString); setContents(toMsg, newString); retval = KNI_TRUE; } } else if (KNI_IsInstanceOf(fromContents, linkClass)) { /* copy the link */ rendezvous *rp = getNativePointer(fromContents); setNativePointer(toLink, rp); rp_incref(rp); setContents(toMsg, toLink); retval = KNI_TRUE; } else { retval = KNI_FALSE; } KNI_EndHandles(); return retval;}/** * public native void close(); */KNIEXPORT KNI_RETURNTYPE_VOIDJava_com_sun_midp_links_Link_close(void){ rendezvous *rp; KNI_StartHandles(1); KNI_DeclareHandle(thisObj); KNI_GetThisPointer(thisObj); rp = getNativePointer(thisObj); /* ignore if closed twice */ if (rp != NULL) { if (rp->sender == JVM_CurrentIsolateID() && rp->msg != INVALID_REFERENCE_ID) { /* we're the sender, make sure to clean out our message */ SNI_DeleteReference(rp->msg); rp->msg = INVALID_REFERENCE_ID; } rp->state = CLOSED; midp_thread_signal(LINK_READY_SIGNAL, (int)rp, 0); setNativePointer(thisObj, NULL); rp_decref(rp); } KNI_EndHandles(); KNI_ReturnVoid();}/** * private native void finalize(); */KNIEXPORT KNI_RETURNTYPE_VOIDJava_com_sun_midp_links_Link_finalize(void){ Java_com_sun_midp_links_Link_close();}/** * private native void init0(int sender, int receiver); */KNIEXPORT KNI_RETURNTYPE_VOIDJava_com_sun_midp_links_Link_init0(void){ int sender; int receiver; rendezvous *rp; KNI_StartHandles(1); KNI_DeclareHandle(thisObj); sender = KNI_GetParameterAsInt(1); receiver = KNI_GetParameterAsInt(2); KNI_GetThisPointer(thisObj); rp = rp_create(sender, receiver); if (rp == NULL) { KNI_ThrowNew(midpOutOfMemoryError, NULL); } else { setNativePointer(thisObj, rp); rp_incref(rp); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?